From 39c3a11d9f65730baac527c5586799709aba9055 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Tue, 7 Dec 2021 21:38:09 +0100 Subject: [PATCH 001/199] first draft: does not export to correct path yet --- typescript/sharedLib/.gitignore | 2 ++ typescript/sharedLib/README.md | 27 +++++++++++++++++++ typescript/sharedLib/package-lock.json | 37 ++++++++++++++++++++++++++ typescript/sharedLib/package.json | 20 ++++++++++++++ typescript/sharedLib/src/app.ts | 2 ++ typescript/sharedLib/tsconfig.json | 8 ++++++ 6 files changed, 96 insertions(+) create mode 100644 typescript/sharedLib/.gitignore create mode 100644 typescript/sharedLib/README.md create mode 100644 typescript/sharedLib/package-lock.json create mode 100644 typescript/sharedLib/package.json create mode 100644 typescript/sharedLib/src/app.ts create mode 100644 typescript/sharedLib/tsconfig.json diff --git a/typescript/sharedLib/.gitignore b/typescript/sharedLib/.gitignore new file mode 100644 index 000000000..b2af6e004 --- /dev/null +++ b/typescript/sharedLib/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +!package-lock.json \ No newline at end of file diff --git a/typescript/sharedLib/README.md b/typescript/sharedLib/README.md new file mode 100644 index 000000000..78b07b332 --- /dev/null +++ b/typescript/sharedLib/README.md @@ -0,0 +1,27 @@ +# BangleTS + +A generic project setup for compiling apps from Typescript to Bangle.js ready, readable Javascript. +It includes types for *some* of the modules and globals that are exposed for apps to use. +The goal is to have types for everything, but that will take some time. Feel free to help out by contributing! + +## Using the types +TODO + +## Compilation + +Install [npm](https://www.npmjs.com/get-npm) if you haven't already. +Make sure you are using version ^8 by running `npm -v`. If the version is incorrect, run `npm i -g npm@^8`. + +After having installed npm for your platform, open a terminal, and navigate into the `/typescript/sharedLib` folder. Then run: + +``` +npm ci +``` + +to install the project's build tools, and: + +``` +npm run build:app pathToYourApp.ts +``` + +To build your app. The last command will generate the `app.js` file containing the transpiled code for the BangleJS. diff --git a/typescript/sharedLib/package-lock.json b/typescript/sharedLib/package-lock.json new file mode 100644 index 000000000..9df411a91 --- /dev/null +++ b/typescript/sharedLib/package-lock.json @@ -0,0 +1,37 @@ +{ + "name": "banglets", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "banglets", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "typescript": "^4.5.2" + } + }, + "node_modules/typescript": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + }, + "dependencies": { + "typescript": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", + "dev": true + } + } +} diff --git a/typescript/sharedLib/package.json b/typescript/sharedLib/package.json new file mode 100644 index 000000000..2bf45de2e --- /dev/null +++ b/typescript/sharedLib/package.json @@ -0,0 +1,20 @@ +{ + "name": "bangle.ts", + "version": "0.1.0", + "description": "Typescript configuration and typings for Bangle.js", + "main": "app.js", + "types": "app.d.ts", + "scripts": { + "build:testapp": "tsc src/app.ts", + "build:types": "tsc src/bangle.d.ts", + "build:app": "tsc" + }, + "author": { + "name": "Sebastian Di Luzio", + "email": "sebastian@diluz.io" + }, + "license": "MIT", + "devDependencies": { + "typescript": "^4.5.2" + } +} diff --git a/typescript/sharedLib/src/app.ts b/typescript/sharedLib/src/app.ts new file mode 100644 index 000000000..6e5739557 --- /dev/null +++ b/typescript/sharedLib/src/app.ts @@ -0,0 +1,2 @@ +const testString = 'test hehe'; +console.log(testString); diff --git a/typescript/sharedLib/tsconfig.json b/typescript/sharedLib/tsconfig.json new file mode 100644 index 000000000..42b34ec65 --- /dev/null +++ b/typescript/sharedLib/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "module": "es2015", + "noImplicitAny": true, + "target": "es2015", + "outDir": "../dist" + } +} From 3cd9c3952560dec0f7689de0cf2eb9302125afb6 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Tue, 7 Dec 2021 21:46:28 +0100 Subject: [PATCH 002/199] add build example to export to correct path --- typescript/sharedLib/README.md | 5 +++-- typescript/sharedLib/package.json | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/typescript/sharedLib/README.md b/typescript/sharedLib/README.md index 78b07b332..a54a4c75a 100644 --- a/typescript/sharedLib/README.md +++ b/typescript/sharedLib/README.md @@ -1,10 +1,11 @@ # BangleTS A generic project setup for compiling apps from Typescript to Bangle.js ready, readable Javascript. -It includes types for *some* of the modules and globals that are exposed for apps to use. +It includes types for _some_ of the modules and globals that are exposed for apps to use. The goal is to have types for everything, but that will take some time. Feel free to help out by contributing! ## Using the types + TODO ## Compilation @@ -21,7 +22,7 @@ npm ci to install the project's build tools, and: ``` -npm run build:app pathToYourApp.ts +npx tsc ./relativePathToYourApp/app.ts --outDir ./relativePathToYourApp/dist ``` To build your app. The last command will generate the `app.js` file containing the transpiled code for the BangleJS. diff --git a/typescript/sharedLib/package.json b/typescript/sharedLib/package.json index 2bf45de2e..814db8f3e 100644 --- a/typescript/sharedLib/package.json +++ b/typescript/sharedLib/package.json @@ -5,9 +5,8 @@ "main": "app.js", "types": "app.d.ts", "scripts": { - "build:testapp": "tsc src/app.ts", - "build:types": "tsc src/bangle.d.ts", - "build:app": "tsc" + "build:testapp": "tsc ./src/app.ts --outDir ./dist", + "build:types": "tsc ./src/bangle.d.ts" }, "author": { "name": "Sebastian Di Luzio", From 61cc93b0b6e461b25daa5225497466c00a099662 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Tue, 7 Dec 2021 22:27:09 +0100 Subject: [PATCH 003/199] prepare for using with widChargingStatus global types are not yet received correctly, but we're close! - use widChargerStatus as first example to make setup work - add github action to compile supplied types/globals on pushes --- .github/workflows/nodejs.yml | 25 +++ .../{widget.js => widget.ts} | 0 typescript/{sharedLib => }/.gitignore | 0 typescript/{sharedLib => }/README.md | 0 typescript/globals.d.ts | 145 ++++++++++++++++++ typescript/{sharedLib => }/package-lock.json | 0 typescript/{sharedLib => }/package.json | 4 +- typescript/sharedLib/src/app.ts | 2 - typescript/{sharedLib => }/tsconfig.json | 6 +- 9 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/nodejs.yml rename apps/widChargingStatus/{widget.js => widget.ts} (100%) rename typescript/{sharedLib => }/.gitignore (100%) rename typescript/{sharedLib => }/README.md (100%) create mode 100644 typescript/globals.d.ts rename typescript/{sharedLib => }/package-lock.json (100%) rename typescript/{sharedLib => }/package.json (70%) delete mode 100644 typescript/sharedLib/src/app.ts rename typescript/{sharedLib => }/tsconfig.json (52%) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 000000000..9503d8934 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,25 @@ +name: Node CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x] + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: go to typescript directory + run: cd typescript + - name: npm ci + run: npm ci + - name: build types + run: npm run build:types \ No newline at end of file diff --git a/apps/widChargingStatus/widget.js b/apps/widChargingStatus/widget.ts similarity index 100% rename from apps/widChargingStatus/widget.js rename to apps/widChargingStatus/widget.ts diff --git a/typescript/sharedLib/.gitignore b/typescript/.gitignore similarity index 100% rename from typescript/sharedLib/.gitignore rename to typescript/.gitignore diff --git a/typescript/sharedLib/README.md b/typescript/README.md similarity index 100% rename from typescript/sharedLib/README.md rename to typescript/README.md diff --git a/typescript/globals.d.ts b/typescript/globals.d.ts new file mode 100644 index 000000000..702ef26cb --- /dev/null +++ b/typescript/globals.d.ts @@ -0,0 +1,145 @@ +// TODO all of these globals (copied from eslintrc need to be typed at some point) +/* "globals": { + // Methods and Fields at https://banglejs.com/reference + "Array": "readonly", + "ArrayBuffer": "readonly", + "ArrayBufferView": "readonly", + "Bangle": "readonly", + "BluetoothDevice": "readonly", + "BluetoothRemoteGATTCharacteristic": "readonly", + "BluetoothRemoteGATTServer": "readonly", + "BluetoothRemoteGATTService": "readonly", + "Boolean": "readonly", + "console": "readonly", + "DataView": "readonly", + "Date": "readonly", + "E": "readonly", + "Error": "readonly", + "Flash": "readonly", + "Float32Array": "readonly", + "Float64Array": "readonly", + "fs": "readonly", + "Function": "readonly", + "Graphics": "readonly", + "heatshrink": "readonly", + "I2C": "readonly", + "Int16Array": "readonly", + "Int32Array": "readonly", + "Int8Array": "readonly", + "InternalError": "readonly", + "JSON": "readonly", + "Math": "readonly", + "Modules": "readonly", + "NRF": "readonly", + "Number": "readonly", + "Object": "readonly", + "OneWire": "readonly", + "Pin": "readonly", + "process": "readonly", + "Promise": "readonly", + "ReferenceError": "readonly", + "RegExp": "readonly", + "Serial": "readonly", + "SPI": "readonly", + "Storage": "readonly", + "StorageFile": "readonly", + "String": "readonly", + "SyntaxError": "readonly", + "tensorflow": "readonly", + "TFMicroInterpreter": "readonly", + "TypeError": "readonly", + "Uint16Array": "readonly", + "Uint24Array": "readonly", + "Uint32Array": "readonly", + "Uint8Array": "readonly", + "Uint8ClampedArray": "readonly", + "Waveform": "readonly", + // Methods and Fields at https://banglejs.com/reference + "analogRead": "readonly", + "analogWrite": "readonly", + "arguments": "readonly", + "atob": "readonly", + "Bluetooth": "readonly", + "BTN": "readonly", + "BTN1": "readonly", + "BTN2": "readonly", + "BTN3": "readonly", + "BTN4": "readonly", + "BTN5": "readonly", + "btoa": "readonly", + "changeInterval": "readonly", + "clearInterval": "readonly", + "clearTimeout": "readonly", + "clearWatch": "readonly", + "decodeURIComponent": "readonly", + "digitalPulse": "readonly", + "digitalRead": "readonly", + "digitalWrite": "readonly", + "dump": "readonly", + "echo": "readonly", + "edit": "readonly", + "encodeURIComponent": "readonly", + "eval": "readonly", + "getPinMode": "readonly", + "getSerial": "readonly", + "getTime": "readonly", + "global": "readonly", + "HIGH": "readonly", + "I2C1": "readonly", + "Infinity": "readonly", + "isFinite": "readonly", + "isNaN": "readonly", + "LED": "readonly", + "LED1": "readonly", + "LED2": "readonly", + "load": "readonly", + "LoopbackA": "readonly", + "LoopbackB": "readonly", + "LOW": "readonly", + "NaN": "readonly", + "parseFloat": "readonly", + "parseInt": "readonly", + "peek16": "readonly", + "peek32": "readonly", + "peek8": "readonly", + "pinMode": "readonly", + "poke16": "readonly", + "poke32": "readonly", + "poke8": "readonly", + "print": "readonly", + "require": "readonly", + "reset": "readonly", + "save": "readonly", + "Serial1": "readonly", + "setBusyIndicator": "readonly", + "setInterval": "readonly", + "setSleepIndicator": "readonly", + "setTime": "readonly", + "setTimeout": "readonly", + "setWatch": "readonly", + "shiftOut": "readonly", + "SPI1": "readonly", + "Terminal": "readonly", + "trace": "readonly", + "VIBRATE": "readonly", + // Aliases and not defined at https://banglejs.com/reference + "g": "readonly", + */ + +declare const Bangle: { + // functions + buzz: () => void; + drawWidgets: () => void; + isCharging: () => boolean; + // events + on(event: 'charging', listener: (charging: boolean) => void): void; + // TODO add more +}; + +type Widget = { + area: 'tr' | 'tl'; + width: number; + draw: () => void; +}; + +declare const WIDGETS: { [key: string]: Widget }; diff --git a/typescript/sharedLib/package-lock.json b/typescript/package-lock.json similarity index 100% rename from typescript/sharedLib/package-lock.json rename to typescript/package-lock.json diff --git a/typescript/sharedLib/package.json b/typescript/package.json similarity index 70% rename from typescript/sharedLib/package.json rename to typescript/package.json index 814db8f3e..513e7b7df 100644 --- a/typescript/sharedLib/package.json +++ b/typescript/package.json @@ -5,8 +5,8 @@ "main": "app.js", "types": "app.d.ts", "scripts": { - "build:testapp": "tsc ./src/app.ts --outDir ./dist", - "build:types": "tsc ./src/bangle.d.ts" + "build:example": "tsc ../apps/widChargingStatus/widget.ts --outDir ../apps/widChargingStatus/dist", + "build:types": "tsc ./globals.d.ts" }, "author": { "name": "Sebastian Di Luzio", diff --git a/typescript/sharedLib/src/app.ts b/typescript/sharedLib/src/app.ts deleted file mode 100644 index 6e5739557..000000000 --- a/typescript/sharedLib/src/app.ts +++ /dev/null @@ -1,2 +0,0 @@ -const testString = 'test hehe'; -console.log(testString); diff --git a/typescript/sharedLib/tsconfig.json b/typescript/tsconfig.json similarity index 52% rename from typescript/sharedLib/tsconfig.json rename to typescript/tsconfig.json index 42b34ec65..ce8e6278b 100644 --- a/typescript/sharedLib/tsconfig.json +++ b/typescript/tsconfig.json @@ -3,6 +3,8 @@ "module": "es2015", "noImplicitAny": true, "target": "es2015", - "outDir": "../dist" - } + "outDir": "../dist", + "isolatedModules": false + }, + "include": ["./globals.d.ts"] } From 63b26f5d1ffeb069c373d94eb9a9705004a1c1c1 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Wed, 8 Dec 2021 20:22:39 +0100 Subject: [PATCH 004/199] move dev dependencies to main package.json, get first compiling version of test widget - i still want to be able to get the types ambiently defined without any weird import needed - it would be nice to be able to have a separate package.json in ./typescirpt. not sure if it's possible, I would move working on that part to the end --- apps.json | 2 +- apps/widChargingStatus/dist/widget.js | 31 +++++++++++ apps/widChargingStatus/widget.ts | 60 +++++++++++---------- package.json | 8 ++- tsconfig.json | 7 +++ typescript/.gitignore | 2 - typescript/package-lock.json | 37 ------------- typescript/package.json | 19 ------- typescript/tsconfig.json | 10 ---- typescript/{ => types}/globals.d.ts | 77 ++++++++++++++++----------- 10 files changed, 124 insertions(+), 129 deletions(-) create mode 100644 apps/widChargingStatus/dist/widget.js create mode 100644 tsconfig.json delete mode 100644 typescript/.gitignore delete mode 100644 typescript/package-lock.json delete mode 100644 typescript/package.json delete mode 100644 typescript/tsconfig.json rename typescript/{ => types}/globals.d.ts (75%) diff --git a/apps.json b/apps.json index 13bb5892d..58a67d8c2 100644 --- a/apps.json +++ b/apps.json @@ -4763,7 +4763,7 @@ "tags": "widget", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"widChargingStatus.wid.js","url":"widget.js"} + {"name":"widChargingStatus.wid.js","url":"./dist/widget.js"} ] }, { diff --git a/apps/widChargingStatus/dist/widget.js b/apps/widChargingStatus/dist/widget.js new file mode 100644 index 000000000..7772a5b87 --- /dev/null +++ b/apps/widChargingStatus/dist/widget.js @@ -0,0 +1,31 @@ +"use strict"; +exports.__esModule = true; +(function () { + var icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); + var iconWidth = 18; + function draw() { + g.reset(); + if (Bangle.isCharging()) { + g.setColor('#FD0'); + g.drawImage(icon, this.x + 1, this.y + 1, { + scale: 0.6875 + }); + } + } + WIDGETS.chargingStatus = { + area: 'tr', + width: Bangle.isCharging() ? iconWidth : 0, + draw: draw + }; + Bangle.on('charging', function (charging) { + if (charging) { + Bangle.buzz(); + WIDGETS.chargingStatus.width = iconWidth; + } + else { + WIDGETS.chargingStatus.width = 0; + } + Bangle.drawWidgets(); // re-layout widgets + g.flip(); + }); +})(); diff --git a/apps/widChargingStatus/widget.ts b/apps/widChargingStatus/widget.ts index 90f9199fa..e3ce2d7e2 100644 --- a/apps/widChargingStatus/widget.ts +++ b/apps/widChargingStatus/widget.ts @@ -1,31 +1,37 @@ +import { loadGlobals } from '../../typescript/types/globals'; // TODO find a nicer way to load ambient type definitions than this + (() => { - const icon = require("heatshrink").decompress(atob("ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA")); - const iconWidth = 18; + const icon = require('heatshrink').decompress( + atob( + 'ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA' + ) + ); + const iconWidth = 18; - function draw() { - g.reset(); - if (Bangle.isCharging()) { - g.setColor("#FD0"); - g.drawImage(icon, this.x + 1, this.y + 1, { - scale: 0.6875 - }); - } - } + function draw() { + g.reset(); + if (Bangle.isCharging()) { + g.setColor('#FD0'); + g.drawImage(icon, this.x + 1, this.y + 1, { + scale: 0.6875, + }); + } + } - WIDGETS.chargingStatus = { - area: 'tr', - width: Bangle.isCharging() ? iconWidth : 0, - draw: draw, - }; + WIDGETS.chargingStatus = { + area: 'tr', + width: Bangle.isCharging() ? iconWidth : 0, + draw: draw, + }; - Bangle.on('charging', (charging) => { - if (charging) { - Bangle.buzz(); - WIDGETS.chargingStatus.width = iconWidth; - } else { - WIDGETS.chargingStatus.width = 0; - } - Bangle.drawWidgets(); // re-layout widgets - g.flip(); - }); -})(); \ No newline at end of file + Bangle.on('charging', (charging) => { + if (charging) { + Bangle.buzz(); + WIDGETS.chargingStatus.width = iconWidth; + } else { + WIDGETS.chargingStatus.width = 0; + } + Bangle.drawWidgets(); // re-layout widgets + g.flip(); + }); +})(); diff --git a/package.json b/package.json index b796044c9..1ecfb6280 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,16 @@ "author": "Gordon Williams (http://espruino.com)", "version": "0.0.1", "devDependencies": { - "eslint": "7.1.0" + "eslint": "7.1.0", + "@types/node": "16.11.12", + "typescript": "4.5.2" }, "scripts": { "lint-apps": "eslint ./apps --ext .js", "test": "node bin/sanitycheck.js && eslint ./apps --ext .js", - "start": "npx http-server -c-1" + "start": "npx http-server -c-1", + "build:example": "tsc ./apps/widChargingStatus/widget.ts --outDir ./apps/widChargingStatus/dist", + "build:types": "tsc .typescript/types/globals.d.ts" }, "dependencies": { "acorn": "^7.2.0" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..46a557e89 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "module": "es2015", + "noImplicitAny": true, + "target": "es2015" + } +} diff --git a/typescript/.gitignore b/typescript/.gitignore deleted file mode 100644 index b2af6e004..000000000 --- a/typescript/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -!package-lock.json \ No newline at end of file diff --git a/typescript/package-lock.json b/typescript/package-lock.json deleted file mode 100644 index 9df411a91..000000000 --- a/typescript/package-lock.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "banglets", - "version": "0.1.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "banglets", - "version": "0.1.0", - "license": "MIT", - "devDependencies": { - "typescript": "^4.5.2" - } - }, - "node_modules/typescript": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", - "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - } - }, - "dependencies": { - "typescript": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", - "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", - "dev": true - } - } -} diff --git a/typescript/package.json b/typescript/package.json deleted file mode 100644 index 513e7b7df..000000000 --- a/typescript/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "bangle.ts", - "version": "0.1.0", - "description": "Typescript configuration and typings for Bangle.js", - "main": "app.js", - "types": "app.d.ts", - "scripts": { - "build:example": "tsc ../apps/widChargingStatus/widget.ts --outDir ../apps/widChargingStatus/dist", - "build:types": "tsc ./globals.d.ts" - }, - "author": { - "name": "Sebastian Di Luzio", - "email": "sebastian@diluz.io" - }, - "license": "MIT", - "devDependencies": { - "typescript": "^4.5.2" - } -} diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json deleted file mode 100644 index ce8e6278b..000000000 --- a/typescript/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "module": "es2015", - "noImplicitAny": true, - "target": "es2015", - "outDir": "../dist", - "isolatedModules": false - }, - "include": ["./globals.d.ts"] -} diff --git a/typescript/globals.d.ts b/typescript/types/globals.d.ts similarity index 75% rename from typescript/globals.d.ts rename to typescript/types/globals.d.ts index 702ef26cb..97a40ae54 100644 --- a/typescript/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -1,33 +1,19 @@ // TODO all of these globals (copied from eslintrc need to be typed at some point) /* "globals": { // Methods and Fields at https://banglejs.com/reference - "Array": "readonly", - "ArrayBuffer": "readonly", - "ArrayBufferView": "readonly", - "Bangle": "readonly", "BluetoothDevice": "readonly", "BluetoothRemoteGATTCharacteristic": "readonly", "BluetoothRemoteGATTServer": "readonly", "BluetoothRemoteGATTService": "readonly", - "Boolean": "readonly", - "console": "readonly", "DataView": "readonly", - "Date": "readonly", "E": "readonly", "Error": "readonly", "Flash": "readonly", - "Float32Array": "readonly", - "Float64Array": "readonly", "fs": "readonly", "Function": "readonly", - "Graphics": "readonly", "heatshrink": "readonly", "I2C": "readonly", - "Int16Array": "readonly", - "Int32Array": "readonly", - "Int8Array": "readonly", "InternalError": "readonly", - "JSON": "readonly", "Math": "readonly", "Modules": "readonly", "NRF": "readonly", @@ -122,24 +108,53 @@ "Terminal": "readonly", "trace": "readonly", "VIBRATE": "readonly", - // Aliases and not defined at https://banglejs.com/reference - "g": "readonly", */ -declare const Bangle: { - // functions - buzz: () => void; - drawWidgets: () => void; - isCharging: () => boolean; - // events - on(event: 'charging', listener: (charging: boolean) => void): void; - // TODO add more -}; +export type loadGlobals = {}; -type Widget = { - area: 'tr' | 'tl'; - width: number; - draw: () => void; -}; +declare global { + const Bangle: { + // functions + buzz: () => void; + drawWidgets: () => void; + isCharging: () => boolean; + // events + on(event: 'charging', listener: (charging: boolean) => void): void; + // TODO add more + }; -declare const WIDGETS: { [key: string]: Widget }; + type Image = { + width: number; + height: number; + bpp?: number; + buffer: ArrayBuffer | string; + transparent?: number; + palette?: Uint16Array; + }; + + type GraphicsApi = { + reset: () => void; + flip: () => void; + setColor: (color: string) => void; // TODO we can most likely type color more usefully than this + drawImage: ( + image: string | Image | ArrayBuffer, + xOffset: number, + yOffset: number, + options?: { + rotate?: number; + scale?: number; + } + ) => void; + // TODO add more + }; + + const Graphics: GraphicsApi; + const g: GraphicsApi; + + type Widget = { + area: 'tr' | 'tl'; + width: number; + draw: () => void; + }; + const WIDGETS: { [key: string]: Widget }; +} From d46736c01a4fa85888e78a8c8814ddcd26384908 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Wed, 8 Dec 2021 20:23:14 +0100 Subject: [PATCH 005/199] adjust github actions --- .github/workflows/nodejs.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 9503d8934..e2a12cc51 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -4,7 +4,6 @@ on: [push] jobs: build: - runs-on: ubuntu-latest strategy: @@ -12,14 +11,12 @@ jobs: node-version: [16.x] steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: go to typescript directory - run: cd typescript - - name: npm ci - run: npm ci - - name: build types - run: npm run build:types \ No newline at end of file + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: npm i + run: npm i + - name: build types + run: npm run build:types From 0a2426a6dd9add940909a552663eb0b25ce86ade Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Wed, 8 Dec 2021 20:24:11 +0100 Subject: [PATCH 006/199] fix type build script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ecfb6280..f6426e7e2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "node bin/sanitycheck.js && eslint ./apps --ext .js", "start": "npx http-server -c-1", "build:example": "tsc ./apps/widChargingStatus/widget.ts --outDir ./apps/widChargingStatus/dist", - "build:types": "tsc .typescript/types/globals.d.ts" + "build:types": "tsc ./typescript/types/globals.d.ts" }, "dependencies": { "acorn": "^7.2.0" From 83d445c1a28c7257cfd09b819a0b949ce439507e Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 20:52:17 +0100 Subject: [PATCH 007/199] move package back within typescript --- package.json | 8 +--- typescript/.gitignore | 2 + typescript/README.md | 4 +- typescript/package-lock.json | 49 +++++++++++++++++++++++ typescript/package.json | 14 +++++++ tsconfig.json => typescript/tsconfig.json | 0 6 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 typescript/.gitignore create mode 100644 typescript/package-lock.json create mode 100644 typescript/package.json rename tsconfig.json => typescript/tsconfig.json (100%) diff --git a/package.json b/package.json index f6426e7e2..b796044c9 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,12 @@ "author": "Gordon Williams (http://espruino.com)", "version": "0.0.1", "devDependencies": { - "eslint": "7.1.0", - "@types/node": "16.11.12", - "typescript": "4.5.2" + "eslint": "7.1.0" }, "scripts": { "lint-apps": "eslint ./apps --ext .js", "test": "node bin/sanitycheck.js && eslint ./apps --ext .js", - "start": "npx http-server -c-1", - "build:example": "tsc ./apps/widChargingStatus/widget.ts --outDir ./apps/widChargingStatus/dist", - "build:types": "tsc ./typescript/types/globals.d.ts" + "start": "npx http-server -c-1" }, "dependencies": { "acorn": "^7.2.0" diff --git a/typescript/.gitignore b/typescript/.gitignore new file mode 100644 index 000000000..630f61ee5 --- /dev/null +++ b/typescript/.gitignore @@ -0,0 +1,2 @@ +./node_modules +!package-lock.json diff --git a/typescript/README.md b/typescript/README.md index a54a4c75a..9b38459ae 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -13,7 +13,7 @@ TODO Install [npm](https://www.npmjs.com/get-npm) if you haven't already. Make sure you are using version ^8 by running `npm -v`. If the version is incorrect, run `npm i -g npm@^8`. -After having installed npm for your platform, open a terminal, and navigate into the `/typescript/sharedLib` folder. Then run: +After having installed npm for your platform, open a terminal, and navigate into the `/typescript` folder. Then run: ``` npm ci @@ -22,7 +22,7 @@ npm ci to install the project's build tools, and: ``` -npx tsc ./relativePathToYourApp/app.ts --outDir ./relativePathToYourApp/dist +npx tsc ../apps/relativePathToYourApp/app.ts --outDir ../apps/relativePathToYourApp/dist ``` To build your app. The last command will generate the `app.js` file containing the transpiled code for the BangleJS. diff --git a/typescript/package-lock.json b/typescript/package-lock.json new file mode 100644 index 000000000..bd3cfc702 --- /dev/null +++ b/typescript/package-lock.json @@ -0,0 +1,49 @@ +{ + "name": "Bangle.ts", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "Bangle.ts", + "version": "0.0.1", + "devDependencies": { + "@types/node": "16.11.12", + "typescript": "4.5.2" + } + }, + "node_modules/@types/node": { + "version": "16.11.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", + "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + }, + "dependencies": { + "@types/node": { + "version": "16.11.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", + "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", + "dev": true + }, + "typescript": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", + "dev": true + } + } +} diff --git a/typescript/package.json b/typescript/package.json new file mode 100644 index 000000000..03f435497 --- /dev/null +++ b/typescript/package.json @@ -0,0 +1,14 @@ +{ + "name": "Bangle.ts", + "description": "Bangle.js Typescript Project Setup and Types", + "author": "Sebastian Di Luzio (https://diluz.io)", + "version": "0.0.1", + "devDependencies": { + "@types/node": "16.11.12", + "typescript": "4.5.2" + }, + "scripts": { + "build:example": "tsc ../apps/widChargingStatus/widget.ts --outDir ../apps/widChargingStatus/dist", + "build:types": "tsc ./types/globals.d.ts" + } +} diff --git a/tsconfig.json b/typescript/tsconfig.json similarity index 100% rename from tsconfig.json rename to typescript/tsconfig.json From 45bd654eca724a8cb15cddf1eab883978c38bd87 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 21:19:01 +0100 Subject: [PATCH 008/199] fix global vars inside IDE (only cli to go) --- apps/widChargingStatus/dist/widget.js | 2 - apps/widChargingStatus/widget.ts | 2 - typescript/package-lock.json | 13 - typescript/package.json | 1 - typescript/tsconfig.json | 3 +- typescript/types/globals.d.ts | 327 ++++++++++++++------------ 6 files changed, 177 insertions(+), 171 deletions(-) diff --git a/apps/widChargingStatus/dist/widget.js b/apps/widChargingStatus/dist/widget.js index 7772a5b87..eea96ce58 100644 --- a/apps/widChargingStatus/dist/widget.js +++ b/apps/widChargingStatus/dist/widget.js @@ -1,5 +1,3 @@ -"use strict"; -exports.__esModule = true; (function () { var icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); var iconWidth = 18; diff --git a/apps/widChargingStatus/widget.ts b/apps/widChargingStatus/widget.ts index e3ce2d7e2..a8cf2ed94 100644 --- a/apps/widChargingStatus/widget.ts +++ b/apps/widChargingStatus/widget.ts @@ -1,5 +1,3 @@ -import { loadGlobals } from '../../typescript/types/globals'; // TODO find a nicer way to load ambient type definitions than this - (() => { const icon = require('heatshrink').decompress( atob( diff --git a/typescript/package-lock.json b/typescript/package-lock.json index bd3cfc702..52be5f98a 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -8,16 +8,9 @@ "name": "Bangle.ts", "version": "0.0.1", "devDependencies": { - "@types/node": "16.11.12", "typescript": "4.5.2" } }, - "node_modules/@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true - }, "node_modules/typescript": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", @@ -33,12 +26,6 @@ } }, "dependencies": { - "@types/node": { - "version": "16.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", - "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==", - "dev": true - }, "typescript": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", diff --git a/typescript/package.json b/typescript/package.json index 03f435497..83ea7d82b 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -4,7 +4,6 @@ "author": "Sebastian Di Luzio (https://diluz.io)", "version": "0.0.1", "devDependencies": { - "@types/node": "16.11.12", "typescript": "4.5.2" }, "scripts": { diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 46a557e89..8a7ab3342 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -3,5 +3,6 @@ "module": "es2015", "noImplicitAny": true, "target": "es2015" - } + }, + "include": ["../apps/**/*", "./**/*"] } diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 97a40ae54..359d5d294 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -1,160 +1,183 @@ // TODO all of these globals (copied from eslintrc need to be typed at some point) -/* "globals": { - // Methods and Fields at https://banglejs.com/reference - "BluetoothDevice": "readonly", - "BluetoothRemoteGATTCharacteristic": "readonly", - "BluetoothRemoteGATTServer": "readonly", - "BluetoothRemoteGATTService": "readonly", - "DataView": "readonly", - "E": "readonly", - "Error": "readonly", - "Flash": "readonly", - "fs": "readonly", - "Function": "readonly", - "heatshrink": "readonly", - "I2C": "readonly", - "InternalError": "readonly", - "Math": "readonly", - "Modules": "readonly", - "NRF": "readonly", - "Number": "readonly", - "Object": "readonly", - "OneWire": "readonly", - "Pin": "readonly", - "process": "readonly", - "Promise": "readonly", - "ReferenceError": "readonly", - "RegExp": "readonly", - "Serial": "readonly", - "SPI": "readonly", - "Storage": "readonly", - "StorageFile": "readonly", - "String": "readonly", - "SyntaxError": "readonly", - "tensorflow": "readonly", - "TFMicroInterpreter": "readonly", - "TypeError": "readonly", - "Uint16Array": "readonly", - "Uint24Array": "readonly", - "Uint32Array": "readonly", - "Uint8Array": "readonly", - "Uint8ClampedArray": "readonly", - "Waveform": "readonly", - // Methods and Fields at https://banglejs.com/reference - "analogRead": "readonly", - "analogWrite": "readonly", - "arguments": "readonly", - "atob": "readonly", - "Bluetooth": "readonly", - "BTN": "readonly", - "BTN1": "readonly", - "BTN2": "readonly", - "BTN3": "readonly", - "BTN4": "readonly", - "BTN5": "readonly", - "btoa": "readonly", - "changeInterval": "readonly", - "clearInterval": "readonly", - "clearTimeout": "readonly", - "clearWatch": "readonly", - "decodeURIComponent": "readonly", - "digitalPulse": "readonly", - "digitalRead": "readonly", - "digitalWrite": "readonly", - "dump": "readonly", - "echo": "readonly", - "edit": "readonly", - "encodeURIComponent": "readonly", - "eval": "readonly", - "getPinMode": "readonly", - "getSerial": "readonly", - "getTime": "readonly", - "global": "readonly", - "HIGH": "readonly", - "I2C1": "readonly", - "Infinity": "readonly", - "isFinite": "readonly", - "isNaN": "readonly", - "LED": "readonly", - "LED1": "readonly", - "LED2": "readonly", - "load": "readonly", - "LoopbackA": "readonly", - "LoopbackB": "readonly", - "LOW": "readonly", - "NaN": "readonly", - "parseFloat": "readonly", - "parseInt": "readonly", - "peek16": "readonly", - "peek32": "readonly", - "peek8": "readonly", - "pinMode": "readonly", - "poke16": "readonly", - "poke32": "readonly", - "poke8": "readonly", - "print": "readonly", - "require": "readonly", - "reset": "readonly", - "save": "readonly", - "Serial1": "readonly", - "setBusyIndicator": "readonly", - "setInterval": "readonly", - "setSleepIndicator": "readonly", - "setTime": "readonly", - "setTimeout": "readonly", - "setWatch": "readonly", - "shiftOut": "readonly", - "SPI1": "readonly", - "Terminal": "readonly", - "trace": "readonly", - "VIBRATE": "readonly", +/* { + // Methods and Fields at https://banglejs.com/reference + "Array": "readonly", + "ArrayBuffer": "readonly", + "ArrayBufferView": "readonly", + "Bangle": "readonly", + "BluetoothDevice": "readonly", + "BluetoothRemoteGATTCharacteristic": "readonly", + "BluetoothRemoteGATTServer": "readonly", + "BluetoothRemoteGATTService": "readonly", + "Boolean": "readonly", + "console": "readonly", + "DataView": "readonly", + "Date": "readonly", + "E": "readonly", + "Error": "readonly", + "Flash": "readonly", + "Float32Array": "readonly", + "Float64Array": "readonly", + "fs": "readonly", + "Function": "readonly", + "Graphics": "readonly", // partly done + "heatshrink": "readonly", + "I2C": "readonly", + "Int16Array": "readonly", + "Int32Array": "readonly", + "Int8Array": "readonly", + "InternalError": "readonly", + "JSON": "readonly", + "Math": "readonly", + "Modules": "readonly", + "NRF": "readonly", + "Number": "readonly", + "Object": "readonly", + "OneWire": "readonly", + "Pin": "readonly", + "process": "readonly", + "Promise": "readonly", + "ReferenceError": "readonly", + "RegExp": "readonly", + "Serial": "readonly", + "SPI": "readonly", + "Storage": "readonly", + "StorageFile": "readonly", + "String": "readonly", + "SyntaxError": "readonly", + "tensorflow": "readonly", + "TFMicroInterpreter": "readonly", + "TypeError": "readonly", + "Uint16Array": "readonly", + "Uint24Array": "readonly", + "Uint32Array": "readonly", + "Uint8Array": "readonly", + "Uint8ClampedArray": "readonly", + "Waveform": "readonly", + // Methods and Fields at https://banglejs.com/reference + "analogRead": "readonly", + "analogWrite": "readonly", + "arguments": "readonly", + "atob": "readonly", + "Bluetooth": "readonly", + "BTN": "readonly", + "BTN1": "readonly", + "BTN2": "readonly", + "BTN3": "readonly", + "BTN4": "readonly", + "BTN5": "readonly", + "btoa": "readonly", + "changeInterval": "readonly", + "clearInterval": "readonly", + "clearTimeout": "readonly", + "clearWatch": "readonly", + "decodeURIComponent": "readonly", + "digitalPulse": "readonly", + "digitalRead": "readonly", + "digitalWrite": "readonly", + "dump": "readonly", + "echo": "readonly", + "edit": "readonly", + "encodeURIComponent": "readonly", + "eval": "readonly", + "getPinMode": "readonly", + "getSerial": "readonly", + "getTime": "readonly", + "global": "readonly", + "HIGH": "readonly", + "I2C1": "readonly", + "Infinity": "readonly", + "isFinite": "readonly", + "isNaN": "readonly", + "LED": "readonly", + "LED1": "readonly", + "LED2": "readonly", + "load": "readonly", + "LoopbackA": "readonly", + "LoopbackB": "readonly", + "LOW": "readonly", + "NaN": "readonly", + "parseFloat": "readonly", + "parseInt": "readonly", + "peek16": "readonly", + "peek32": "readonly", + "peek8": "readonly", + "pinMode": "readonly", + "poke16": "readonly", + "poke32": "readonly", + "poke8": "readonly", + "print": "readonly", + "require": "readonly", + "reset": "readonly", + "save": "readonly", + "Serial1": "readonly", + "setBusyIndicator": "readonly", + "setInterval": "readonly", + "setSleepIndicator": "readonly", + "setTime": "readonly", + "setTimeout": "readonly", + "setWatch": "readonly", + "shiftOut": "readonly", + "SPI1": "readonly", + "Terminal": "readonly", + "trace": "readonly", + "VIBRATE": "readonly", + // Aliases and not defined at https://banglejs.com/reference + "g": "readonly", // done + "WIDGETS": "readonly" // done + } */ -export type loadGlobals = {}; +// ambient JS definitions -declare global { - const Bangle: { - // functions - buzz: () => void; - drawWidgets: () => void; - isCharging: () => boolean; - // events - on(event: 'charging', listener: (charging: boolean) => void): void; - // TODO add more - }; +declare const require: ((module: 'heatshrink') => { + decompress: (compressedString: string) => string; +}) & // TODO add more + ((module: 'otherString') => {}); - type Image = { - width: number; - height: number; - bpp?: number; - buffer: ArrayBuffer | string; - transparent?: number; - palette?: Uint16Array; - }; +// ambient bangle.js definitions - type GraphicsApi = { - reset: () => void; - flip: () => void; - setColor: (color: string) => void; // TODO we can most likely type color more usefully than this - drawImage: ( - image: string | Image | ArrayBuffer, - xOffset: number, - yOffset: number, - options?: { - rotate?: number; - scale?: number; - } - ) => void; - // TODO add more - }; +declare const Bangle: { + // functions + buzz: () => void; + drawWidgets: () => void; + isCharging: () => boolean; + // events + on(event: 'charging', listener: (charging: boolean) => void): void; + // TODO add more +}; - const Graphics: GraphicsApi; - const g: GraphicsApi; +declare type Image = { + width: number; + height: number; + bpp?: number; + buffer: ArrayBuffer | string; + transparent?: number; + palette?: Uint16Array; +}; - type Widget = { - area: 'tr' | 'tl'; - width: number; - draw: () => void; - }; - const WIDGETS: { [key: string]: Widget }; -} +declare type GraphicsApi = { + reset: () => void; + flip: () => void; + setColor: (color: string) => void; // TODO we can most likely type color more usefully than this + drawImage: ( + image: string | Image | ArrayBuffer, + xOffset: number, + yOffset: number, + options?: { + rotate?: number; + scale?: number; + } + ) => void; + // TODO add more +}; + +declare const Graphics: GraphicsApi; +declare const g: GraphicsApi; + +declare type Widget = { + area: 'tr' | 'tl'; + width: number; + draw: () => void; +}; +declare const WIDGETS: { [key: string]: Widget }; From 15d24ac1b3f5a1412adda885b116894d47c749a2 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 21:36:42 +0100 Subject: [PATCH 009/199] update TS rules to make them stricter --- apps/widChargingStatus/dist/widget.js | 19 +++++++++++-------- apps/widChargingStatus/widget.ts | 21 ++++++++++++--------- typescript/tsconfig.json | 11 ++++++++++- typescript/types/globals.d.ts | 2 +- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/apps/widChargingStatus/dist/widget.js b/apps/widChargingStatus/dist/widget.js index eea96ce58..6cac1931f 100644 --- a/apps/widChargingStatus/dist/widget.js +++ b/apps/widChargingStatus/dist/widget.js @@ -16,14 +16,17 @@ draw: draw }; Bangle.on('charging', function (charging) { - if (charging) { - Bangle.buzz(); - WIDGETS.chargingStatus.width = iconWidth; + var widget = WIDGETS.chargingStatus; + if (widget) { + if (charging) { + Bangle.buzz(); + widget.width = iconWidth; + } + else { + widget.width = 0; + } + Bangle.drawWidgets(); // re-layout widgets + g.flip(); } - else { - WIDGETS.chargingStatus.width = 0; - } - Bangle.drawWidgets(); // re-layout widgets - g.flip(); }); })(); diff --git a/apps/widChargingStatus/widget.ts b/apps/widChargingStatus/widget.ts index a8cf2ed94..712bf4f97 100644 --- a/apps/widChargingStatus/widget.ts +++ b/apps/widChargingStatus/widget.ts @@ -6,7 +6,7 @@ ); const iconWidth = 18; - function draw() { + function draw(this: { x: number; y: number }) { g.reset(); if (Bangle.isCharging()) { g.setColor('#FD0'); @@ -19,17 +19,20 @@ WIDGETS.chargingStatus = { area: 'tr', width: Bangle.isCharging() ? iconWidth : 0, - draw: draw, + draw, }; Bangle.on('charging', (charging) => { - if (charging) { - Bangle.buzz(); - WIDGETS.chargingStatus.width = iconWidth; - } else { - WIDGETS.chargingStatus.width = 0; + const widget = WIDGETS.chargingStatus; + if (widget) { + if (charging) { + Bangle.buzz(); + widget.width = iconWidth; + } else { + widget.width = 0; + } + Bangle.drawWidgets(); // re-layout widgets + g.flip(); } - Bangle.drawWidgets(); // re-layout widgets - g.flip(); }); })(); diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 8a7ab3342..09101094b 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -2,7 +2,16 @@ "compilerOptions": { "module": "es2015", "noImplicitAny": true, - "target": "es2015" + "target": "es2015", + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strict": true }, "include": ["../apps/**/*", "./**/*"] } diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 359d5d294..46d1e3b0a 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -178,6 +178,6 @@ declare const g: GraphicsApi; declare type Widget = { area: 'tr' | 'tl'; width: number; - draw: () => void; + draw: (this: { x: number; y: number }) => void; }; declare const WIDGETS: { [key: string]: Widget }; From 96b099b10ac58143d15b0ea28e1476a81d573c57 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 21:51:35 +0100 Subject: [PATCH 010/199] make tsconfig work for all ts apps --- .github/workflows/nodejs.yml | 9 +++++++-- apps.json | 2 +- apps/widChargingStatus/{dist => }/widget.js | 15 ++++++++------- typescript/package.json | 2 +- typescript/tsconfig.json | 3 ++- 5 files changed, 19 insertions(+), 12 deletions(-) rename apps/widChargingStatus/{dist => }/widget.js (61%) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index e2a12cc51..8187fc890 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -16,7 +16,12 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: npm i - run: npm i + - name: npm ci + working-directory: ./typescript + run: npm ci - name: build types + working-directory: ./typescript + run: npm run build:types + - name: build all TS apps + working-directory: ./typescript run: npm run build:types diff --git a/apps.json b/apps.json index 58a67d8c2..6e85c19d7 100644 --- a/apps.json +++ b/apps.json @@ -4763,7 +4763,7 @@ "tags": "widget", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"widChargingStatus.wid.js","url":"./dist/widget.js"} + {"name":"widChargingStatus.wid.js","url":"./widget.js"} ] }, { diff --git a/apps/widChargingStatus/dist/widget.js b/apps/widChargingStatus/widget.js similarity index 61% rename from apps/widChargingStatus/dist/widget.js rename to apps/widChargingStatus/widget.js index 6cac1931f..68a7c0aca 100644 --- a/apps/widChargingStatus/dist/widget.js +++ b/apps/widChargingStatus/widget.js @@ -1,22 +1,23 @@ -(function () { - var icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); - var iconWidth = 18; +"use strict"; +(() => { + const icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); + const iconWidth = 18; function draw() { g.reset(); if (Bangle.isCharging()) { g.setColor('#FD0'); g.drawImage(icon, this.x + 1, this.y + 1, { - scale: 0.6875 + scale: 0.6875, }); } } WIDGETS.chargingStatus = { area: 'tr', width: Bangle.isCharging() ? iconWidth : 0, - draw: draw + draw, }; - Bangle.on('charging', function (charging) { - var widget = WIDGETS.chargingStatus; + Bangle.on('charging', (charging) => { + const widget = WIDGETS.chargingStatus; if (widget) { if (charging) { Bangle.buzz(); diff --git a/typescript/package.json b/typescript/package.json index 83ea7d82b..4bfb88d27 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -7,7 +7,7 @@ "typescript": "4.5.2" }, "scripts": { - "build:example": "tsc ../apps/widChargingStatus/widget.ts --outDir ../apps/widChargingStatus/dist", + "build:apps": "tsc", "build:types": "tsc ./types/globals.d.ts" } } diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 09101094b..aff7a6d38 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -13,5 +13,6 @@ "noUnusedParameters": true, "strict": true }, - "include": ["../apps/**/*", "./**/*"] + "include": ["../apps/**/*", "./**/*"], + "exclude": ["../apps/banglerun", "../apps/hebrew_calendar"] } From a393d573d644993927b4155c0c5c6ca570cb88a0 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 21:52:26 +0100 Subject: [PATCH 011/199] Update nodejs.yml --- .github/workflows/nodejs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 8187fc890..a9ada5e5e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -21,7 +21,7 @@ jobs: run: npm ci - name: build types working-directory: ./typescript - run: npm run build:types + run: npm run build:apps - name: build all TS apps working-directory: ./typescript run: npm run build:types From d7be82bcc71a2445993e7adcec8074142cfa6038 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:01:01 +0100 Subject: [PATCH 012/199] Update README.md --- typescript/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typescript/README.md b/typescript/README.md index 9b38459ae..66506924e 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -22,7 +22,7 @@ npm ci to install the project's build tools, and: ``` -npx tsc ../apps/relativePathToYourApp/app.ts --outDir ../apps/relativePathToYourApp/dist +npm run build:apps ``` -To build your app. The last command will generate the `app.js` file containing the transpiled code for the BangleJS. +To build all Typescript apps. The last command will generate the `app.js` files containing the transpiled code for the BangleJS. From a86f2c108dfc119de10d8ac3b65e1bc21009649b Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:02:41 +0100 Subject: [PATCH 013/199] Update README.md --- typescript/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/typescript/README.md b/typescript/README.md index 66506924e..d1f60fd0b 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -6,7 +6,8 @@ The goal is to have types for everything, but that will take some time. Feel fre ## Using the types -TODO +All currently typed modules can be found in `/typescript/types.globals.d.ts`. +The typing is an ongoing process. If anything is still missing, you can add it! It will automatically be available in your TS files. ## Compilation From 4990c426752586600ebb08ae472d71cbe2ed22c4 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:04:43 +0100 Subject: [PATCH 014/199] Update tsconfig.json --- typescript/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index aff7a6d38..40537c680 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -14,5 +14,6 @@ "strict": true }, "include": ["../apps/**/*", "./**/*"], + // these apps have been excluded because they were built before this configuration was created and are using their own "exclude": ["../apps/banglerun", "../apps/hebrew_calendar"] } From 4511520c88c4f4e2174639c41bb24195f3a82d83 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:17:06 +0100 Subject: [PATCH 015/199] upgrade chargingStatus version --- apps.json | 2 +- apps/widChargingStatus/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3466ab0fb..0a6cebba7 100644 --- a/apps.json +++ b/apps.json @@ -4782,7 +4782,7 @@ "name": "Charging Status", "shortName":"ChargingStatus", "icon": "widget.png", - "version":"0.1", + "version":"0.2", "type": "widget", "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", "tags": "widget", diff --git a/apps/widChargingStatus/ChangeLog b/apps/widChargingStatus/ChangeLog index d3175e1ab..ceb7cb883 100644 --- a/apps/widChargingStatus/ChangeLog +++ b/apps/widChargingStatus/ChangeLog @@ -1 +1,2 @@ -0.1: First release. \ No newline at end of file +0.1: First release. +0.2: No functional changes, just moved codebase to Typescript. \ No newline at end of file From d255d42a8c34b70c762cd8f4f3197aedfcf78a21 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:27:25 +0100 Subject: [PATCH 016/199] disable strict to see if that fixes widget --- apps/widChargingStatus/widget.js | 1 - typescript/tsconfig.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/widChargingStatus/widget.js b/apps/widChargingStatus/widget.js index 68a7c0aca..042e225f7 100644 --- a/apps/widChargingStatus/widget.js +++ b/apps/widChargingStatus/widget.js @@ -1,4 +1,3 @@ -"use strict"; (() => { const icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); const iconWidth = 18; diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 40537c680..114e01ac3 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -11,7 +11,7 @@ "noUncheckedIndexedAccess": true, "noUnusedLocals": true, "noUnusedParameters": true, - "strict": true + "noImplicitUseStrict": true }, "include": ["../apps/**/*", "./**/*"], // these apps have been excluded because they were built before this configuration was created and are using their own From 0ece5ccdb0d8f61b963c7473ef00c47466b86900 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:32:36 +0100 Subject: [PATCH 017/199] more testing to get app back running --- apps.json | 2 +- apps/widChargingStatus/widget.js | 2 +- apps/widChargingStatus/widget.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 0a6cebba7..6f53c0c48 100644 --- a/apps.json +++ b/apps.json @@ -4782,7 +4782,7 @@ "name": "Charging Status", "shortName":"ChargingStatus", "icon": "widget.png", - "version":"0.2", + "version":"0.3", "type": "widget", "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", "tags": "widget", diff --git a/apps/widChargingStatus/widget.js b/apps/widChargingStatus/widget.js index 042e225f7..386b84947 100644 --- a/apps/widChargingStatus/widget.js +++ b/apps/widChargingStatus/widget.js @@ -13,7 +13,7 @@ WIDGETS.chargingStatus = { area: 'tr', width: Bangle.isCharging() ? iconWidth : 0, - draw, + draw: draw, }; Bangle.on('charging', (charging) => { const widget = WIDGETS.chargingStatus; diff --git a/apps/widChargingStatus/widget.ts b/apps/widChargingStatus/widget.ts index 712bf4f97..14b4df4a4 100644 --- a/apps/widChargingStatus/widget.ts +++ b/apps/widChargingStatus/widget.ts @@ -19,7 +19,7 @@ WIDGETS.chargingStatus = { area: 'tr', width: Bangle.isCharging() ? iconWidth : 0, - draw, + draw: draw, }; Bangle.on('charging', (charging) => { From 0499f04dc3de9c1d5725c325ad67ddb6d676b939 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:36:22 +0100 Subject: [PATCH 018/199] try to use strict again --- apps/widChargingStatus/widget.js | 1 + typescript/tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/widChargingStatus/widget.js b/apps/widChargingStatus/widget.js index 386b84947..5d9ea3837 100644 --- a/apps/widChargingStatus/widget.js +++ b/apps/widChargingStatus/widget.js @@ -1,3 +1,4 @@ +"use strict"; (() => { const icon = require('heatshrink').decompress(atob('ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA')); const iconWidth = 18; diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 114e01ac3..40537c680 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -11,7 +11,7 @@ "noUncheckedIndexedAccess": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noImplicitUseStrict": true + "strict": true }, "include": ["../apps/**/*", "./**/*"], // these apps have been excluded because they were built before this configuration was created and are using their own From 8baa3eca7235085698f08c5c8b2501048da1aa44 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:38:26 +0100 Subject: [PATCH 019/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6f53c0c48..3f2363a31 100644 --- a/apps.json +++ b/apps.json @@ -4782,7 +4782,7 @@ "name": "Charging Status", "shortName":"ChargingStatus", "icon": "widget.png", - "version":"0.3", + "version":"0.4", "type": "widget", "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", "tags": "widget", From 5c851714ee17ad55ca6692a6e9ad49e717a16d11 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:43:33 +0100 Subject: [PATCH 020/199] revert chargingStatus version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3f2363a31..0a6cebba7 100644 --- a/apps.json +++ b/apps.json @@ -4782,7 +4782,7 @@ "name": "Charging Status", "shortName":"ChargingStatus", "icon": "widget.png", - "version":"0.4", + "version":"0.2", "type": "widget", "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", "tags": "widget", From c462547a2bfe283e610ea093bfa34a9cc98faf75 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 22:45:10 +0100 Subject: [PATCH 021/199] fix github actions --- .github/workflows/nodejs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index a9ada5e5e..c268c884c 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -21,7 +21,7 @@ jobs: run: npm ci - name: build types working-directory: ./typescript - run: npm run build:apps + run: npm run build:types - name: build all TS apps working-directory: ./typescript - run: npm run build:types + run: npm run build:apps From fc2c3c86a4c9c68b9ec56f5731775955f710b4c3 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Fri, 10 Dec 2021 23:17:18 +0100 Subject: [PATCH 022/199] document typing progress --- typescript/types/globals.d.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 46d1e3b0a..2ef52dcdf 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -1,10 +1,12 @@ -// TODO all of these globals (copied from eslintrc need to be typed at some point) -/* { +// TODO all of these globals (copied from eslintrc) need to be typed at some point +/* The typing status is listed on the left of the attribute, e.g.: +status "Attribute" + // Methods and Fields at https://banglejs.com/reference "Array": "readonly", "ArrayBuffer": "readonly", "ArrayBufferView": "readonly", - "Bangle": "readonly", +started "Bangle": "readonly", "BluetoothDevice": "readonly", "BluetoothRemoteGATTCharacteristic": "readonly", "BluetoothRemoteGATTServer": "readonly", @@ -20,8 +22,8 @@ "Float64Array": "readonly", "fs": "readonly", "Function": "readonly", - "Graphics": "readonly", // partly done - "heatshrink": "readonly", +started "Graphics": "readonly", +done "heatshrink": "readonly", "I2C": "readonly", "Int16Array": "readonly", "Int32Array": "readonly", @@ -107,7 +109,7 @@ "poke32": "readonly", "poke8": "readonly", "print": "readonly", - "require": "readonly", +started "require": "readonly", "reset": "readonly", "save": "readonly", "Serial1": "readonly", @@ -123,9 +125,8 @@ "trace": "readonly", "VIBRATE": "readonly", // Aliases and not defined at https://banglejs.com/reference - "g": "readonly", // done - "WIDGETS": "readonly" // done - } +done "g": "readonly", +done "WIDGETS": "readonly" */ // ambient JS definitions From 92b6fc0ea000968a6d24dba03f386f2ef6f99f07 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 22:57:12 -0800 Subject: [PATCH 023/199] Create app.js --- apps/aptSciClock/app.js | 206 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 apps/aptSciClock/app.js diff --git a/apps/aptSciClock/app.js b/apps/aptSciClock/app.js new file mode 100644 index 000000000..cb1305c36 --- /dev/null +++ b/apps/aptSciClock/app.js @@ -0,0 +1,206 @@ +const big = g.getWidth()>200; +const timeFontSize = big?5:4; +const dateFontSize = big?3:2; +const gmtFontSize = 2; +const font = "6x8"; + +const xyCenter = g.getWidth() / 2; +const yposTime = xyCenter*0.73; +const yposDate = xyCenter*1.44; +const yposYear = xyCenter*1.8; + +const buttonTolerance = 20; +const buttonX = 88; +const buttonY = 104; + +function getImg(img){ + if (img == "w0"){//drink + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOZFIQOD4EABwnwgEDBwf8g/4h4ODwYQBv4OC+AbDAIP+j/HAQIOC4Hwj4RBBwP8o8B/+PBwWOkEP/l/BwP4+JCB44OCj+Ih/+n4OB+PEoP38YOB/0YkUXGgIOB8cBi9f+IOCkEI+XvBwXigFG64OEg0/t4OEuP7BwkHx/PBwWigF8voOC+Uwg/ig4OCkMgv8QsIOB+cfSoOGLIUR/E/4ljBwPxx/B/0kO4UI/0P+J3C/HHVQOISoWEn+D/iPBBwIwC8IOCwcP84IBBwU4TAMHBwfAv+AcARBBgD3CBwX8gDnBBwfwewIODAgIABBwYHDB3oAEBwIHFByyDBABg")) +} + } + else if (img == "w1"){//cube + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOI/3/+fvBwYEBnwO/By3APgN/O6IeBh4OF8AOcwADCBwX8g4dM/8fBwt774OE+/9Bwt/BxodH3oOcFgyVG8BhCBwX8hRwCBwXA0C6BBwc/w4OE41MBwtEo6VF84sE/1/54OLDo4sHHYxKHLIxoGO44AD/kAABo")) + } + } + else if (img == "w2"){//acid + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOF+IOGngOF8/D8YGD/wdBB4nv4fzAwf4BwOfGQd/4f7/+//+f74OB4PwHIJKDx8P/4BBBwP8BwIBBBwXvh+Hw5ZD+Pwnl/NAcegJOBBwfgj0fBwvhBxcPgYEBBwXw/F+FghIB84OC/BfBOYQOBk/w/0f4f4nkGgFgh0hwED4H4jOBuF8hk/v/Hzlnx/zFgQZBGYLCD4EHaIn8gAOF8EDBwn+dgQOK/8AN4IOD+EABww0BBwqGEBwIWBBwk8CwIODg/gv4OEv4OD+4OBBAIOBRYIFBh+PcAQdC+gOCDoN+h/vBwPP/wOB/wOBwJCBBwP2oa3BLALgBiA7BOwIvB/+DQoV/d4hPBBwQsB/wJB8ZoEAAZoDAAQOPRQIAM")) + } + } + else if (img == "w3"){//turret + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOi+IOGh4OF8AOF/UNBwthx4OE+0YBwtBh4OE6mQBwn7rEfBwl22IOE99gBwn99UzBwUc/+90YsC8HH+++n98n/+g0++2Z+4OB4Fz73T74OCg877d8/YdC+d7u/v3gsBjEvt/+O4X+gvtIgI7CwG934OD8E326kD/0A+yzEwEO74OD/EArYOEgEDv4OD+PAl4OEnkBaInz0EPBwk3iAdE+XwSIYDBj2Oj4OD/fYvIOEvdHz4OD99unIOD/vt44OE3u4Dou3h4OE+3x/IOE70/Bwn78/9Bwl4LAQ7Dx75DBwP4Awb+EBwgAEBz0AABo=")) + } + } + else if (img == "w4"){//cake + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOY/oOG94OF/1/Bwv3FgwKCBwfnFhn8HY0LAQPwvgOB8EP/5uBBwP2gF4j+PBwP+sEEj/x44OB90Ao/8Dodwg8/nkH4ZXBgHnx8ABwPv/k98+ABwZEB+EAJQPj/3+nkAv4OB5+fz0Aj4OB98Ag+Ah/nBwJXB4EDHYSTB/EA/wsCSoJfBwAODNIPgBwgcBHYQOCC4QODn8Ah4ODGgMH+47D8EB/A7KTYMf4A7Eg/wHYgcBHZx3DcAPggbRBFgQcBcAQOB/iUBBwgcBBwgcCd4V/HYL+D/YOBDgIOC8/+DgIOC/+HfwIOD/4cCBwYAEBwQADBz0AABoA=")) + } + } + else if (img == "butPress"){ + return { + width : 176, height : 176, bpp : 4, + transparent : 1, + buffer : require("heatshrink").decompress(atob("iIA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AFEVqsFqpD/ACVVAAJXBqtRI35WSK4ZY/AB8VK49VJP5WRK4pY/ABhQEK41RJn5X/AEMVK5dVJv6uPK46w/K/4AgipPFgEALAxP/K5tQAQhX/K6KsDWApP/AA6uHWA9RIWPd6ICPK46qFAohXxjvd7oCMCAJX/K7cAAAZXFBQkBK/6v/ABPd6ICPK/4AaKIlQAhCv2ACMVVRC0FK2MdAIRXXVYSuFK/5XOqsAgCuFK/4AJJwtVKw1RK+MR7vRK/4AripXMJv6wQK4qu/K/4AjipXKJf5YRK4hJ/ABxXHqJI/LCRXCK34ASipXCIf4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACI=")) + } + } + else if (img == "butUnpress"){ + return { + width : 176, height : 176, bpp : 4, + transparent : 1, + buffer : require("heatshrink").decompress(atob("iIA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AFEc5kM5hD/ACXMAAJXB5nBI35WSK4ZY/AB8cK4/MJP5WRK4pY/ABhQEK43BJn5X/AEMcK5fMJv6uPK46w/K/4AgjhPFgEALAxP/K5vAAQhX/K6KsDWApP/AA6uHWA/BIWOIwICPK46qFAohXxjGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwICPK/4AaKInAAhCv2ACMcVRC0FK2MYAIRXXVYSuFK/5XO5kAgCuFK/4AJJwvMKw3BK+MRxGBK/4ArjhXMJv6wQK4qu/K/4AjjhXKJf5YRK4hJ/ABxXH4JI/LCRXCK34ASjhXCIf4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACI=")) + } + } + + else if (img == "apetureLaboratories"){ + return { + width : 173, height : 43, bpp : 4, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AA+IAAeAIv5UTK34APhABBKwpeBJX5VLJgJWGAwKv/ABL8EKomABIYA/KpJWHAoRW/KpZQCfwJSCAgRW/KphWFBgZW/KphNCAgSxEKP4ADJAatFKwWAL4oA/KpALGXQhS/Ko4MIwAOMAHREOKv5ZVVgcAh///4LDAwQAB+AIHCQYHMDQQYBDwQEGDIoaGTx4MCwAiCJgYhFBIYIHLw4HFBARjGESJUDehZVFVhJNLRI5VGDIIdEAgwiL+DzDJAJVJB4IMBCoKsHAYpFCDgr2IApYEIBpJFCKpqsCHgQbFIhBVHBhJoGTwyBRKp5mBDoY6GKoYqEXYg7JApKeHQJysEKpRmBDoasHQBAACM4qMGEAr0JAgZjGFYhVPgGAEIpVEAAaAEA4oyEW4qyKFZBoFKoisDJIJWLfIp3IQBJeJfgysMERpVCwEIVpijFBA6ZJdA4JHJYgEKQIx1EVgRVBVhj5IEIyZHHYoUGNw4MCQIwIKAARVDxBVRQo6ZJHZZoGU4yBGBAiBGVgRZBVhYlIfJBoFHZZoHfJRwGBAQrEVISvCKpwrEUZAqFVhzYKB4yKGQIpVDAYJVKEoYFDBIpVIb4ysMIgoPHOgoRFhGAVwKsLAFzQHACBVCVhQA/KpawBCJa76IhRWDVxIODAwTaFAocP///dhALGBQYJBCIYQBDYgKEBBAEDVgeIAgKgFBYZVEEYY+CH4YDBBgYFBBYoFEOYhmEDYgFFLIwEDKw2AKwhTFBoSsHIgglFAQo/HKIoDECBBZGc46eEAYa2EKox2Ga5LjLDoq8FKAgVDBAv/EghWGVgRWJKoaOFD4IgCViAWFVjKTGJIZOFKpKOHAQj3JAogCFPApcGKQziGLopKCU4hWFKojsEHYrXFCAJFId45CEDYh4EB4Y1DCYSzFJQT+FgAGCKooA/AAZMBfopWDKv5WLVgxT/AB+AKopW/ACBU/ABwA==")) + } + } + + else if (img == "apetureWatch"){ + return { + width : 176, height : 176, bpp : 4, + transparent : 2, + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0SkQASkIVViIrqK/5X/K/5X/CqPd6EAAA8BiAKIABUBiIVUFZMIxBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xal////yK/5XTKwIABK4URAA3/+Pd6ILHAG8YxADBj5XD+ISIBwRX/K4pWDAAIHBiS6CAAMvBYXd6DbTeJcRCqgrJhGIJIJXFkUhK4oLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCkMSK4auDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAhXBAoa/Cl5X/K4ZHCAAZXEAoZnCK/5XLVQRXFBgZX/K4igCLAnxK4RdBBohX/K5cikJXCAAxX/K4j5EK/5X/K9fyK/5X/K93/K/5X/KxQABK78vK4PyK/5XWWApXq+JXC+BXeKwRXPl5Xdh//K4Y1BK+H/K7n//GIK4g5BWR5XP+RXNl5Xch+IGQJXFA4JXeJwpXICAJXah/4x4fBKwURj5XBBIJXcVwpXBFoYwDK4XRBYwAR/CtFAAZXCBQ4AQjBXCCRxXcUoJLDjnMhnMBgTqCK7RzIiS3FkRXC6DbTAAf4UYIoB5gABK4PM4KBD+AcLFZUIK4JNGkUhK44ABK7EPQwZWCK4ZYCWARXY+RXrVwccK4/MWB5XMJhBXkVwJWEK4pYBK/4AGh+IVwJQEK43BWARX/VwmP+JXNWBpX5VwMcK5fMiKwBK9YAKCphXCJ4pXH4JXB+QrWCtUvxHxK58R///K/5XCx/xjhPFdAJYGK/5XN4ACEK/4AIIYMRK4qsDWAsRj//+RX/iIACVw6wH4ITCEJBXlxGCARxXIVQoFEK+MoxGIARgQBK/5XbgAADK4oKEgJX/V/4AJxGCARxX/Cq5XI4AEIV+wVO///iMcVRC0FiMf//yTNIADlABCCp0v//xK4qrCVwpXB/+PeNRXf5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQVQ///K58f/HyK94VSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5UR/+IGgbeXK9awBLAhXEiKuBx40DHCYuEK9EvWAURK4/BVwSWEK/6wGLAZXCKwKuGK/6wIiMcK4QFBVw5X/WA2IwJSCAAYJBVwpX/WA2IJwJVDj///GPVwpX/A434K4PxVoYHBKwxX/AAynCK4ZWCGA5X/BI//V4itHK/4LKK4YtKK/4qJK4QOKK/5X/K8BYCBpZX/K/5XVfYQAWK6gedK/5XiBhchiINLK6grJK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xu/4AYV/4AXK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiKv/K/5X/K/5X/K/5X/K/5X6/4AdiIAYFzw=")) + } + } +} + + +function drawStart(){ + g.clear(); + g.reset(); + apSciLab = getImg("apetureLaboratories"); + g.drawImage(apSciLab, xyCenter-apSciLab.width/2, xyCenter-apSciLab.height/2); +} + +drawStart(); + +// Check settings for what type our clock should be +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; + +// timeout used to update every minute +var drawTimeout; + +//warnings +var curWarning = -1; +var maxWarning = 4; + +function buttonPressed(){ + if (curWarning < maxWarning) curWarning += 1; + else curWarning = 0; + buttonImg = getImg("butPress"); + g.drawImage(buttonImg, 0, 0); + + warningImg = getImg("w"+String(curWarning)); + g.drawImage(warningImg, 1, g.getWidth()-61); + + setTimeout(buttonUnpressed, 500); +} +function buttonUnpressed(){ + buttonImg = getImg("butUnpress"); + g.drawImage(buttonImg, 0, 0); +} + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function draw() { + // get date + var d = new Date(); + var da = d.toString().split(" "); + + g.reset(); // default draw styles + + //draw watchface + apSciWatch = getImg("apetureWatch"); + g.drawImage(apSciWatch, xyCenter-apSciWatch.width/2, xyCenter-apSciWatch.height/2); + + // drawSting centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); + meridian = "AM"; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); + } + + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, false); + g.setFont(font, gmtFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // draw Day, name of month, Date + var date = [da[0], da[1], da[2]].join(" "); + g.setFont(font, dateFontSize); + + g.drawString(String(da[0]), xyCenter*1.55, yposDate, true); + g.drawString(String(da[1]), xyCenter*1.55, yposDate+20*1, true); + g.drawString(String(da[2]), xyCenter*1.55, yposDate+20*2, true); + + + // draw year + g.setFont(font, dateFontSize); + g.drawString(d.getFullYear(), xyCenter+1, yposYear, true); + + queueDraw(); +} + + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +Bangle.on('touch',(n,e)=>{ + //button is 88 104 + if (buttonX-buttonTolerance < e.x && e.x < buttonX+buttonTolerance && buttonY-buttonTolerance < e.y && e.y < buttonY+buttonTolerance){ + buttonPressed(); + } +}); + +// clean app screen +g.clear(); +// Show launcher when button pressed +Bangle.setUI("clock"); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +buttonPressed();//update warning image + +// draw now +draw(); From 4113dab20b004d974df743fc164f362086f44063 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:09:34 -0800 Subject: [PATCH 024/199] Add files via upload --- apps/aptSciClock/App.png | Bin 0 -> 714 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/aptSciClock/App.png diff --git a/apps/aptSciClock/App.png b/apps/aptSciClock/App.png new file mode 100644 index 0000000000000000000000000000000000000000..b37efdaf87f40701f3599655074d11a22bf2ff11 GIT binary patch literal 714 zcmV;*0yX`KP)L z17IEMg|K#r{J;RL^LnLPK*|`;7J!HWTAUY7FL9iYc~@j+`DRVteY zwLCHZ_W?#YpOq8>DDydyI0N)LPb8kJb%_?TZ|3gl8Ha$Z)OIB#PB3FT~o`pF_Pw8t!2*VeN>iwlrse+R13PgiuG`%lo+#{}%wVKOF(0bLq?oFwUPMz??~E zK`;QjzwZbH&El12GXNOp-2)AoG?x}3ba&*OOL8Z&t0RC`AKnY02_$sP;XfNHZ9B1n zJl{$n!}{vuQxQ>i^A}rQvX25`6>!*%+7(BWM3+x22(nRAfg`Q_-^?KySfl9uCp|0hAdt wJ4o$;{H8^Iroccu@ALzBhEWe`bk-a82X Date: Sun, 19 Dec 2021 23:10:52 -0800 Subject: [PATCH 025/199] Delete App.png --- apps/aptSciClock/App.png | Bin 714 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/aptSciClock/App.png diff --git a/apps/aptSciClock/App.png b/apps/aptSciClock/App.png deleted file mode 100644 index b37efdaf87f40701f3599655074d11a22bf2ff11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 714 zcmV;*0yX`KP)L z17IEMg|K#r{J;RL^LnLPK*|`;7J!HWTAUY7FL9iYc~@j+`DRVteY zwLCHZ_W?#YpOq8>DDydyI0N)LPb8kJb%_?TZ|3gl8Ha$Z)OIB#PB3FT~o`pF_Pw8t!2*VeN>iwlrse+R13PgiuG`%lo+#{}%wVKOF(0bLq?oFwUPMz??~E zK`;QjzwZbH&El12GXNOp-2)AoG?x}3ba&*OOL8Z&t0RC`AKnY02_$sP;XfNHZ9B1n zJl{$n!}{vuQxQ>i^A}rQvX25`6>!*%+7(BWM3+x22(nRAfg`Q_-^?KySfl9uCp|0hAdt wJ4o$;{H8^Iroccu@ALzBhEWe`bk-a82X Date: Sun, 19 Dec 2021 23:11:25 -0800 Subject: [PATCH 026/199] Renamed folder --- apps/{aptSciClock => aptsciclk}/app.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{aptSciClock => aptsciclk}/app.js (100%) diff --git a/apps/aptSciClock/app.js b/apps/aptsciclk/app.js similarity index 100% rename from apps/aptSciClock/app.js rename to apps/aptsciclk/app.js From 498f0701599dcb26412ce19df3be79be27ae2bdb Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:11:45 -0800 Subject: [PATCH 027/199] Add files via upload --- apps/aptsciclk/App.png | Bin 0 -> 714 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/aptsciclk/App.png diff --git a/apps/aptsciclk/App.png b/apps/aptsciclk/App.png new file mode 100644 index 0000000000000000000000000000000000000000..b37efdaf87f40701f3599655074d11a22bf2ff11 GIT binary patch literal 714 zcmV;*0yX`KP)L z17IEMg|K#r{J;RL^LnLPK*|`;7J!HWTAUY7FL9iYc~@j+`DRVteY zwLCHZ_W?#YpOq8>DDydyI0N)LPb8kJb%_?TZ|3gl8Ha$Z)OIB#PB3FT~o`pF_Pw8t!2*VeN>iwlrse+R13PgiuG`%lo+#{}%wVKOF(0bLq?oFwUPMz??~E zK`;QjzwZbH&El12GXNOp-2)AoG?x}3ba&*OOL8Z&t0RC`AKnY02_$sP;XfNHZ9B1n zJl{$n!}{vuQxQ>i^A}rQvX25`6>!*%+7(BWM3+x22(nRAfg`Q_-^?KySfl9uCp|0hAdt wJ4o$;{H8^Iroccu@ALzBhEWe`bk-a82X Date: Sun, 19 Dec 2021 23:12:57 -0800 Subject: [PATCH 028/199] Create app-icon.js --- apps/aptsciclk/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/aptsciclk/app-icon.js diff --git a/apps/aptsciclk/app-icon.js b/apps/aptsciclk/app-icon.js new file mode 100644 index 000000000..d2a2dbbd6 --- /dev/null +++ b/apps/aptsciclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwgNKxAACEaIVDDKWAhAXGwAtODA4HBLR4YFD4QWICIhABGAoMBJRBZHC4wwHOQ4IFAgQwGUQ4YBAg4uMJIwDDGAjRLIgYLHc5gXJIwbKLC4hICb4gZKfAhgETJKHJLwwXRUooWKCImAJogXRMopGMNwkIC4oWLYYqtHC5rFJC5h0GIxwsGFyD8CC4wwOIxBIQFwoeBCxrwEFwYXTFgTXReI4uQC4apPC4xNERqBlGFx4XCeJ4nHD4kIIxY3KPoIxNBwYXEJRInEP44iGOgwXFBYYcDChCHHC4wMBC5BnJEoouMGAYXEJJCCJC4pOEcpYKBFIpJFZRQXGD4gWKXBUICxjdFIhwyJOJMAA=")) From 8ed719a73a072f4f6c123160324be653a553bd31 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:16:25 -0800 Subject: [PATCH 029/199] Delete App.png --- apps/aptsciclk/App.png | Bin 714 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/aptsciclk/App.png diff --git a/apps/aptsciclk/App.png b/apps/aptsciclk/App.png deleted file mode 100644 index b37efdaf87f40701f3599655074d11a22bf2ff11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 714 zcmV;*0yX`KP)L z17IEMg|K#r{J;RL^LnLPK*|`;7J!HWTAUY7FL9iYc~@j+`DRVteY zwLCHZ_W?#YpOq8>DDydyI0N)LPb8kJb%_?TZ|3gl8Ha$Z)OIB#PB3FT~o`pF_Pw8t!2*VeN>iwlrse+R13PgiuG`%lo+#{}%wVKOF(0bLq?oFwUPMz??~E zK`;QjzwZbH&El12GXNOp-2)AoG?x}3ba&*OOL8Z&t0RC`AKnY02_$sP;XfNHZ9B1n zJl{$n!}{vuQxQ>i^A}rQvX25`6>!*%+7(BWM3+x22(nRAfg`Q_-^?KySfl9uCp|0hAdt wJ4o$;{H8^Iroccu@ALzBhEWe`bk-a82X Date: Sun, 19 Dec 2021 23:16:36 -0800 Subject: [PATCH 030/199] Add files via upload --- apps/aptsciclk/app.png | Bin 0 -> 714 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/aptsciclk/app.png diff --git a/apps/aptsciclk/app.png b/apps/aptsciclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b37efdaf87f40701f3599655074d11a22bf2ff11 GIT binary patch literal 714 zcmV;*0yX`KP)L z17IEMg|K#r{J;RL^LnLPK*|`;7J!HWTAUY7FL9iYc~@j+`DRVteY zwLCHZ_W?#YpOq8>DDydyI0N)LPb8kJb%_?TZ|3gl8Ha$Z)OIB#PB3FT~o`pF_Pw8t!2*VeN>iwlrse+R13PgiuG`%lo+#{}%wVKOF(0bLq?oFwUPMz??~E zK`;QjzwZbH&El12GXNOp-2)AoG?x}3ba&*OOL8Z&t0RC`AKnY02_$sP;XfNHZ9B1n zJl{$n!}{vuQxQ>i^A}rQvX25`6>!*%+7(BWM3+x22(nRAfg`Q_-^?KySfl9uCp|0hAdt wJ4o$;{H8^Iroccu@ALzBhEWe`bk-a82X Date: Sun, 19 Dec 2021 23:20:44 -0800 Subject: [PATCH 031/199] Added aptsciclk --- apps.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps.json b/apps.json index e5e9f8f02..f1d9c962f 100644 --- a/apps.json +++ b/apps.json @@ -5047,6 +5047,21 @@ {"name":"circlesclock.json"} ] }, + { "id": "aptsciclk", + "name": "Apeture Science clock", + "shortName":"AptSci clock", + "version":"0.01", + "description": "A clock based on the Portal series, + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "storage": [ + {"name":"aptsciclk.app.js","url":"app.js"}, + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true}, + ] + }, { "id": "ltherm", "name": "Localized Thermometer", From 3e090cd727ba2d929a7ba212fb0b6f360406c830 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:28:04 -0800 Subject: [PATCH 032/199] Update apps.json --- apps.json | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/apps.json b/apps.json index f1d9c962f..5abe84172 100644 --- a/apps.json +++ b/apps.json @@ -5047,21 +5047,6 @@ {"name":"circlesclock.json"} ] }, - { "id": "aptsciclk", - "name": "Apeture Science clock", - "shortName":"AptSci clock", - "version":"0.01", - "description": "A clock based on the Portal series, - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports" : ["BANGLEJS2"], - "allow_emulator":true, - "storage": [ - {"name":"aptsciclk.app.js","url":"app.js"}, - {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true}, - ] - }, { "id": "ltherm", "name": "Localized Thermometer", @@ -5077,5 +5062,19 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] - } + }, + }, +{ "id": "aptsciclk", + "name": "Apeture Science Clock", + "shortName":"Apeture", + "icon": "app.png", + "version":"0.01", + "description": "A clock made in the style of the Portal series", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"aptsciclk.app.js","url":"app.js"}, + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} + ] +} ] From d63a9975955aa65616b3bc3f078c22ee1c1fecdb Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:32:45 -0800 Subject: [PATCH 033/199] Update apps.json --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 5abe84172..0a9cd40f9 100644 --- a/apps.json +++ b/apps.json @@ -5070,8 +5070,9 @@ "icon": "app.png", "version":"0.01", "description": "A clock made in the style of the Portal series", - "tags": "clock", "type":"clock", + "tags": "clock", + "supports": ["BANGLEJS2"], "storage": [ {"name":"aptsciclk.app.js","url":"app.js"}, {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} From 8066e3d8ab82614edd2d0847160ebcf5299bc637 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:34:40 -0800 Subject: [PATCH 034/199] Update apps.json --- apps.json | 1 - 1 file changed, 1 deletion(-) diff --git a/apps.json b/apps.json index 0a9cd40f9..bc7c74703 100644 --- a/apps.json +++ b/apps.json @@ -5063,7 +5063,6 @@ {"name":"ltherm.img","url":"icon.js","evaluate":true} ] }, - }, { "id": "aptsciclk", "name": "Apeture Science Clock", "shortName":"Apeture", From 58ede020fa44bd2f8f8f907f3e0aa0556ecaefb5 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:36:57 -0800 Subject: [PATCH 035/199] Update apps.json --- apps.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index bc7c74703..c1d50ca6e 100644 --- a/apps.json +++ b/apps.json @@ -5065,11 +5065,11 @@ }, { "id": "aptsciclk", "name": "Apeture Science Clock", - "shortName":"Apeture", + "shortName": "Apeture", "icon": "app.png", - "version":"0.01", + "version": "0.01", "description": "A clock made in the style of the Portal series", - "type":"clock", + "type": "clock", "tags": "clock", "supports": ["BANGLEJS2"], "storage": [ From 6947bdf5fe7e36cb4bac83343efde84321c33d2f Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:40:55 -0800 Subject: [PATCH 036/199] Update apps.json --- apps.json | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index c1d50ca6e..6e6f84426 100644 --- a/apps.json +++ b/apps.json @@ -5063,18 +5063,19 @@ {"name":"ltherm.img","url":"icon.js","evaluate":true} ] }, -{ "id": "aptsciclk", - "name": "Apeture Science Clock", - "shortName": "Apeture", - "icon": "app.png", - "version": "0.01", - "description": "A clock made in the style of the Portal series", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"aptsciclk.app.js","url":"app.js"}, - {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} - ] +{ + "id": "aptsciclk", + "name": "Apeture Science Clock", + "version": "0.1", + "description": "A clock based on the portal series", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"aptsciclk.app.js","url":"app.js"}, + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} + ] } ] From 7f3864f310445fcc634e012ecebf4187e0a34445 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 19 Dec 2021 23:43:37 -0800 Subject: [PATCH 037/199] Update apps.json --- apps.json | 5064 ----------------------------------------------------- 1 file changed, 5064 deletions(-) diff --git a/apps.json b/apps.json index 6e6f84426..1d792ecfc 100644 --- a/apps.json +++ b/apps.json @@ -1,5068 +1,4 @@ [ - { - "id": "fwupdate", - "name": "Firmware Update", - "version": "0.02", - "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", - "icon": "app.png", - "type": "RAM", - "tags": "tools,system", - "supports": ["BANGLEJS2"], - "custom": "custom.html", - "customConnect": true, - "storage": [], - "sortorder": 20 - }, - { - "id": "boot", - "name": "Bootloader", - "version": "0.39", - "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", - "icon": "bootloader.png", - "type": "bootloader", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":".boot0","url":"boot0.js"}, - {"name":".bootcde","url":"bootloader.js"}, - {"name":"bootupdate.js","url":"bootupdate.js"} - ], - "sortorder": -10 - }, - { - "id": "hebrew_calendar", - "name": "Hebrew Calendar", - "shortName": "HebCal", - "version": "0.04", - "description": "lists the date according to the hebrew calendar", - "icon": "app.png", - "allow_emulator": false, - "tags": "tool,locale", - "supports": [ - "BANGLEJS", - "BANGLEJS2" - ], - "readme": "README.md", - "storage": [ - { - "name": "hebrew_calendar.app.js", - "url": "app.js" - }, - { - "name": "hebrewDate", - "url": "hebrewDate.js" - }, - { - "name": "hebrew_calendar.img", - "url": "app-icon.js", - "evaluate": true - } - ] - }, - { "id": "golfscore", - "name": "Golf Score", - "shortName":"golfscore", - "version":"0.02", - "description": "keeps track of strokes during a golf game", - "icon": "app.png", - "tags": "outdoors", - "allow_emulator": true, - "supports" : ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"golfscore.app.js","url":"app.js"}, - {"name":"golfscore.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "messages", - "name": "Messages", - "version": "0.14", - "description": "App to display notifications from iOS and Gadgetbridge", - "icon": "app.png", - "type": "app", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"messages.app.js","url":"app.js"}, - {"name":"messages.settings.js","url":"settings.js"}, - {"name":"messages.img","url":"app-icon.js","evaluate":true}, - {"name":"messages.wid.js","url":"widget.js"}, - {"name":"messages","url":"lib.js"} - ], - "data": [{"name":"messages.json"},{"name":"messages.settings.json"}], - "screenshots": [{"url":"screenshot.png"},{"url":"screenshot-notify.gif"}], - "sortorder": -9 - }, - { - "id": "android", - "name": "Android Integration", - "shortName": "Android", - "version": "0.05", - "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", - "icon": "app.png", - "tags": "tool,system,messages,notifications", - "dependencies": {"messages":"app"}, - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"android.app.js","url":"app.js"}, - {"name":"android.settings.js","url":"settings.js"}, - {"name":"android.img","url":"app-icon.js","evaluate":true}, - {"name":"android.boot.js","url":"boot.js"} - ], - "sortorder": -8 - }, - { - "id": "ios", - "name": "iOS Integration", - "version": "0.07", - "description": "Display notifications/music/etc from iOS devices", - "icon": "app.png", - "tags": "tool,system,ios,apple,messages,notifications", - "dependencies": {"messages":"app"}, - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"ios.app.js","url":"app.js"}, - {"name":"ios.img","url":"app-icon.js","evaluate":true}, - {"name":"ios.boot.js","url":"boot.js"} - ], - "sortorder": -8 - }, - { - "id": "health", - "name": "Health Tracking", - "version": "0.09", - "description": "Logs health data and provides an app to view it (requires firmware 2v10.100 or later)", - "icon": "app.png", - "tags": "tool,system,health", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"health.app.js","url":"app.js"}, - {"name":"health.img","url":"app-icon.js","evaluate":true}, - {"name":"health.boot.js","url":"boot.js"}, - {"name":"health","url":"lib.js"} - ] - }, - { - "id": "launch", - "name": "Launcher", - "shortName": "Launcher", - "version": "0.10", - "description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", - "icon": "app.png", - "type": "launch", - "tags": "tool,system,launcher", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"launch.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]}, - {"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]}, - {"name":"launch.settings.js","url":"settings.js","supports":["BANGLEJS2"]} - ], - "data": [{"name":"launch.json"}], - "sortorder": -10 - }, - { - "id": "setting", - "name": "Settings", - "version": "0.38", - "description": "A menu for setting up Bangle.js", - "icon": "settings.png", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"setting.app.js","url":"settings.js"}, - {"name":"setting.img","url":"settings-icon.js","evaluate":true} - ], - "data": [{"name":"setting.json","url":"settings.min.json","evaluate":true}], - "sortorder": -5 - }, - { - "id": "about", - "name": "About", - "version": "0.12", - "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", - "icon": "app.png", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"bangle1-about-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"about.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, - {"name":"about.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, - {"name":"about.img","url":"app-icon.js","evaluate":true} - ], - "sortorder": -4 - }, - { - "id": "alarm", - "name": "Default Alarm & Timer", - "shortName": "Alarms", - "version": "0.14", - "description": "Set and respond to alarms and timers", - "icon": "app.png", - "tags": "tool,alarm,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"alarm.app.js","url":"app.js"}, - {"name":"alarm.boot.js","url":"boot.js"}, - {"name":"alarm.js","url":"alarm.js"}, - {"name":"alarm.img","url":"app-icon.js","evaluate":true}, - {"name":"alarm.wid.js","url":"widget.js"} - ], - "data": [{"name":"alarm.json"}] - }, - { - "id": "locale", - "name": "Languages", - "version": "0.14", - "description": "Translations for different countries", - "icon": "locale.png", - "type": "locale", - "tags": "tool,system,locale,translate", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "custom": "locale.html", - "storage": [ - {"name":"locale"} - ], - "sortorder": -10 - }, - { - "id": "notify", - "name": "Notifications (default)", - "shortName": "Notifications", - "version": "0.11", - "description": "Provides the default `notify` module used by applications to display notifications in a bar at the top of the screen. This module is installed by default by client applications such as the Gadgetbridge app. Installing `Fullscreen Notifications` replaces this module with a version that displays the notifications using the full screen", - "icon": "notify.png", - "type": "notify", - "tags": "widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"notify","url":"notify.js"} - ] - }, - { - "id": "notifyfs", - "name": "Fullscreen Notifications", - "shortName": "Notifications", - "version": "0.12", - "description": "Provides a replacement for the `Notifications (default)` `notify` module. This version is used by applications to display notifications fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notify module.", - "icon": "notify.png", - "type": "notify", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"notify","url":"notify.js"} - ] - }, - { - "id": "welcome", - "name": "Welcome", - "shortName": "Welcome", - "version": "0.14", - "description": "Appears at first boot and explains how to use Bangle.js", - "icon": "app.png", - "screenshots": [{"url":"screenshot_welcome.png"}], - "tags": "start,welcome", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"welcome.boot.js","url":"boot.js"}, - {"name":"welcome.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, - {"name":"welcome.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, - {"name":"welcome.settings.js","url":"settings.js"}, - {"name":"welcome.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"welcome.json"}] - }, - { - "id": "mywelcome", - "name": "Customised Welcome", - "shortName": "My Welcome", - "version": "0.13", - "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", - "icon": "app.png", - "tags": "start,welcome", - "supports": ["BANGLEJS","BANGLEJS2"], - "custom": "custom.html", - "screenshots": [{"url":"bangle1-customized-welcome-screenshot.png"}], - "storage": [ - {"name":"mywelcome.boot.js","url":"boot.js"}, - {"name":"mywelcome.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, - {"name":"mywelcome.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, - {"name":"mywelcome.settings.js","url":"settings.js"}, - {"name":"mywelcome.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"mywelcome.json"}] - }, - { - "id": "gbridge", - "name": "Gadgetbridge", - "version": "0.25", - "description": "(NOT RECOMMENDED) Displays Gadgetbridge notifications from Android. Please use the 'Android' Bangle.js app instead.", - "icon": "app.png", - "type": "widget", - "tags": "tool,system,android,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "dependencies": {"notify":"type"}, - "readme": "README.md", - "storage": [ - {"name":"gbridge.settings.js","url":"settings.js"}, - {"name":"gbridge.img","url":"app-icon.js","evaluate":true}, - {"name":"gbridge.wid.js","url":"widget.js"} - ], - "data": [{"name":"gbridge.json"}] - }, - { "id": "gbdebug", - "name": "Gadgetbridge Debug", - "shortName":"GB Debug", - "version":"0.01", - "description": "Debug info for Gadgetbridge. Run this app and when Gadgetbridge messages arrive they are displayed on-screen.", - "icon": "app.png", - "tags": "", - "supports" : ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"gbdebug.app.js","url":"app.js"}, - {"name":"gbdebug.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "mclock", - "name": "Morphing Clock", - "version": "0.07", - "description": "7 segment clock that morphs between minutes and hours", - "icon": "clock-morphing.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-morphing-clock-screenshot.png"}], - "storage": [ - {"name":"mclock.app.js","url":"clock-morphing.js"}, - {"name":"mclock.img","url":"clock-morphing-icon.js","evaluate":true} - ], - "sortorder": -9 - }, - { - "id": "moonphase", - "name": "Moonphase", - "version": "0.02", - "description": "Shows current moon phase. Now with GPS function.", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-moon-phase-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"moonphase.app.js","url":"app.js"}, - {"name":"moonphase.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "daysl", - "name": "Days left", - "version": "0.03", - "description": "Shows you the days left until a certain date. Date can be set with a settings app and is written to a file.", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "allow_emulator": false, - "storage": [ - {"name":"daysl.app.js","url":"app.js"}, - {"name":"daysl.img","url":"app-icon.js","evaluate":true}, - {"name":"daysl.wid.js","url":"widget.js"} - ] - }, - { - "id": "wclock", - "name": "Word Clock", - "version": "0.03", - "description": "Display Time as Text", - "icon": "clock-word.png", - "screenshots": [{"url":"screenshot_word.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"wclock.app.js","url":"clock-word.js"}, - {"name":"wclock.img","url":"clock-word-icon.js","evaluate":true} - ] - }, - { - "id": "fontclock", - "name": "Font Clock", - "version": "0.01", - "description": "Choose the font and design of clock face from a library of available designs", - "icon": "fontclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "custom": "custom.html", - "allow_emulator": false, - "storage": [ - {"name":"fontclock.app.js","url":"fontclock.js"}, - {"name":"fontclock.img","url":"fontclock-icon.js","evaluate":true}, - {"name":"fontclock.hand.js","url":"fontclock.hand.js"}, - {"name":"fontclock.thinhand.js","url":"fontclock.thinhand.js"}, - {"name":"fontclock.thickhand.js","url":"fontclock.thickhand.js"}, - {"name":"fontclock.hourscriber.js","url":"fontclock.hourscriber.js"}, - {"name":"fontclock.font.js","url":"fontclock.font.js"}, - {"name":"fontclock.font.abril_ff50.js","url":"fontclock.font.abril_ff50.js"}, - {"name":"fontclock.font.cpstc58.js","url":"fontclock.font.cpstc58.js"}, - {"name":"fontclock.font.mntn25.js","url":"fontclock.font.mntn25.js"}, - {"name":"fontclock.font.mntn50.js","url":"fontclock.font.mntn50.js"}, - {"name":"fontclock.font.vector25.js","url":"fontclock.font.vector25.js"}, - {"name":"fontclock.font.vector50.js","url":"fontclock.font.vector50.js"} - ] - }, - { - "id": "slidingtext", - "name": "Sliding Clock", - "version": "0.07", - "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported", - "icon": "slidingtext.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "custom": "custom.html", - "allow_emulator": false, - "storage": [ - {"name":"slidingtext.app.js","url":"slidingtext.js"}, - {"name":"slidingtext.img","url":"slidingtext-icon.js","evaluate":true}, - {"name":"slidingtext.locale.en.js","url":"slidingtext.locale.en.js"}, - {"name":"slidingtext.locale.en2.js","url":"slidingtext.locale.en2.js"}, - {"name":"slidingtext.utils.en.js","url":"slidingtext.utils.en.js"}, - {"name":"slidingtext.locale.es.js","url":"slidingtext.locale.es.js"}, - {"name":"slidingtext.locale.fr.js","url":"slidingtext.locale.fr.js"}, - {"name":"slidingtext.locale.jp.js","url":"slidingtext.locale.jp.js"}, - {"name":"slidingtext.locale.de.js","url":"slidingtext.locale.de.js"}, - {"name":"slidingtext.dtfmt.js","url":"slidingtext.dtfmt.js"} - ] - }, - { - "id": "solarclock", - "name": "Solar Clock", - "version": "0.02", - "description": "Using your current or chosen location the solar watch face shows the Sun's sky position, time and date. Also allows you to wind backwards and forwards in time to see the sun's position", - "icon": "solar_clock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "custom": "custom.html", - "allow_emulator": false, - "storage": [ - {"name":"solarclock.app.js","url":"solar_clock.js"}, - {"name":"solarclock.img","url":"solar_clock-icon.js","evaluate":true}, - {"name":"solar_colors.js","url":"solar_colors.js"}, - {"name":"solar_controller.js","url":"solar_controller.js"}, - {"name":"solar_date_utils.js","url":"solar_date_utils.js"}, - {"name":"solar_graphic_utils.js","url":"solar_graphic_utils.js"}, - {"name":"solar_location.js","url":"solar_location.js"}, - {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, - {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, - {"name":"solar_loc.Hong_Kong.json","url":"solar_loc.Hong_Kong.json"}, - {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, - {"name":"solar_loc.Rio.json","url":"solar_loc.Rio.json"}, - {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, - {"name":"solar_loc.Seoul.json","url":"solar_loc.Seoul.json"} - ] - }, - { - "id": "sweepclock", - "name": "Sweep Clock", - "version": "0.04", - "description": "Smooth sweep secondhand with single hour numeral. Use button 1 to toggle the numeral font, button 3 to change the colour theme and button 4 to change the date placement", - "icon": "sweepclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-sweep-clock-screenshot.png"}], - "storage": [ - {"name":"sweepclock.app.js","url":"sweepclock.js"}, - {"name":"sweepclock.img","url":"sweepclock-icon.js","evaluate":true} - ] - }, - { - "id": "matrixclock", - "name": "Matrix Clock", - "version": "0.02", - "description": "inspired by The Matrix, a clock of the same style", - "icon": "matrixclock.png", - "screenshots": [{"url":"screenshot_matrix.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"matrixclock.app.js","url":"matrixclock.js"}, - {"name":"matrixclock.img","url":"matrixclock-icon.js","evaluate":true} - ] - }, - { - "id": "mandelbrotclock", - "name": "Mandelbrot Clock", - "version": "0.01", - "description": "A mandelbrot set themed clock cool", - "icon": "mandelbrotclock.png", - "screenshots": [{ "url": "screenshot_mandelbrotclock.png" }], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - { "name": "mandelbrotclock.app.js", "url": "mandelbrotclock.js" }, - { - "name": "mandelbrotclock.img", - "url": "mandelbrotclock-icon.js", - "evaluate": true - } - ] - }, - { - "id": "imgclock", - "name": "Image background clock", - "shortName": "Image Clock", - "version": "0.08", - "description": "A clock with an image as a background", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "custom": "custom.html", - "storage": [ - {"name":"imgclock.app.js","url":"app.js"}, - {"name":"imgclock.img","url":"app-icon.js","evaluate":true}, - {"name":"imgclock.face.img"}, - {"name":"imgclock.face.json"}, - {"name":"imgclock.face.bg","content":""} - ] - }, - { - "id": "impwclock", - "name": "Imprecise Word Clock", - "version": "0.04", - "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", - "icon": "clock-impword.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"impwclock.app.js","url":"clock-impword.js"}, - {"name":"impwclock.img","url":"clock-impword-icon.js","evaluate":true} - ] - }, - { - "id": "aclock", - "name": "Analog Clock", - "version": "0.15", - "description": "An Analog Clock", - "icon": "clock-analog.png", - "screenshots": [{"url":"screenshot_analog.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"aclock.app.js","url":"clock-analog.js"}, - {"name":"aclock.img","url":"clock-analog-icon.js","evaluate":true} - ] - }, - { - "id": "clock2x3", - "name": "2x3 Pixel Clock", - "version": "0.05", - "description": "This is a simple clock using minimalist 2x3 pixel numerical digits", - "icon": "clock2x3.png", - "screenshots": [{"url":"screenshot_pixel.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"clock2x3.app.js","url":"clock2x3-app.js"}, - {"name":"clock2x3.img","url":"clock2x3-icon.js","evaluate":true} - ] - }, - { - "id": "geissclk", - "name": "Geiss Clock", - "version": "0.03", - "description": "7 segment clock with animated background in the style of Ryan Geiss' music visualisation. NOTE: The first run will take ~1 minute to do some precalculation", - "icon": "clock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"geissclk.app.js","url":"clock.js"}, - {"name":"geissclk.precompute.js","url":"precompute.js"}, - {"name":"geissclk.img","url":"clock-icon.js","evaluate":true} - ], - "data": [{"name":"geissclk.0.map"},{"name":"geissclk.1.map"},{"name":"geissclk.2.map"},{"name":"geissclk.3.map"},{"name":"geissclk.4.map"},{"name":"geissclk.5.map"},{"name":"geissclk.0.pal"},{"name":"geissclk.1.pal"},{"name":"geissclk.2.pal"}] - }, - { - "id": "trex", - "name": "T-Rex", - "version": "0.04", - "description": "T-Rex game in the style of Chrome's offline game", - "icon": "trex.png", - "screenshots": [{"url":"screenshot_trex.png"}], - "tags": "game", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"trex.app.js","url":"trex.js"}, - {"name":"trex.img","url":"trex-icon.js","evaluate":true}, - {"name":"trex.settings.js","url":"settings.js"} - ], - "data": [{"name":"trex.score","storageFile":true}] - }, - { - "id": "cubescramble", - "name": "Cube Scramble", - "version":"0.04", - "description": "A random scramble generator for the 3x3 Rubik's cube with a basic timer", - "icon": "cube-scramble.png", - "tags": "", - "supports" : ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle2-cube-scramble-screenshot.png"},{"url":"bangle1-cube-scramble-screenshot.png"}], - "storage": [ - {"name":"cubescramble.app.js","url":"cube-scramble.js"}, - {"name":"cubescramble.img","url":"cube-scramble-icon.js","evaluate":true} - ] - }, - { - "id": "astroid", - "name": "Asteroids!", - "version": "0.03", - "description": "Retro asteroids game", - "icon": "asteroids.png", - "screenshots": [{"url":"screenshot_asteroids.png"}], - "tags": "game", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"astroid.app.js","url":"asteroids.js"}, - {"name":"astroid.img","url":"asteroids-icon.js","evaluate":true} - ] - }, - { - "id": "clickms", - "name": "Click Master", - "version": "0.01", - "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", - "icon": "click-master.png", - "tags": "game", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"clickms.app.js","url":"click-master.js"}, - {"name":"clickms.img","url":"click-master-icon.js","evaluate":true} - ] - }, - { - "id": "horsey", - "name": "Horse Race!", - "version": "0.01", - "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", - "icon": "horse-race.png", - "tags": "game", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"horsey.app.js","url":"horse-race.js"}, - {"name":"horsey.img","url":"horse-race-icon.js","evaluate":true} - ] - }, - { - "id": "compass", - "name": "Compass", - "version": "0.05", - "description": "Simple compass that points North", - "icon": "compass.png", - "screenshots": [{"url":"screenshot_compass.png"}], - "tags": "tool,outdoors", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"compass.app.js","url":"compass.js"}, - {"name":"compass.img","url":"compass-icon.js","evaluate":true} - ] - }, - { - "id": "gpstime", - "name": "GPS Time", - "version": "0.05", - "description": "Update the Bangle.js's clock based on the time from the GPS receiver", - "icon": "gpstime.png", - "tags": "tool,gps", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"gpstime.app.js","url":"gpstime.js"}, - {"name":"gpstime.img","url":"gpstime-icon.js","evaluate":true} - ] - }, - { - "id": "openloc", - "name": "Open Location / Plus Codes", - "shortName": "Open Location", - "version": "0.01", - "description": "Convert your current GPS location to a series of characters", - "icon": "app.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"openloc.app.js","url":"app.js"}, - {"name":"openloc.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "speedo", - "name": "Speedo", - "version": "0.05", - "description": "Show the current speed according to the GPS", - "icon": "speedo.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"speedo.app.js","url":"speedo.js"}, - {"name":"speedo.img","url":"speedo-icon.js","evaluate":true} - ] - }, - { - "id": "gpsrec", - "name": "GPS Recorder", - "version": "0.27", - "description": "Application that allows you to record a GPS track. Can run in background", - "icon": "app.png", - "tags": "tool,outdoors,gps,widget", - "screenshots": [{"url":"screenshot.png"}], - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"gpsrec.app.js","url":"app.js"}, - {"name":"gpsrec.img","url":"app-icon.js","evaluate":true}, - {"name":"gpsrec.wid.js","url":"widget.js"}, - {"name":"gpsrec.settings.js","url":"settings.js"} - ], - "data": [{"name":"gpsrec.json"},{"wildcard":".gpsrc?","storageFile":true}] - }, - { - "id": "recorder", - "name": "Recorder (BETA)", - "shortName": "Recorder", - "version": "0.04", - "description": "Record GPS position, heart rate and more in the background, then download to your PC.", - "icon": "app.png", - "tags": "tool,outdoors,gps,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"recorder.app.js","url":"app.js"}, - {"name":"recorder.img","url":"app-icon.js","evaluate":true}, - {"name":"recorder.wid.js","url":"widget.js"}, - {"name":"recorder.settings.js","url":"settings.js"} - ], - "data": [{"name":"recorder.json"},{"wildcard":"recorder.log?.csv","storageFile":true}] - }, - { - "id": "gpsnav", - "name": "GPS Navigation", - "version": "0.05", - "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording, now with waypoint editor", - "icon": "icon.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "waypoints.html", - "storage": [ - {"name":"gpsnav.app.js","url":"app.min.js"}, - {"name":"gpsnav.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"waypoints.json","url":"waypoints.json"}] - }, - { - "id": "heart", - "name": "Heart Rate Recorder", - "shortName": "HRM Record", - "version": "0.07", - "description": "Application that allows you to record your heart rate. Can run in background", - "icon": "app.png", - "tags": "tool,health,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "interface": "interface.html", - "storage": [ - {"name":"heart.app.js","url":"app.js"}, - {"name":"heart.img","url":"app-icon.js","evaluate":true}, - {"name":"heart.wid.js","url":"widget.js"} - ], - "data": [{"name":"heart.json"},{"wildcard":".heart?","storageFile":true}] - }, - { - "id": "slevel", - "name": "Spirit Level", - "version": "0.02", - "description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat", - "icon": "spiritlevel.png", - "tags": "tool", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"slevel.app.js","url":"spiritlevel.js"}, - {"name":"slevel.img","url":"spiritlevel-icon.js","evaluate":true} - ] - }, - { - "id": "files", - "name": "App Manager", - "version": "0.07", - "description": "Show currently installed apps, free space, and allow their deletion from the watch", - "icon": "files.png", - "tags": "tool,system,files", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"files.app.js","url":"files.js"}, - {"name":"files.img","url":"files-icon.js","evaluate":true} - ] - }, - { - "id": "weather", - "name": "Weather", - "version": "0.13", - "description": "Show Gadgetbridge weather report", - "icon": "icon.png", - "screenshots": [{"url":"screenshot.png"}], - "tags": "widget,outdoors", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "readme.md", - "storage": [ - {"name":"weather.app.js","url":"app.js"}, - {"name":"weather.wid.js","url":"widget.js"}, - {"name":"weather","url":"lib.js"}, - {"name":"weather.img","url":"icon.js","evaluate":true}, - {"name":"weather.settings.js","url":"settings.js"} - ], - "data": [{"name":"weather.json"}] - }, - { - "id": "chargeanim", - "name": "Charge Animation", - "version": "0.02", - "description": "When charging, show a sideways charging animation and keep the screen on. When removed from the charger load the clock again.", - "icon": "icon.png", - "tags": "battery", - "supports": ["BANGLEJS", "BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-charge-animation-screenshot.png"},{"url":"bangle-charge-animation-screenshot.png"}], - "storage": [ - {"name":"chargeanim.app.js","url":"app.js"}, - {"name":"chargeanim.boot.js","url":"boot.js"}, - {"name":"chargeanim.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "bluetoothdock", - "name": "Bluetooth Dock", - "shortName": "Dock", - "version": "0.01", - "description": "When charging shows the time, scans Bluetooth for known devices (eg temperature) and shows them on the screen", - "icon": "app.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"bluetoothdock.app.js","url":"app.js"}, - {"name":"bluetoothdock.boot.js","url":"boot.js"}, - {"name":"bluetoothdock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widbat", - "name": "Battery Level Widget", - "version": "0.09", - "description": "Show the current battery level and charging status in the top right of the clock", - "icon": "widget.png", - "type": "widget", - "tags": "widget,battery", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widbat.wid.js","url":"widget.js"} - ] - }, - { - "id": "widbatv", - "name": "Battery Level Widget (Vertical)", - "version": "0.01", - "description": "Slim, vertical battery widget that only takes up 14px", - "icon": "widget.png", - "type": "widget", - "tags": "widget,battery", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widbatv.wid.js","url":"widget.js"} - ] - }, - { - "id": "widlock", - "name": "Lock Widget", - "version": "0.03", - "description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked", - "icon": "widget.png", - "type": "widget", - "tags": "widget,lock", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widlock.wid.js","url":"widget.js"} - ] - }, - { - "id": "widbatpc", - "name": "Battery Level Widget (with percentage)", - "shortName": "Battery Widget", - "version": "0.14", - "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", - "icon": "widget.png", - "type": "widget", - "tags": "widget,battery", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"widbatpc.wid.js","url":"widget.js"}, - {"name":"widbatpc.settings.js","url":"settings.js"} - ], - "data": [{"name":"widbatpc.json"}] - }, - { - "id": "widbatwarn", - "name": "Battery Warning", - "shortName": "Battery Warning", - "version": "0.02", - "description": "Show a warning when the battery runs low.", - "icon": "widget.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "widget", - "tags": "tool,battery", - "supports": ["BANGLEJS"], - "dependencies": {"notify":"type"}, - "readme": "README.md", - "storage": [ - {"name":"widbatwarn.wid.js","url":"widget.js"}, - {"name":"widbatwarn.settings.js","url":"settings.js"} - ], - "data": [{"name":"widbatwarn.json"}] - }, - { - "id": "widbt", - "name": "Bluetooth Widget", - "version": "0.07", - "description": "Show the current Bluetooth connection status in the top right of the clock", - "icon": "widget.png", - "type": "widget", - "tags": "widget,bluetooth", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widbt.wid.js","url":"widget.js"} - ] - }, - { - "id": "widchime", - "name": "Hour Chime", - "version": "0.02", - "description": "Buzz or beep on every whole hour.", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widchime.wid.js","url":"widget.js"}, - {"name":"widchime.settings.js","url":"settings.js"} - ], - "data": [{"name":"widchime.json"}] - }, - { - "id": "widram", - "name": "RAM Widget", - "shortName": "RAM Widget", - "version": "0.01", - "description": "Display your Bangle's available RAM percentage in a widget", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widram.wid.js","url":"widget.js"} - ] - }, - { - "id": "hrm", - "name": "Heart Rate Monitor", - "version": "0.06", - "description": "Measure your heart rate and see live sensor data", - "icon": "heartrate.png", - "tags": "health", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"hrm.app.js","url":"heartrate.js"}, - {"name":"hrm.img","url":"heartrate-icon.js","evaluate":true} - ] - }, - { - "id": "widhrm", - "name": "Simple Heart Rate widget", - "version": "0.05", - "description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.", - "icon": "widget.png", - "type": "widget", - "tags": "health,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widhrm.wid.js","url":"widget.js"} - ] - }, - { - "id": "bthrm", - "name": "Bluetooth Heart Rate Monitor", - "shortName": "BT HRM", - "version": "0.01", - "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", - "icon": "app.png", - "type": "boot", - "tags": "health,bluetooth", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"bthrm.boot.js","url":"boot.js"}, - {"name":"bthrm.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "stetho", - "name": "Stethoscope", - "version": "0.01", - "description": "Hear your heart rate", - "icon": "stetho.png", - "tags": "health", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"stetho.app.js","url":"stetho.js"}, - {"name":"stetho.img","url":"stetho-icon.js","evaluate":true} - ] - }, - { - "id": "swatch", - "name": "Stopwatch", - "version": "0.07", - "description": "Simple stopwatch with Lap Time logging to a JSON file", - "icon": "stopwatch.png", - "tags": "health", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "interface.html", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-stopwatch-screenshot.png"}], - "storage": [ - {"name":"swatch.app.js","url":"stopwatch.js"}, - {"name":"swatch.img","url":"stopwatch-icon.js","evaluate":true} - ] - }, - { - "id": "hidmsic", - "name": "Bluetooth Music Controls", - "shortName": "Music Control", - "version": "0.02", - "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", - "icon": "hid-music.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"hidmsic.app.js","url":"hid-music.js"}, - {"name":"hidmsic.img","url":"hid-music-icon.js","evaluate":true} - ] - }, - { - "id": "hidkbd", - "name": "Bluetooth Keyboard", - "shortName": "Bluetooth Kbd", - "version": "0.02", - "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", - "icon": "hid-keyboard.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"hidkbd.app.js","url":"hid-keyboard.js"}, - {"name":"hidkbd.img","url":"hid-keyboard-icon.js","evaluate":true} - ] - }, - { - "id": "hidbkbd", - "name": "Binary Bluetooth Keyboard", - "shortName": "Binary BT Kbd", - "version": "0.02", - "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", - "icon": "hid-binary-keyboard.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"hidbkbd.app.js","url":"hid-binary-keyboard.js"}, - {"name":"hidbkbd.img","url":"hid-binary-keyboard-icon.js","evaluate":true} - ] - }, - { - "id": "animals", - "name": "Animals Game", - "version": "0.01", - "description": "Simple toddler's game - displays a different number of animals each time the screen is pressed", - "icon": "animals.png", - "tags": "game", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"animals.app.js","url":"animals.js"}, - {"name":"animals.img","url":"animals-icon.js","evaluate":true}, - {"name":"animals-snake.img","url":"animals-snake.js","evaluate":true}, - {"name":"animals-duck.img","url":"animals-duck.js","evaluate":true}, - {"name":"animals-swan.img","url":"animals-swan.js","evaluate":true}, - {"name":"animals-fox.img","url":"animals-fox.js","evaluate":true}, - {"name":"animals-camel.img","url":"animals-camel.js","evaluate":true}, - {"name":"animals-pig.img","url":"animals-pig.js","evaluate":true}, - {"name":"animals-sheep.img","url":"animals-sheep.js","evaluate":true}, - {"name":"animals-mouse.img","url":"animals-mouse.js","evaluate":true} - ] - }, - { - "id": "qrcode", - "name": "Custom QR Code", - "version": "0.04", - "description": "Use this to upload a customised QR code to Bangle.js", - "icon": "app.png", - "tags": "qrcode", - "supports": ["BANGLEJS","BANGLEJS2"], - "custom": "custom.html", - "customConnect": true, - "storage": [ - {"name":"qrcode.app.js"}, - {"name":"qrcode.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "beer", - "name": "Beer Compass", - "version": "0.01", - "description": "Uploads all the pubs in an area onto your watch, so it can always point you at the nearest one", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "custom": "custom.html", - "storage": [ - {"name":"beer.app.js"}, - {"name":"beer.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "route", - "name": "Route Viewer", - "version": "0.02", - "description": "Upload a KML file of a route, and have your watch display a map with how far around it you are", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "custom": "custom.html", - "storage": [ - {"name":"route.app.js"}, - {"name":"route.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "ncstart", - "name": "NCEU Startup", - "version": "0.06", - "description": "NodeConfEU 2019 'First Start' Sequence", - "icon": "start.png", - "tags": "start,welcome", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"ncstart.app.js","url":"start.js"}, - {"name":"ncstart.boot.js","url":"boot.js"}, - {"name":"ncstart.settings.js","url":"settings.js"}, - {"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}, - {"name":"nc-nfr.img","url":"start-nfr.js","evaluate":true}, - {"name":"nc-nodew.img","url":"start-nodew.js","evaluate":true}, - {"name":"nc-tf.img","url":"start-tf.js","evaluate":true} - ], - "data": [{"name":"ncstart.json"}] - }, - { - "id": "ncfrun", - "name": "NCEU 5K Fun Run", - "version": "0.01", - "description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it", - "icon": "nceu-funrun.png", - "tags": "health", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"ncfrun.app.js","url":"nceu-funrun.js"}, - {"name":"ncfrun.img","url":"nceu-funrun-icon.js","evaluate":true} - ] - }, - { - "id": "widnceu", - "name": "NCEU Logo Widget", - "version": "0.02", - "description": "Show the NodeConf EU logo in the top left", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"widnceu.wid.js","url":"widget.js"} - ] - }, - { - "id": "sclock", - "name": "Simple Clock", - "version": "0.07", - "description": "A Simple Digital Clock", - "icon": "clock-simple.png", - "screenshots": [{"url":"screenshot_simplec.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"sclock.app.js","url":"clock-simple.js"}, - {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} - ] - }, - { - "id": "s7clk", - "name": "Simple 7 segment Clock", - "version": "0.03", - "description": "A simple 7 segment Clock with date", - "icon": "icon.png", - "screenshots": [{"url":"screenshot_s7segment.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"s7clk.app.js","url":"app.js"}, - {"name":"s7clk.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "vibrclock", - "name": "Vibrate Clock", - "version": "0.03", - "description": "When BTN1 is pressed, vibrate out the time as a series of buzzes, one digit at a time. Hours, then Minutes. Zero is signified by one long buzz. Otherwise a simple digital clock.", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-vibrate-clock-screenshot.png"}], - "storage": [ - {"name":"vibrclock.app.js","url":"app.js"}, - {"name":"vibrclock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "svclock", - "name": "Simple V-Clock", - "version": "0.04", - "description": "Modification of Simple Clock 0.04 to use Vectorfont", - "icon": "vclock-simple.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-simple-v-clock-screenshot.png"}], - "storage": [ - {"name":"svclock.app.js","url":"vclock-simple.js"}, - {"name":"svclock.img","url":"vclock-simple-icon.js","evaluate":true} - ] - }, - { - "id": "dclock", - "name": "Dev Clock", - "version": "0.10", - "description": "A Digital Clock including timestamp (tst), beats(@), days in current month (dm) and days since new moon (l)", - "icon": "clock-dev.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-dev-clock-screenshot.png"},{"url":"bangle1-dev-clock-screenshot.png"}], - "storage": [ - {"name":"dclock.app.js","url":"clock-dev.js"}, - {"name":"dclock.img","url":"clock-dev-icon.js","evaluate":true} - ] - }, - { - "id": "gesture", - "name": "Gesture Test", - "version": "0.01", - "description": "BETA! Uploads a basic Tensorflow Gesture model, and then outputs each gesture as a message", - "icon": "gesture.png", - "type": "app", - "tags": "gesture,ai", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"gesture.app.js","url":"gesture.js"}, - {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, - {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, - {"name":"gesture.img","url":"gesture-icon.js","evaluate":true} - ] - }, - { - "id": "pparrot", - "name": "Party Parrot", - "version": "0.01", - "description": "Party with a parrot on your wrist", - "icon": "party-parrot.png", - "type": "app", - "tags": "party,parrot,lol", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-party-parrot-screenshot.png"}], - "storage": [ - {"name":"pparrot.app.js","url":"party-parrot.js"}, - {"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true} - ] - }, - { - "id": "hrings", - "name": "Hypno Rings", - "version": "0.01", - "description": "Experiment with trippy rings, press buttons for change", - "icon": "hypno-rings.png", - "type": "app", - "tags": "rings,hypnosis,psychadelic", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-hypno-rings-screenshot.png"}], - "storage": [ - {"name":"hrings.app.js","url":"hypno-rings.js"}, - {"name":"hrings.img","url":"hypno-rings-icon.js","evaluate":true} - ] - }, - { - "id": "morse", - "name": "Morse Code", - "version": "0.01", - "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", - "icon": "morse-code.png", - "type": "app", - "tags": "morse,sound,visual,input", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"morse.app.js","url":"morse-code.js"}, - {"name":"morse.img","url":"morse-code-icon.js","evaluate":true} - ] - }, - { - "id": "blescan", - "name": "BLE Scanner", - "version": "0.01", - "description": "Scan for advertising BLE devices", - "icon": "blescan.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"blescan.app.js","url":"blescan.js"}, - {"name":"blescan.img","url":"blescan-icon.js","evaluate":true} - ] - }, - { - "id": "mmonday", - "name": "Manic Monday Tone", - "version": "0.02", - "description": "The Bangles make a comeback", - "icon": "manic-monday-icon.png", - "tags": "sound", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"mmonday.app.js","url":"manic-monday.js"}, - {"name":"mmonday.img","url":"manic-monday-icon.js","evaluate":true} - ] - }, - { - "id": "jbells", - "name": "Jingle Bells", - "version": "0.01", - "description": "Play Jingle Bells", - "icon": "jbells.png", - "type": "app", - "tags": "sound", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"jbells.app.js","url":"jbells.js"}, - {"name":"jbells.img","url":"jbells-icon.js","evaluate":true} - ] - }, - { - "id": "scolor", - "name": "Show Color", - "version": "0.01", - "description": "Display all available Colors and Names", - "icon": "show-color.png", - "type": "app", - "tags": "tool", - "screenshots": [{"url":"bangle1-view-color-screenshot.png"}], - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"scolor.app.js","url":"show-color.js"}, - {"name":"scolor.img","url":"show-color-icon.js","evaluate":true} - ] - }, - { - "id": "miclock", - "name": "Mixed Clock", - "version": "0.05", - "description": "A mix of analog and digital Clock", - "icon": "clock-mixed.png", - "type": "clock", - "tags": "clock", - "screenshots": [{"url":"bangle1-mixed-clock-screenshot.png"}], - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"miclock.app.js","url":"clock-mixed.js"}, - {"name":"miclock.img","url":"clock-mixed-icon.js","evaluate":true} - ] - }, - { - "id": "bclock", - "name": "Binary Clock", - "version": "0.03", - "description": "A simple binary clock watch face", - "icon": "clock-binary.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-binary-clock-screenshot.png"}], - "storage": [ - {"name":"bclock.app.js","url":"clock-binary.js"}, - {"name":"bclock.img","url":"clock-binary-icon.js","evaluate":true} - ] - }, - { - "id": "clotris", - "name": "Clock-Tris", - "version": "0.01", - "description": "A fully functional clone of a classic game of falling blocks", - "icon": "clock-tris.png", - "tags": "game", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-clock-tris-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"clotris.app.js","url":"clock-tris.js"}, - {"name":"clotris.img","url":"clock-tris-icon.js","evaluate":true}, - {"name":".trishig","url":"clock-tris-high"} - ] - }, - { - "id": "flappy", - "name": "Flappy Bird", - "version": "0.05", - "description": "A Flappy Bird game clone", - "icon": "app.png", - "screenshots": [{"url":"screenshot1_flappy.png"},{"url":"screenshot2_flappy.png"}], - "tags": "game", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"flappy.app.js","url":"app.js"}, - {"name":"flappy.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "gpsinfo", - "name": "GPS Info", - "version": "0.05", - "description": "An application that displays information about altitude, lat/lon, satellites and time", - "icon": "gps-info.png", - "type": "app", - "tags": "gps", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"gpsinfo.app.js","url":"gps-info.js"}, - {"name":"gpsinfo.img","url":"gps-info-icon.js","evaluate":true} - ] - }, - { - "id": "assistedgps", - "name": "Assisted GPS Update (AGPS)", - "version": "0.01", - "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", - "icon": "app.png", - "type": "RAM", - "tags": "tool,outdoors,agps", - "supports": ["BANGLEJS"], - "custom": "custom.html", - "storage": [] - }, - { - "id": "pomodo", - "name": "Pomodoro", - "version": "0.02", - "description": "A simple pomodoro timer.", - "icon": "pomodoro.png", - "type": "app", - "tags": "pomodoro,cooking,tools", - "supports": ["BANGLEJS", "BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-pomodoro-screenshot.png"}], - "storage": [ - {"name":"pomodo.app.js","url":"pomodoro.js"}, - {"name":"pomodo.img","url":"pomodoro-icon.js","evaluate":true} - ] - }, - { - "id": "blobclk", - "name": "Large Digit Blob Clock", - "shortName": "Blob Clock", - "version": "0.06", - "description": "A clock with big digits", - "icon": "clock-blob.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-large-digit-blob-clock-screenshot.png"},{"url":"bangle1-large-digit-blob-clock-screenshot.png"}], - "storage": [ - {"name":"blobclk.app.js","url":"clock-blob.js"}, - {"name":"blobclk.img","url":"clock-blob-icon.js","evaluate":true} - ] - }, - { - "id": "boldclk", - "name": "Bold Clock", - "version": "0.05", - "description": "Simple, readable and practical clock", - "icon": "bold_clock.png", - "screenshots": [{"url":"screenshot_bold.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"boldclk.app.js","url":"bold_clock.js"}, - {"name":"boldclk.img","url":"bold_clock-icon.js","evaluate":true} - ] - }, - { - "id": "widclk", - "name": "Digital clock widget", - "version": "0.06", - "description": "A simple digital clock widget", - "icon": "widget.png", - "type": "widget", - "tags": "widget,clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widclk.wid.js","url":"widget.js"} - ] - }, - { - "id": "widpedom", - "name": "Pedometer widget", - "version": "0.20", - "description": "Daily pedometer widget", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widpedom.wid.js","url":"widget.js"}, - {"name":"widpedom.settings.js","url":"settings.js"} - ] - }, - { - "id": "berlinc", - "name": "Berlin Clock", - "version": "0.05", - "description": "Berlin Clock (see https://en.wikipedia.org/wiki/Mengenlehreuhr)", - "icon": "berlin-clock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"berlin-clock-screenshot.png"}], - "storage": [ - {"name":"berlinc.app.js","url":"berlin-clock.js"}, - {"name":"berlinc.img","url":"berlin-clock-icon.js","evaluate":true} - ] - }, - { - "id": "ctrclk", - "name": "Centerclock", - "version": "0.03", - "description": "Watch-centered digital 24h clock with date in dd.mm.yyyy format.", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-center-clock-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"ctrclk.app.js","url":"app.js"}, - {"name":"ctrclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "demoapp", - "name": "Demo Loop", - "version": "0.02", - "description": "Simple demo app - displays Bangle.js, JS logo, graphics, and Bangle.js information", - "icon": "app.png", - "type": "app", - "tags": "", - "screenshots": [{"url":"bangle1-demo-loop-screenshot1.png"},{"url":"bangle1-demo-loop-screenshot2.png"},{"url":"bangle1-demo-loop-screenshot3.png"},{"url":"bangle1-demo-loop-screenshot4.png"}], - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"demoapp.app.js","url":"app.js"}, - {"name":"demoapp.img","url":"app-icon.js","evaluate":true} - ], - "sortorder": -9 - }, - { - "id": "flagrse", - "name": "Espruino Flag Raiser", - "version": "0.01", - "description": "App to send a command to another Espruino to cause it to raise a flag", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"flagrse.app.js","url":"app.js"}, - {"name":"flagrse.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "pipboy", - "name": "Pipboy", - "version": "0.04", - "description": "Pipboy themed clock", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-pipboy-themed-clock-screenshot.png"}], - "storage": [ - {"name":"pipboy.app.js","url":"app.js"}, - {"name":"pipboy.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "torch", - "name": "Torch", - "shortName": "Torch", - "version": "0.02", - "description": "Turns screen white to help you see in the dark. Select from the launcher or press BTN1,BTN3,BTN1,BTN3 quickly to start when in any app that shows widgets", - "icon": "app.png", - "tags": "tool,torch", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"torch.app.js","url":"app.js"}, - {"name":"torch.wid.js","url":"widget.js"}, - {"name":"torch.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "rtorch", - "name": "Red Torch", - "shortName": "RedTorch", - "version": "0.02", - "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or on Bangle 1 press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", - "icon": "app.png", - "tags": "tool,torch", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"rtorch.app.js","url":"app.js"}, - {"name":"rtorch.wid.js","url":"widget.js", "supports": ["BANGLEJS"]}, - {"name":"rtorch.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "wohrm", - "name": "Workout HRM", - "version": "0.08", - "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "icon": "app.png", - "type": "app", - "tags": "hrm,workout", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], - "storage": [ - {"name":"wohrm.app.js","url":"app.js"}, - {"name":"wohrm.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widid", - "name": "Bluetooth ID Widget", - "version": "0.03", - "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", - "icon": "widget.png", - "type": "widget", - "tags": "widget,address,mac", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widid.wid.js","url":"widget.js"} - ] - }, - { - "id": "grocery", - "name": "Grocery", - "version": "0.02", - "description": "Simple grocery (shopping) list - Display a list of product and track if you already put them in your cart.", - "icon": "grocery.png", - "type": "app", - "tags": "tool,outdoors,shopping,list", - "supports": ["BANGLEJS"], - "custom": "grocery.html", - "storage": [ - {"name":"grocery.app.js","url":"app.js"}, - {"name":"grocery.img","url":"grocery-icon.js","evaluate":true} - ] - }, - { - "id": "marioclock", - "name": "Mario Clock", - "version": "0.15", - "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", - "icon": "marioclock.png", - "type": "clock", - "tags": "clock,mario,retro", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": false, - "screenshots": [{"url":"bangle1-mario-clock-screenshot.png"}], - "storage": [ - {"name":"marioclock.app.js","url":"marioclock-app.js"}, - {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} - ] - }, - { - "id": "cliock", - "name": "Commandline-Clock", - "shortName": "CLI-Clock", - "version": "0.15", - "description": "Simple CLI-Styled Clock", - "icon": "app.png", - "screenshots": [{"url":"screenshot_cli.png"}], - "type": "clock", - "tags": "clock,cli,command,bash,shell", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"cliock.app.js","url":"app.js"}, - {"name":"cliock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widver", - "name": "Firmware Version Widget", - "version": "0.03", - "description": "Display the version of the installed firmware in the top widget section.", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widver.wid.js","url":"widget.js"} - ] - }, - { - "id": "barclock", - "name": "Bar Clock", - "version": "0.09", - "description": "A simple digital clock showing seconds as a bar", - "icon": "clock-bar.png", - "screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"barclock.app.js","url":"clock-bar.js"}, - {"name":"barclock.img","url":"clock-bar-icon.js","evaluate":true} - ] - }, - { - "id": "dotclock", - "name": "Dot Clock", - "version": "0.03", - "description": "A Minimal Dot Analog Clock", - "icon": "clock-dot.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle2-dot-clcok-screenshot.png"},{"url":"bangle1-dot-clock-screenshot.png"}], - "storage": [ - {"name":"dotclock.app.js","url":"clock-dot.js"}, - {"name":"dotclock.img","url":"clock-dot-icon.js","evaluate":true} - ] - }, - { - "id": "widtbat", - "name": "Tiny Battery Widget", - "version": "0.02", - "description": "Tiny blueish battery widget, vibs and changes level color when charging", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widtbat.wid.js","url":"widget.js"} - ] - }, - { - "id": "chrono", - "name": "Chrono", - "shortName": "Chrono", - "version": "0.01", - "description": "Single click BTN1 to add 5 minutes. Single click BTN2 to add 30 seconds. Single click BTN3 to add 5 seconds. Tap to pause or play to timer. Double click BTN1 to reset. When timer finishes the watch vibrates.", - "icon": "chrono.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"chrono.app.js","url":"chrono.js"}, - {"name":"chrono.img","url":"chrono-icon.js","evaluate":true} - ] - }, - { - "id": "astrocalc", - "name": "Astrocalc", - "version": "0.02", - "description": "Calculates interesting information on the sun and moon cycles for the current day based on your location.", - "icon": "astrocalc.png", - "tags": "app,sun,moon,cycles,tool,outdoors", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"astrocalc.app.js","url":"astrocalc-app.js"}, - {"name":"suncalc.js","url":"suncalc.js"}, - {"name":"astrocalc.img","url":"astrocalc-icon.js","evaluate":true}, - {"name":"first-quarter.img","url":"first-quarter-icon.js","evaluate":true}, - {"name":"last-quarter.img","url":"last-quarter-icon.js","evaluate":true}, - {"name":"waning-crescent.img","url":"waning-crescent-icon.js","evaluate":true}, - {"name":"waning-gibbous.img","url":"waning-gibbous-icon.js","evaluate":true}, - {"name":"full.img","url":"full-icon.js","evaluate":true}, - {"name":"new.img","url":"new-icon.js","evaluate":true}, - {"name":"waxing-gibbous.img","url":"waxing-gibbous-icon.js","evaluate":true}, - {"name":"waxing-crescent.img","url":"waxing-crescent-icon.js","evaluate":true} - ] - }, - { - "id": "widhwt", - "name": "Hand Wash Timer", - "version": "0.01", - "description": "Swipe your wrist over the watch face to start your personal Bangle.js hand wash timer for 35 sec. Start washing after the short buzz and stop after the long buzz.", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tool", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"widhwt.wid.js","url":"widget.js"} - ] - }, - { - "id": "toucher", - "name": "Touch Launcher", - "shortName": "Toucher", - "version": "0.07", - "description": "Touch enable left to right launcher.", - "icon": "app.png", - "type": "launch", - "tags": "tool,system,launcher", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"toucher.app.js","url":"app.js"}, - {"name":"toucher.settings.js","url":"settings.js"} - ], - "data": [{"name":"toucher.json"}] - }, - { - "id": "balltastic", - "name": "Balltastic", - "version": "0.02", - "description": "Simple but fun ball eats dots game.", - "icon": "app.png", - "type": "app", - "tags": "game,fun", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"balltastic.app.js","url":"app.js"}, - {"name":"balltastic.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "rpgdice", - "name": "RPG dice", - "version": "0.02", - "description": "Simple RPG dice rolling app.", - "icon": "rpgdice.png", - "type": "app", - "tags": "game,fun", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-rpg-dice-screenshot.png"}], - "storage": [ - {"name":"rpgdice.app.js","url":"app.js"}, - {"name":"rpgdice.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widmp", - "name": "Moon Phase Widget", - "version": "0.02", - "description": "Display the current moon phase in blueish for the northern hemisphere in eight phases", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tools", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widmp.wid.js","url":"widget.js"} - ] - }, - { - "id": "widmpsh", - "name": "Moon Phase Widget Southern Hemisphere", - "version": "0.01", - "description": "Display the current moon phase in blueish for the southern hemisphere in eight phases", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tools", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widmpsh.wid.js","url":"widget.js"} - ] - }, - { - "id": "minionclk", - "name": "Minion clock", - "version": "0.05", - "description": "Minion themed clock.", - "icon": "minionclk.png", - "type": "clock", - "tags": "clock,minion", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-minion-clock-screenshot.png"}], - "storage": [ - {"name":"minionclk.app.js","url":"app.js"}, - {"name":"minionclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "openstmap", - "name": "OpenStreetMap", - "shortName": "OpenStMap", - "version": "0.11", - "description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps", - "icon": "app.png", - "tags": "outdoors,gps,osm", - "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}], - "custom": "custom.html", - "customConnect": true, - "storage": [ - {"name":"openstmap","url":"openstmap.js"}, - {"name":"openstmap.app.js","url":"app.js"}, - {"name":"openstmap.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "activepedom", - "name": "Active Pedometer", - "shortName": "Active Pedometer", - "version": "0.09", - "description": "Pedometer that filters out arm movement and displays a step goal progress. Steps are saved to a daily file and can be viewed as graph.", - "icon": "app.png", - "tags": "outdoors,widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"activepedom.wid.js","url":"widget.js"}, - {"name":"activepedom.settings.js","url":"settings.js"}, - {"name":"activepedom.img","url":"app-icon.js","evaluate":true}, - {"name":"activepedom.app.js","url":"app.js"} - ] - }, - { - "id": "chronowid", - "name": "Chrono Widget", - "shortName": "Chrono Widget", - "version": "0.04", - "description": "Chronometer (timer) which runs as widget.", - "icon": "app.png", - "tags": "tool,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}], - "readme": "README.md", - "storage": [ - {"name":"chronowid.wid.js","url":"widget.js"}, - {"name":"chronowid.app.js","url":"app.js"}, - {"name":"chronowid.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "tabata", - "name": "Tabata", - "shortName": "Tabata - Control High-Intensity Interval Training", - "version": "0.01", - "description": "Control high-intensity interval training (according to tabata: https://en.wikipedia.org/wiki/Tabata_method).", - "icon": "tabata.png", - "tags": "workout,health", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"tabata.app.js","url":"tabata.js"}, - {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} - ] - }, - { - "id": "custom", - "name": "Custom Boot Code ", - "version": "0.01", - "description": "Add code you want to run at boot time", - "icon": "custom.png", - "type": "bootloader", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "custom": "custom.html", - "storage": [ - {"name":"custom"} - ] - }, - { - "id": "devstopwatch", - "name": "Dev Stopwatch", - "shortName": "Dev Stopwatch", - "version": "0.03", - "description": "Stopwatch with 5 laps supported (cyclically replaced)", - "icon": "app.png", - "tags": "stopwatch,chrono,timer,chronometer", - "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"devstopwatch.app.js","url":"app.js"}, - {"name":"devstopwatch.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "batchart", - "name": "Battery Chart", - "shortName": "Battery Chart", - "version": "0.10", - "description": "A widget and an app for recording and visualizing battery percentage over time.", - "icon": "app.png", - "tags": "app,widget,battery,time,record,chart,tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"batchart.wid.js","url":"widget.js"}, - {"name":"batchart.app.js","url":"app.js"}, - {"name":"batchart.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "nato", - "name": "NATO Alphabet", - "shortName": "NATOAlphabet", - "version": "0.01", - "description": "Learn the NATO Phonetic alphabet plus some numbers.", - "icon": "nato.png", - "type": "app", - "tags": "app,learn,visual", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-NATO-alphabet-screenshot.png"},{"url":"bangle1-NATO-alphabet-screenshot2.png"}], - "storage": [ - {"name":"nato.app.js","url":"nato.js"}, - {"name":"nato.img","url":"nato-icon.js","evaluate":true} - ] - }, - { - "id": "numerals", - "name": "Numerals Clock", - "shortName": "Numerals Clock", - "version": "0.10", - "description": "A simple big numerals clock", - "icon": "numerals.png", - "type": "clock", - "tags": "numerals,clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-numerals-screenshot.png"}], - "storage": [ - {"name":"numerals.app.js","url":"numerals.app.js"}, - {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, - {"name":"numerals.settings.js","url":"numerals.settings.js"} - ], - "data": [{"name":"numerals.json"}] - }, - { - "id": "bledetect", - "name": "BLE Detector", - "shortName": "BLE Detector", - "version": "0.03", - "description": "Detect BLE devices and show some informations.", - "icon": "bledetect.png", - "tags": "app,bluetooth,tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"bledetect.app.js","url":"bledetect.js"}, - {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} - ] - }, - { - "id": "snake", - "name": "Snake", - "shortName": "Snake", - "version": "0.02", - "description": "The classic snake game. Eat apples and don't bite your tail.", - "icon": "snake.png", - "tags": "game,fun", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"snake.app.js","url":"snake.js"}, - {"name":"snake.img","url":"snake-icon.js","evaluate":true} - ] - }, - { "id": "snek", - "name": "The snek game", - "shortName":"Snek", - "version": "0.02", - "description": "A snek game where you control a snek to eat all the apples!", - "screenshots": [{"url":"screenshot_snek.png"}], - "icon": "snek.png", - "supports": ["BANGLEJS2"], - "tags": "game,fun", - "storage": [ - {"name":"snek.app.js","url":"snek.js"}, - {"name":"snek.img","url":"snek.icon.js","evaluate":true} - ] - }, - { - "id": "calculator", - "name": "Calculator", - "shortName": "Calculator", - "version": "0.04", - "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", - "icon": "calculator.png", - "screenshots": [{"url":"screenshot_calculator.png"}], - "tags": "app,tool", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"calculator.app.js","url":"app.js"}, - {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} - ] - }, - { - "id": "dane", - "name": "Digital Assistant, not EDITH", - "shortName": "DANE", - "version": "0.16", - "description": "A Watchface inspired by Tony Stark's EDITH and based on https://arwes.dev/", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"dane.app.js","url":"app.js"}, - {"name":"dane.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "dane_tcr", - "name": "DANE Touch Launcher", - "shortName": "DANE Toucher", - "version": "0.07", - "description": "Touch enable left to right launcher in the style of the DANE Watchface", - "icon": "app.png", - "type": "launch", - "tags": "tool,system,launcher", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"dane_tcr.app.js","url":"app.js"}, - {"name":"dane_tcr.settings.js","url":"settings.js"} - ], - "data": [{"name":"dane_tcr.json"}] - }, - { - "id": "buffgym", - "name": "BuffGym", - "version": "0.02", - "description": "BuffGym is the famous 5x5 workout program for the BangleJS", - "icon": "buffgym.png", - "type": "app", - "tags": "tool,outdoors,gym,exercise", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "buffgym.html", - "allow_emulator": false, - "storage": [ - {"name":"buffgym.app.js","url":"buffgym.app.js"}, - {"name":"buffgym-set.js","url":"buffgym-set.js"}, - {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, - {"name":"buffgym-workout.js","url":"buffgym-workout.js"}, - {"name":"buffgym-workout-a.json","url":"buffgym-workout-a.json"}, - {"name":"buffgym-workout-b.json","url":"buffgym-workout-b.json"}, - {"name":"buffgym-workout-index.json","url":"buffgym-workout-index.json"}, - {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} - ] - }, - { - "id": "banglerun", - "name": "BangleRun", - "shortName": "BangleRun", - "version": "0.10", - "description": "An app for running sessions. Displays info and logs your run for later viewing.", - "icon": "banglerun.png", - "tags": "run,running,fitness,outdoors", - "supports": ["BANGLEJS"], - "interface": "interface.html", - "allow_emulator": false, - "storage": [ - {"name":"banglerun.app.js","url":"app.js"}, - {"name":"banglerun.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "metronome", - "name": "Metronome", - "version": "0.07", - "readme": "README.md", - "description": "Makes the watch blinking and vibrating with a given rate", - "icon": "metronome_icon.png", - "tags": "tool", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-metronome-screenshot.png"}], - "storage": [ - {"name":"metronome.app.js","url":"metronome.js"}, - {"name":"metronome.img","url":"metronome-icon.js","evaluate":true}, - {"name":"metronome.settings.js","url":"settings.js"} - ] - }, - { - "id": "blackjack", - "name": "Black Jack game", - "shortName": "Black Jack game", - "version": "0.02", - "description": "Simple implementation of card game Black Jack", - "icon": "blackjack.png", - "tags": "game", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-black-jack-game-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"blackjack.app.js","url":"blackjack.app.js"}, - {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} - ] - }, - { - "id": "hidcam", - "name": "Camera shutter", - "shortName": "Cam shutter", - "version": "0.03", - "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", - "icon": "app.png", - "tags": "bluetooth,tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"hidcam.app.js","url":"app.js"}, - {"name":"hidcam.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "swlclk", - "name": "SWL Clock / Short Wave Listner Clock", - "shortName": "SWL Clock", - "version": "0.02", - "description": "Display Local, UTC time and some programs on the shorts waves along the day, with the frequencies", - "icon": "swlclk.png", - "type": "clock", - "tags": "tool,clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-SWL-clock-screenshot.png"}], - "storage": [ - {"name":"swlclk.app.js","url":"app.js"}, - {"name":"swlclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "rclock", - "name": "Round clock with seconds, minutes and date", - "shortName": "Round Clock", - "version": "0.06", - "description": "Designed round clock with ticks for minutes and seconds and heart rate indication", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"rclock.app.js","url":"rclock.app.js"}, - {"name":"rclock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "fclock", - "name": "fclock", - "shortName": "F Clock", - "version": "0.02", - "description": "Simple design of a digital clock", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"fclock.app.js","url":"fclock.app.js"}, - {"name":"fclock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "hamloc", - "name": "QTH Locator / Maidenhead Locator System", - "shortName": "QTH Locator", - "version": "0.01", - "description": "Convert your current GPS location to the Maidenhead locator system used by HAM amateur radio operators", - "icon": "app.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"hamloc.app.js","url":"app.js"}, - {"name":"hamloc.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "osmpoi", - "name": "POI Compass", - "version": "0.03", - "description": "Uploads all the points of interest in an area onto your watch, same as Beer Compass with more p.o.i.", - "icon": "app.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "custom": "custom.html", - "storage": [ - {"name":"osmpoi.app.js"}, - {"name":"osmpoi.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "pong", - "name": "Pong", - "shortName": "Pong", - "version": "0.03", - "description": "A clone of the Atari game Pong", - "icon": "pong.png", - "type": "app", - "tags": "game", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-pong-screenshot.png"}], - "storage": [ - {"name":"pong.app.js","url":"app.js"}, - {"name":"pong.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "ballmaze", - "name": "Ball Maze", - "version": "0.02", - "description": "Navigate a ball through a maze by tilting your watch.", - "icon": "icon.png", - "type": "app", - "tags": "game", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"ballmaze.app.js","url":"app.js"}, - {"name":"ballmaze.img","url":"icon.js","evaluate":true} - ], - "data": [{"name":"ballmaze.json"}] - }, - { - "id": "calendar", - "name": "Calendar", - "version": "0.04", - "description": "Simple calendar", - "icon": "calendar.png", - "screenshots": [{"url":"screenshot_calendar.png"}], - "tags": "calendar", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"calendar.app.js","url":"calendar.js"}, - {"name":"calendar.settings.js","url":"settings.js"}, - {"name":"calendar.img","url":"calendar-icon.js","evaluate":true} - ], - "data": [{"name":"calendar.json"}] - }, - { - "id": "hidjoystick", - "name": "Bluetooth Joystick", - "shortName": "Joystick", - "version": "0.01", - "description": "Emulates a 2 axis/5 button Joystick using the accelerometer as stick input and buttons 1-3, touch left as button 4 and touch right as button 5.", - "icon": "app.png", - "tags": "bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"hidjoystick.app.js","url":"app.js"}, - {"name":"hidjoystick.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "largeclock", - "name": "Large Clock", - "version": "0.10", - "description": "A readable and informational digital watch, with date, seconds and moon phase", - "icon": "largeclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-large-clock-screenshot.png"}], - "storage": [ - {"name":"largeclock.app.js","url":"largeclock.js"}, - {"name":"largeclock.img","url":"largeclock-icon.js","evaluate":true}, - {"name":"largeclock.settings.js","url":"settings.js"} - ], - "data": [{"name":"largeclock.json"}] - }, - { - "id": "smtswch", - "name": "Smart Switch", - "shortName": "Smart Switch", - "version": "0.01", - "description": "Using EspruinoHub, control your smart devices on and off via Bluetooth Low Energy!", - "icon": "app.png", - "type": "app", - "tags": "bluetooth,btle,smart,switch", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"smtswch.app.js","url":"app.js"}, - {"name":"smtswch.img","url":"app-icon.js","evaluate":true}, - {"name":"light-on.img","url":"light-on.js","evaluate":true}, - {"name":"light-off.img","url":"light-off.js","evaluate":true}, - {"name":"switch-on.img","url":"switch-on.js","evaluate":true}, - {"name":"switch-off.img","url":"switch-off.js","evaluate":true} - ] - }, - { - "id": "miplant", - "name": "Xiaomi Plant Sensor", - "shortName": "Mi Plant", - "version": "0.02", - "description": "Reads and displays data from Xiaomi bluetooth plant moisture sensors", - "icon": "app.png", - "tags": "xiaomi,mi,plant,ble,bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"miplant.app.js","url":"app.js"}, - {"name":"miplant.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "simpletimer", - "name": "Timer", - "version": "0.07", - "description": "Simple timer, useful when playing board games or cooking", - "icon": "app.png", - "tags": "timer", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-timer-screenshot.png"}], - "storage": [ - {"name":"simpletimer.app.js","url":"app.js"}, - {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, - {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, - {"name":"simpletimer.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"simpletimer.json"}] - }, - { - "id": "beebclock", - "name": "Beeb Clock", - "version": "0.05", - "description": "Clock face that may be coincidentally familiar to BBC viewers", - "icon": "beebclock.png", - "type": "clock", - "tags": "clock", - "screenshots": [{"url":"bangle1-beeb-clock-screenshot.png"}], - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"beebclock.app.js","url":"beebclock.js"}, - {"name":"beebclock.img","url":"beebclock-icon.js","evaluate":true} - ] - }, - { - "id": "findphone", - "name": "Find Phone", - "shortName": "Find Phone", - "version": "0.03", - "description": "Find your phone via Gadgetbridge. Click any button to let your phone ring. 📳 Note: The functionality is available even without this app, just go to Settings, App Settings, Gadgetbridge, Find Phone.", - "icon": "app.png", - "tags": "tool,android", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"findphone.app.js","url":"app.js"}, - {"name":"findphone.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "getup", - "name": "Get Up", - "shortName": "Get Up", - "version": "0.01", - "description": "Reminds you to getup every x minutes. Sitting to long is dangerous!", - "icon": "app.png", - "tags": "tools,health", - "supports": ["BANGLEJS"], - "readme": "README.md", - "screenshots": [{"url":"bangle1-get-up-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"getup.app.js","url":"app.js"}, - {"name":"getup.settings.js","url":"settings.js"}, - {"name":"getup.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "gallifr", - "name": "Time Traveller's Chronometer", - "shortName": "Time Travel Clock", - "version": "0.02", - "description": "A clock for time travellers. The light pie segment shows the minutes, the black circle, the hour. The dial itself reads 'time' just in case you forget.", - "icon": "gallifr.png", - "screenshots": [{"url":"screenshot_time.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"gallifr.app.js","url":"app.js"}, - {"name":"gallifr.img","url":"app-icon.js","evaluate":true}, - {"name":"gallifr.settings.js","url":"settings.js"} - ], - "data": [{"name":"gallifr.json"}] - }, - { - "id": "rndmclk", - "name": "Random Clock Loader", - "version": "0.03", - "description": "Load a different clock whenever the LCD is switched on.", - "icon": "rndmclk.png", - "type": "widget", - "tags": "widget,clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"rndmclk.wid.js","url":"widget.js"} - ] - }, - { - "id": "dotmatrixclock", - "name": "Dotmatrix Clock", - "version": "0.01", - "description": "A clear white-on-blue dotmatrix simulated clock", - "icon": "dotmatrixclock.png", - "type": "clock", - "tags": "clock,dotmatrix,retro", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"dotmatrixclock.app.js","url":"app.js"}, - {"name":"dotmatrixclock.img","url":"dotmatrixclock-icon.js","evaluate":true} - ] - }, - { - "id": "jbm8b", - "name": "Magic 8 Ball", - "shortName": "Magic 8 Ball", - "version": "0.03", - "description": "A simple fortune telling app", - "icon": "app.png", - "tags": "game", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"jbm8b.app.js","url":"app.js"}, - {"name":"jbm8b.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "jbm8b_IT", - "name": "Magic 8 Ball Italiano", - "shortName": "Magic 8 Ball IT", - "version": "0.01", - "description": "La palla predice il futuro", - "icon": "app.png", - "screenshots": [{"url":"bangle1-magic-8-ball-italiano-screenshot.png"}], - "tags": "game", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"jbm8b_IT.app.js","url":"app.js"}, - {"name":"jbm8b_IT.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "BLEcontroller", - "name": "BLE Customisable Controller with Joystick", - "shortName": "BLE Controller", - "version": "0.01", - "description": "A configurable controller for BLE devices and robots, with a basic four direction joystick. Designed to be easy to customise so you can add your own menus.", - "icon": "BLEcontroller.png", - "tags": "tool,bluetooth", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": false, - "storage": [ - {"name":"BLEcontroller.app.js","url":"app.js"}, - {"name":"BLEcontroller.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widviz", - "name": "Widget Visibility Widget", - "shortName": "Viz Widget", - "version": "0.03", - "description": "Swipe left to hide top bar widgets, swipe right to redisplay.", - "icon": "eye.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widviz.wid.js","url":"widget.js"} - ] - }, - { - "id": "binclock", - "name": "Binary Clock", - "shortName": "Binary Clock", - "version": "0.03", - "description": "A binary clock with hours and minutes. BTN1 toggles a digital clock.", - "icon": "app.png", - "type": "clock", - "tags": "clock,binary", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"binclock.app.js","url":"app.js"}, - {"name":"binclock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "pizzatimer", - "name": "Pizza Timer", - "shortName": "Pizza Timer", - "version": "0.01", - "description": "A timer app for when you cook Pizza. Some say it can also time other things", - "icon": "pizza.png", - "tags": "timer,tool,pizza", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"pizzatimer.app.js","url":"app.js"}, - {"name":"pizzatimer.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "animclk", - "name": "Animated Clock", - "shortName": "Anim Clock", - "version": "0.03", - "description": "An animated clock face using Mark Ferrari's amazing 8 bit game art and palette cycling: http://www.markferrari.com/art/8bit-game-art", - "icon": "app.png", - "type": "clock", - "tags": "clock,animated", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"animclk.app.js","url":"app.js"}, - {"name":"animclk.pixels1","url":"animclk.pixels1"}, - {"name":"animclk.pixels2","url":"animclk.pixels2"}, - {"name":"animclk.pal","url":"animclk.pal"}, - {"name":"animclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "analogimgclk", - "name": "Analog Clock (Image background)", - "shortName": "Analog Clock", - "version": "0.03", - "description": "An analog clock with an image background", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"analogimgclk.app.js","url":"app.js"}, - {"name":"analogimgclk.bg.img","url":"bg.img"}, - {"name":"analogimgclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "verticalface", - "name": "Vertical watch face", - "shortName": "Vertical Face", - "version": "0.09", - "description": "A simple vertical watch face with the date. Heart rate monitor is toggled with BTN1", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "screenshots": [{"url":"bangle1-vertical-watch-face-screenshot.png"}], - "storage": [ - {"name":"verticalface.app.js","url":"app.js"}, - {"name":"verticalface.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "sleepphasealarm", - "name": "SleepPhaseAlarm", - "shortName": "SleepPhaseAlarm", - "version": "0.02", - "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", - "icon": "app.png", - "tags": "alarm", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"sleepphasealarm.app.js","url":"app.js"}, - {"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "life", - "name": "Game of Life", - "version": "0.04", - "description": "Conway's Game of Life - 16x16 board", - "icon": "life.png", - "tags": "game", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-game-of-life-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"life.app.js","url":"life.min.js"}, - {"name":"life.img","url":"life-icon.js","evaluate":true} - ] - }, - { - "id": "magnav", - "name": "Navigation Compass", - "version": "0.05", - "description": "Compass with linear display as for GPSNAV. Has Tilt compensation and remembers calibration.", - "screenshots": [{"url":"screenshot-b2.png"},{"url":"screenshot-light-b2.png"}], - "icon": "magnav.png", - "tags": "tool,outdoors", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"magnav.app.js","url":"magnav_b1.js","supports":["BANGLEJS"]}, - {"name":"magnav.app.js","url":"magnav_b2.js","supports":["BANGLEJS2"]}, - {"name":"magnav.img","url":"magnav-icon.js","evaluate":true} - ], - "data": [{"name":"magnav.json"}] - }, - { - "id": "gpspoilog", - "name": "GPS POI Logger", - "shortName": "GPS POI Log", - "version": "0.01", - "description": "A simple app to log points of interest with their GPS coordinates and read them back onto your PC. Based on the https://www.espruino.com/Bangle.js+Storage tutorial", - "icon": "app.png", - "tags": "outdoors", - "supports": ["BANGLEJS"], - "interface": "interface.html", - "storage": [ - {"name":"gpspoilog.app.js","url":"app.js"}, - {"name":"gpspoilog.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "miclock2", - "name": "Mixed Clock 2", - "version": "0.01", - "description": "White color variant of the Mixed Clock with thicker clock hands for better readability in the bright sunlight, extra space under the clock for widgets and seconds in the digital clock.", - "icon": "clock-mixed.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-mixed-clock-2-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"miclock2.app.js","url":"clock-mixed.js"}, - {"name":"miclock2.img","url":"clock-mixed-icon.js","evaluate":true} - ] - }, - { - "id": "1button", - "name": "One-Button-Tracker", - "version": "0.01", - "description": "A widget that turns BTN1 into a tracker, records time of button press/release.", - "icon": "widget.png", - "type": "widget", - "tags": "tool,quantifiedself,widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"1button.wid.js","url":"widget.js"} - ], - "data": [{"name":"one_button_presses.csv","storageFile":true}] - }, - { - "id": "gpsautotime", - "name": "GPS auto time", - "shortName": "GPS auto time", - "version": "0.01", - "description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.", - "icon": "widget.png", - "type": "widget", - "tags": "widget,gps", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"gpsautotime.wid.js","url":"widget.js"} - ] - }, - { - "id": "espruinoctrl", - "name": "Espruino Control", - "shortName": "Espruino Ctrl", - "version": "0.01", - "description": "Send commands to other Espruino devices via the Bluetooth UART interface. Customisable commands!", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "custom": "custom.html", - "storage": [ - {"name":"espruinoctrl.app.js"}, - {"name":"espruinoctrl.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "multiclock", - "name": "Multi Clock", - "version": "0.09", - "description": "Clock with multiple faces. Switch between faces with BTN1 & BTN3 (Bangle 2 touch top-right, bottom right). For best display set theme Background 2 to cyan or some other bright colour in settings.", - "screenshots": [{"url":"screen-ana.png"},{"url":"screen-big.png"},{"url":"screen-td.png"},{"url":"screen-nifty.png"},{"url":"screen-word.png"},{"url":"screen-sec.png"}], - "icon": "multiclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"multiclock.app.js","url":"multiclock.app.js"}, - {"name":"big.face.js","url":"big.face.js"}, - {"name":"ana.face.js","url":"ana.face.js"}, - {"name":"digi.face.js","url":"digi.face.js"}, - {"name":"txt.face.js","url":"txt.face.js"}, - {"name":"dk.face.js","url":"dk.face.js"}, - {"name":"nifty.face.js","url":"nifty.face.js"}, - {"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true} - ] - }, - { - "id": "widancs", - "name": "Apple Notification Widget", - "shortName": "ANCS Widget", - "version": "0.07", - "description": "Displays call, message etc notifications from a paired iPhone. Read README before installation as it only works with compatible apps", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"widancs.wid.js","url":"ancs.min.js"}, - {"name":"widancs.settings.js","url":"settings.js"} - ] - }, - { - "id": "accelrec", - "name": "Acceleration Recorder", - "shortName": "Accel Rec", - "version": "0.02", - "description": "This app puts the Bangle's accelerometer into 100Hz mode and reads 2 seconds worth of data after movement starts. The data can then be exported back to the PC.", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"accelrec.app.js","url":"app.js"}, - {"name":"accelrec.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"wildcard":"accelrec.?.csv"}] - }, - { - "id": "accellog", - "name": "Acceleration Logger", - "shortName": "Accel Log", - "version": "0.03", - "description": "Logs XYZ acceleration data to a CSV file that can be downloaded to your PC", - "icon": "app.png", - "tags": "outdoor", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"accellog.app.js","url":"app.js"}, - {"name":"accellog.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"wildcard":"accellog.?.csv"}] - }, - { - "id": "cprassist", - "name": "CPR Assist", - "version": "0.01", - "description": "Provides assistance while performing a CPR", - "icon": "cprassist-icon.png", - "tags": "tool,firstaid", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-CPR-assist-screenshot.png"}], - "storage": [ - {"name":"cprassist.app.js","url":"cprassist.js"}, - {"name":"cprassist.img","url":"cprassist-icon.js","evaluate":true}, - {"name":"cprassist.settings.js","url":"settings.js"} - ] - }, - { - "id": "osgridref", - "name": "Ordnance Survey Grid Reference", - "shortName": "OS Grid ref", - "version": "0.01", - "description": "Displays the UK Ordnance Survey grid reference of your current GPS location. Useful when in the United Kingdom with an Ordnance Survey map", - "icon": "app.png", - "tags": "outdoors,gps", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"osgridref.app.js","url":"app.js"}, - {"name":"osgridref.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "openseizure", - "name": "OpenSeizureDetector Widget", - "shortName": "Short Name", - "version": "0.01", - "description": "[BETA!] A widget to work alongside [OpenSeizureDetector](https://www.openseizuredetector.org.uk/)", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"openseizure.wid.js","url":"widget.js"} - ] - }, - { - "id": "counter", - "name": "Counter", - "version": "0.03", - "description": "Simple counter", - "icon": "counter_icon.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-counter-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"counter.app.js","url":"counter.js"}, - {"name":"counter.img","url":"counter-icon.js","evaluate":true} - ] - }, - { - "id": "bootgattbat", - "name": "BLE GATT Battery Service", - "shortName": "BLE Battery Service", - "version": "0.01", - "description": "Adds the GATT Battery Service to advertise the percentage of battery currently remaining over Bluetooth.\n", - "icon": "bluetooth.png", - "type": "bootloader", - "tags": "battery,ble,bluetooth,gatt", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"gattbat.boot.js","url":"boot.js"} - ] - }, - { - "id": "viewstl", - "name": "STL file viewer", - "shortName": "ViewSTL", - "version": "0.02", - "description": "This app allows you to view STL 3D models on your watch", - "icon": "icons8-octahedron-48.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"viewstl.app.js","url":"viewstl.min.js"}, - {"name":"viewstl.img","url":"viewstl-icon.js","evaluate":true}, - {"name":"tetra.stl","url":"tetra.stl"}, - {"name":"cube.stl","url":"cube.stl"}, - {"name":"icosa.stl","url":"icosa.stl"} - ] - }, - { - "id": "cscsensor", - "name": "Cycling speed sensor", - "shortName": "CSCSensor", - "version": "0.06", - "description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch", - "icon": "icons8-cycling-48.png", - "tags": "outdoors,exercise,ble,bluetooth", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"cscsensor.app.js","url":"cscsensor.app.js"}, - {"name":"cscsensor.settings.js","url":"settings.js"}, - {"name":"cscsensor.img","url":"cscsensor-icon.js","evaluate":true} - ] - }, - { - "id": "fileman", - "name": "File manager", - "shortName": "FileManager", - "version": "0.03", - "description": "Simple file manager, allows user to examine watch storage and display, load or delete individual files", - "icon": "icons8-filing-cabinet-48.png", - "tags": "tools", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"fileman.app.js","url":"fileman.app.js"}, - {"name":"fileman.img","url":"fileman-icon.js","evaluate":true} - ] - }, - { - "id": "worldclock", - "name": "World Clock - 4 time zones", - "shortName": "World Clock", - "version": "0.05", - "description": "Current time zone plus up to four others", - "icon": "app.png", - "screenshots": [{"url":"screenshot_world.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "custom": "custom.html", - "storage": [ - {"name":"worldclock.app.js","url":"app.js"}, - {"name":"worldclock.img","url":"worldclock-icon.js","evaluate":true} - ], - "data": [{"name":"worldclock.settings.json"}] - }, - { - "id": "digiclock", - "name": "Digital Clock Face", - "shortName": "Digi Clock", - "version": "0.02", - "description": "A simple digital clock with the time, day, month, and year", - "icon": "digiclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"digiclock.app.js","url":"digiclock.js"}, - {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} - ] - }, - { - "id": "dsdrelay", - "name": "DSD BLE Relay controller", - "shortName": "DSDRelay", - "version": "0.01", - "description": "Control BLE relay board from the watch", - "icon": "icons8-relay-48.png", - "tags": "ble,bluetooth", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"dsdrelay.app.js","url":"dsdrelay.app.js"}, - {"name":"dsdrelay.img","url":"dsdrelay-icon.js","evaluate":true} - ] - }, - { - "id": "mandel", - "name": "Mandelbrot", - "shortName": "Mandel", - "version": "0.01", - "description": "Draw a zoomable Mandelbrot set", - "icon": "mandel.png", - "tags": "game", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"mandel.app.js","url":"mandel.min.js"}, - {"name":"mandel.img","url":"mandel-icon.js","evaluate":true} - ] - }, - { - "id": "petrock", - "name": "Pet rock", - "version": "0.02", - "description": "A virtual pet rock with wobbly eyes", - "icon": "petrock.png", - "type": "app", - "tags": "game", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"petrock.app.js","url":"app.js"}, - {"name":"petrock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "smartibot", - "name": "Smartibot controller", - "shortName": "Smartibot", - "version": "0.01", - "description": "Control a [Smartibot Robot](https://thecraftyrobot.net/) straight from your Bangle.js", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"smartibot.app.js","url":"app.js"}, - {"name":"smartibot.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widncr", - "name": "NCR Logo Widget", - "version": "0.01", - "description": "Show the NodeConf Remote logo in the top left", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"widncr.wid.js","url":"widget.js"} - ] - }, - { - "id": "ncrclk", - "name": "NCR Clock", - "shortName": "NCR Clock", - "version": "0.02", - "description": "NodeConf Remote clock", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"ncrclk.app.js","url":"app.js"}, - {"name":"ncrclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "isoclock", - "name": "ISO Compliant Clock Face", - "shortName": "ISO Clock", - "version": "0.02", - "description": "Tweaked fork of digiclock for ISO date and time", - "icon": "isoclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"isoclock.app.js","url":"isoclock.js"}, - {"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true} - ] - }, - { - "id": "gpstimeserver", - "name": "GPS Time Server", - "version": "0.01", - "description": "A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server.", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"gpstimeserver.wid.js","url":"widget.js"} - ] - }, - { - "id": "tilthydro", - "name": "Tilt Hydrometer Display", - "shortName": "Tilt Hydro", - "version": "0.01", - "description": "A display for the [Tilt Hydrometer](https://tilthydrometer.com/) - [more info here](http://www.espruino.com/Tilt+Hydrometer+Display)", - "icon": "app.png", - "tags": "tools,bluetooth", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"tilthydro.app.js","url":"app.js"}, - {"name":"tilthydro.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "supmariodark", - "name": "Super mario clock night mode", - "shortName": "supmariodark", - "version": "0.01", - "description": "Super mario clock in night mode", - "icon": "supmariodark.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"supmariodark.app.js","url":"supmariodark.js"}, - {"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true}, - {"name":"supmario30x24.bin","url":"supmario30x24.bin.js"}, - {"name":"supmario30x24.wdt","url":"supmario30x24.wdt.js"}, - {"name":"banner-up.img","url":"banner-up.js","evaluate":true}, - {"name":"banner-down.img","url":"banner-down.js","evaluate":true}, - {"name":"brick2.img","url":"brick2.js","evaluate":true}, - {"name":"enemy.img","url":"enemy.js","evaluate":true}, - {"name":"flower.img","url":"flower.js","evaluate":true}, - {"name":"flower_b.img","url":"flower_b.js","evaluate":true}, - {"name":"mario_wh.img","url":"mario_wh.js","evaluate":true}, - {"name":"pipe.img","url":"pipe.js","evaluate":true} - ] - }, - { - "id": "gmeter", - "name": "G-Meter", - "shortName": "G-Meter", - "version": "0.01", - "description": "Simple G-Meter", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"gmeter.app.js","url":"app.js"}, - {"name":"gmeter.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "dtlaunch", - "name": "Desktop Launcher", - "version": "0.07", - "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", - "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], - "icon": "icon.png", - "type": "launch", - "tags": "tool,system,launcher", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"dtlaunch.app.js","url":"app-b1.js", "supports": ["BANGLEJS"]}, - {"name":"dtlaunch.app.js","url":"app-b2.js", "supports": ["BANGLEJS2"]}, - {"name":"dtlaunch.settings.js","url":"settings-b1.js", "supports": ["BANGLEJS"]}, - {"name":"dtlaunch.settings.js","url":"settings-b2.js", "supports": ["BANGLEJS2"]}, - {"name":"dtlaunch.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"dtlaunch.json"}] - }, - { - "id": "HRV", - "name": "Heart Rate Variability monitor", - "shortName": "HRV monitor", - "version": "0.04", - "description": "Heart Rate Variability monitor, see Readme for more info", - "icon": "hrv.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"HRV.app.js","url":"app.js"}, - {"name":"HRV.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "hardalarm", - "name": "Hard Alarm", - "shortName": "HardAlarm", - "version": "0.02", - "description": "Make sure you wake up! Count to the right number to turn off the alarm", - "icon": "app.png", - "tags": "tool,alarm,widget", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"hardalarm.app.js","url":"app.js"}, - {"name":"hardalarm.boot.js","url":"boot.js"}, - {"name":"hardalarm.js","url":"hardalarm.js"}, - {"name":"hardalarm.img","url":"app-icon.js","evaluate":true}, - {"name":"hardalarm.wid.js","url":"widget.js"} - ], - "data": [{"name":"hardalarm.json"}] - }, - { - "id": "edisonsball", - "name": "Edison's Ball", - "shortName": "Edison's Ball", - "version": "0.01", - "description": "Hypnagogia/Micro-Sleep alarm for experimental use in exploring sleep transition and combating drowsiness", - "icon": "app-icon.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"edisonsball.app.js","url":"app.js"}, - {"name":"edisonsball.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "hrrawexp", - "name": "HRM Data Exporter", - "shortName": "HRM Data Exporter", - "version": "0.01", - "description": "export raw hrm signal data to a csv file", - "icon": "app-icon.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "interface.html", - "storage": [ - {"name":"hrrawexp.app.js","url":"app.js"}, - {"name":"hrrawexp.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "breath", - "name": "Breathing App", - "shortName": "Breathing App", - "version": "0.01", - "description": "app to aid relaxation and train breath syncronicity using haptics and visualisation, also displays HR", - "icon": "app-icon.png", - "tags": "tools,health", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"breath.app.js","url":"app.js"}, - {"name":"breath.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"breath.settings.json","url":"settings.json"}] - }, - { - "id": "lazyclock", - "name": "Lazy Clock", - "version": "0.03", - "description": "Tells the time, roughly", - "icon": "lazyclock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "screenshots": [{"url":"bangle1-lazy-clock-screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"lazyclock.app.js","url":"lazyclock-app.js"}, - {"name":"lazyclock.img","url":"lazyclock-icon.js","evaluate":true} - ] - }, - { - "id": "astral", - "name": "Astral Clock", - "version": "0.03", - "description": "Clock that calculates and displays Alt Az positions of all planets, Sun as well as several other astronomy targets (customizable) and current Moon phase. Coordinates are calculated by GPS & time and onscreen compass assists orienting. See Readme before using.", - "icon": "app-icon.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"astral.app.js","url":"app.js"}, - {"name":"astral.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "alpinenav", - "name": "Alpine Nav", - "version": "0.01", - "description": "App that performs GPS monitoring to track and display position relative to a given origin in realtime", - "icon": "app-icon.png", - "tags": "outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"alpinenav.app.js","url":"app.js"}, - {"name":"alpinenav.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "lifeclk", - "name": "Game of Life Clock", - "shortName": "Conway's Clock", - "version": "0.06", - "description": "Modification and clockification of Conway's Game of Life", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"lifeclk.app.js","url":"app.min.js"}, - {"name":"lifeclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "speedalt", - "name": "GPS Adventure Sports", - "shortName": "GPS Adv Sport", - "version": "1.02", - "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", - "tags": "tool,outdoors", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"speedalt.app.js","url":"app.js"}, - {"name":"speedalt.img","url":"app-icon.js","evaluate":true}, - {"name":"speedalt.settings.js","url":"settings.js"} - ], - "data": [{"name":"speedalt.json"}] - }, - { - "id": "speedalt2", - "name": "GPS Adventure Sports II", - "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", - "tags": "tool,outdoors", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"speedalt2.app.js","url":"app.js"}, - {"name":"speedalt2.img","url":"app-icon.js","evaluate":true}, - {"name":"speedalt2.settings.js","url":"settings.js"} - ], - "data": [{"name":"speedalt2.json"}] - }, - { - "id": "slomoclock", - "name": "SloMo Clock", - "shortName": "SloMo Clock", - "version": "0.10", - "description": "Simple 24h clock face with large digits, hour above minute. Uses Layout library.", - "icon": "watch.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-slow-mo-clock-screenshot.png"}], - "storage": [ - {"name":"slomoclock.app.js","url":"app.js"}, - {"name":"slomoclock.img","url":"app-icon.js","evaluate":true}, - {"name":"slomoclock.settings.js","url":"settings.js"} - ], - "data": [{"name":"slomoclock.json"}] - }, - { - "id": "de-stress", - "name": "De-Stress", - "shortName": "De-Stress", - "version": "0.02", - "description": "Simple haptic heartbeat", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"de-stress.app.js","url":"app.js"}, - {"name":"de-stress.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "mclockplus", - "name": "Morph Clock+", - "shortName": "Morph Clock+", - "version": "0.02", - "description": "Morphing Clock with more readable seconds and date and additional stopwatch", - "icon": "mclockplus.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"mclockplus.app.js","url":"mclockplus.app.js"}, - {"name":"mclockplus.img","url":"mclockplus-icon.js","evaluate":true} - ] - }, - { - "id": "intervals", - "name": "Intervals App", - "shortName": "Intervals", - "version": "0.01", - "description": "Intervals for training. It is possible to configure work time and rest time and number of sets.", - "icon": "intervals.png", - "tags": "", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"intervals.app.js","url":"intervals.app.js"}, - {"name":"intervals.img","url":"intervals-icon.js","evaluate":true} - ] - }, - { - "id": "planetarium", - "name": "Planetarium", - "shortName": "Planetarium", - "version": "0.03", - "description": "Planetarium showing up to 500 stars using the watch location and time", - "icon": "planetarium.png", - "tags": "", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"planetarium.app.js","url":"planetarium.app.js"}, - {"name":"planetarium.data.csv","url":"planetarium.data.csv"}, - {"name":"planetarium.const.csv","url":"planetarium.const.csv"}, - {"name":"planetarium.extra.csv","url":"planetarium.extra.csv"}, - {"name":"planetarium.settings.js","url":"settings.js"}, - {"name":"planetarium.img","url":"planetarium-icon.js","evaluate":true} - ], - "data": [{"name":"planetarium.json"}] - }, - { - "id": "tapelauncher", - "name": "Tape Launcher", - "version": "0.02", - "description": "An App launcher, icons displayed in a horizontal tape, swipe or use buttons", - "icon": "icon.png", - "type": "launch", - "tags": "tool,system,launcher", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"tapelauncher.app.js","url":"app.js"}, - {"name":"tapelauncher.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "oblique", - "name": "Oblique Strategies", - "version": "0.01", - "description": "Oblique Strategies for creativity. Copied from Brian Eno.", - "icon": "eno.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"oblique.app.js","url":"app.js"}, - {"name":"oblique.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "testuserinput", - "name": "Test User Input", - "shortName": "Test User Input", - "version": "0.06", - "description": "App to test the bangle.js input interface. It displays the user action in text, circle buttons or on/off switch UI elements.", - "icon": "app.png", - "tags": "input,interface,buttons,touch,UI", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"testuserinput.app.js","url":"app.js"}, - {"name":"testuserinput.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "gpssetup", - "name": "GPS Setup", - "shortName": "GPS Setup", - "version": "0.02", - "description": "Configure the GPS power options and store them in the GPS nvram", - "icon": "gpssetup.png", - "tags": "gps,tools,outdoors", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"gpssetup","url":"gpssetup.js"}, - {"name":"gpssetup.settings.js","url":"settings.js"}, - {"name":"gpssetup.app.js","url":"app.js"}, - {"name":"gpssetup.img","url":"icon.js","evaluate":true} - ], - "data": [{"name":"gpssetup.settings.json","url":"settings.json"}] - }, - { - "id": "walkersclock", - "name": "Walkers Clock", - "shortName": "Walkers Clock", - "version": "0.04", - "description": "A large font watch, displays steps, can switch GPS on/off, displays grid reference", - "icon": "walkersclock48.png", - "type": "clock", - "tags": "clock,gps,tools,outdoors", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"walkersclock.app.js","url":"app.js"}, - {"name":"walkersclock.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "widgps", - "name": "GPS Widget", - "version": "0.03", - "description": "Tiny widget to show the power on/off status of the GPS", - "icon": "widget.png", - "type": "widget", - "tags": "widget,gps", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"widgps.wid.js","url":"widget.js"} - ] - }, - { - "id": "widhrt", - "name": "HRM Widget", - "version": "0.03", - "description": "Tiny widget to show the power on/off status of the Heart Rate Monitor", - "icon": "widget.png", - "type": "widget", - "tags": "widget,hrm", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"widhrt.wid.js","url":"widget.js"} - ] - }, - { - "id": "countdowntimer", - "name": "Countdown Timer", - "version": "0.01", - "description": "A simple countdown timer with a focus on usability", - "icon": "countdowntimer.png", - "tags": "timer,tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"countdowntimer.app.js","url":"countdowntimer.js"}, - {"name":"countdowntimer.img","url":"countdowntimer-icon.js","evaluate":true} - ] - }, - { - "id": "helloworld", - "name": "hello, world!", - "shortName": "hello world", - "version": "0.02", - "description": "A cross cultural hello world!/hola mundo! app with colors and languages", - "icon": "app.png", - "tags": "input,interface,buttons,touch", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"helloworld.app.js","url":"app.js"}, - {"name":"helloworld.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widcom", - "name": "Compass Widget", - "version": "0.02", - "description": "Tiny widget to show the power on/off status of the Compass", - "icon": "widget.png", - "type": "widget", - "tags": "widget,compass", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"widcom.wid.js","url":"widget.js"} - ] - }, - { - "id": "arrow", - "name": "Arrow Compass", - "version": "0.05", - "description": "Moving arrow compass that points North, shows heading, with tilt correction. Based on jeffmer's Navigation Compass", - "icon": "arrow.png", - "type": "app", - "tags": "tool,outdoors", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"arrow.app.js","url":"app.js"}, - {"name":"arrow.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "waypointer", - "name": "Way Pointer", - "version": "0.01", - "description": "Navigate to a waypoint using the GPS for bearing and compass to point way, uses the same waypoint interface as GPS Navigation", - "icon": "waypointer.png", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "waypoints.html", - "storage": [ - {"name":"waypointer.app.js","url":"app.js"}, - {"name":"waypointer.img","url":"icon.js","evaluate":true} - ], - "data": [{"name":"waypoints.json","url":"waypoints.json"}] - }, - { - "id": "color_catalog", - "name": "Colors Catalog", - "shortName": "Colors Catalog", - "version": "0.01", - "description": "Displays RGB565 and RGB888 colors, its name and code in screen.", - "icon": "app.png", - "tags": "Color,input,buttons,touch,UI", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"color_catalog.app.js","url":"app.js"}, - {"name":"color_catalog.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "UI4swatch", - "name": "UI 4 swatch", - "shortName": "UI 4 swatch", - "version": "0.01", - "description": "A UI/UX for espruino smartwatches, displays dinamically calc. x,y coordinates.", - "icon": "app.png", - "tags": "Color,input,buttons,touch,UI", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"UI4swatch.app.js","url":"app.js"}, - {"name":"UI4swatch.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "simplest", - "name": "Simplest Clock", - "version": "0.03", - "description": "The simplest working clock, acts as a tutorial piece", - "icon": "simplest.png", - "screenshots": [{"url":"screenshot_simplest.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"simplest.app.js","url":"app.js"}, - {"name":"simplest.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "stepo", - "name": "Stepometer Clock", - "version": "0.03", - "description": "A large font watch, displays step count in a doughnut guage and warns of low battery, requires one of the steps widgets to be installed", - "icon": "stepo.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"stepo.app.js","url":"app.js"}, - {"name":"stepo.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "gbmusic", - "name": "Gadgetbridge Music Controls", - "shortName": "Music Controls", - "version": "0.08", - "description": "Control the music on your Gadgetbridge-connected phone", - "icon": "icon.png", - "screenshots": [{"url":"screenshot_v1.png"},{"url":"screenshot_v2.png"}], - "type": "app", - "tags": "tools,bluetooth,gadgetbridge,music", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"gbmusic.app.js","url":"app.js"}, - {"name":"gbmusic.settings.js","url":"settings.js"}, - {"name":"gbmusic.wid.js","url":"widget.js"}, - {"name":"gbmusic.img","url":"icon.js","evaluate":true} - ], - "data": [{"name":"gbmusic.json"},{"name":"gbmusic.load.json"}] - }, - { - "id": "battleship", - "name": "Battleship", - "version": "0.01", - "description": "The classic game of battleship", - "icon": "battleship-icon.png", - "tags": "game", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-battle-ship-screenshot.png"}], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"battleship.app.js","url":"battleship.js"}, - {"name":"battleship.img","url":"battleship-icon.js","evaluate":true} - ] - }, - { - "id": "kitchen", - "name": "Kitchen Combo", - "version": "0.13", - "description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'", - "icon": "kitchen.png", - "type": "clock", - "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], - "readme": "README.md", - "interface": "waypoints.html", - "storage": [ - {"name":"kitchen.app.js","url":"kitchen.app.js"}, - {"name":"stepo2.kit.js","url":"stepo2.kit.js"}, - {"name":"swatch.kit.js","url":"swatch.kit.js"}, - {"name":"gps.kit.js","url":"gps.kit.js"}, - {"name":"compass.kit.js","url":"compass.kit.js"}, - {"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true} - ], - "data": [{"name":"waypoints.json","url":"waypoints.json"}] - }, - { - "id": "banglebridge", - "name": "BangleBridge", - "shortName": "BangleBridge", - "version": "0.01", - "description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", - "icon": "widget.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"banglebridge.wid.js","url":"widget.js"}, - {"name":"banglebridge.watch.img","url":"watch.img"}, - {"name":"banglebridge.heart.img","url":"heart.img"} - ] - }, - { - "id": "qmsched", - "name": "Quiet Mode Schedule and Widget", - "shortName": "Quiet Mode", - "version": "0.06", - "description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", - "icon": "app.png", - "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, - {"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}], - "tags": "tool,widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"qmsched","url":"lib.js"}, - {"name":"qmsched.app.js","url":"app.js"}, - {"name":"qmsched.boot.js","url":"boot.js"}, - {"name":"qmsched.img","url":"icon.js","evaluate":true}, - {"name":"qmsched.wid.js","url":"widget.js"} - ], - "data": [{"name":"qmsched.json"}] - }, - { - "id": "hourstrike", - "name": "Hour Strike", - "shortName": "Hour Strike", - "version": "0.08", - "description": "Strike the clock on the hour. A great tool to remind you an hour has passed!", - "icon": "app-icon.png", - "tags": "tool,alarm", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"hourstrike.app.js","url":"app.js"}, - {"name":"hourstrike.boot.js","url":"boot.js"}, - {"name":"hourstrike.img","url":"app-icon.js","evaluate":true}, - {"name":"hourstrike.json","url":"hourstrike.json"} - ] - }, - { - "id": "whereworld", - "name": "Where in the World?", - "shortName": "Where World", - "version": "0.01", - "description": "Shows your current location on the world map", - "icon": "app.png", - "tags": "gps", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"whereworld.app.js","url":"app.js"}, - {"name":"whereworld.img","url":"app-icon.js","evaluate":true}, - {"name":"whereworld.worldmap","url":"worldmap"} - ] - }, - { - "id": "omnitrix", - "name": "Omnitrix", - "version": "0.01", - "description": "An Omnitrix Showpiece", - "icon": "omnitrix.png", - "screenshots": [{"url":"screenshot.png"}], - "tags": "game", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"omnitrix.app.js","url":"omnitrix.app.js"}, - {"name":"omnitrix.img","url":"omnitrix.icon.js","evaluate":true} - ] - }, - { - "id": "batclock", - "name": "Bat Clock", - "shortName": "Bat Clock", - "version": "0.02", - "description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.", - "icon": "bat-clock.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"batclock.app.js","url":"bat-clock.app.js"}, - {"name":"batclock.img","url":"bat-clock.icon.js","evaluate":true} - ] - }, - { - "id": "doztime", - "name": "Dozenal Time", - "shortName": "Dozenal Time", - "version": "0.04", - "description": "A dozenal Holocene calendar and dozenal diurnal clock", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"doztime.app.js","url":"app.js"}, - {"name":"doztime.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "gbtwist", - "name": "Gadgetbridge Twist Control", - "shortName": "Twist Control", - "version": "0.01", - "description": "Shake your wrist to control your music app via Gadgetbridge", - "icon": "app.png", - "type": "app", - "tags": "tools,bluetooth,gadgetbridge,music", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": false, - "storage": [ - {"name":"gbtwist.app.js","url":"app.js"}, - {"name":"gbtwist.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "thermom", - "name": "Thermometer", - "version": "0.05", - "description": "Displays the current temperature in degree Celsius/Fahrenheit (depending on locale), updates every 10 seconds with average of last 5 readings.", - "icon": "app.png", - "tags": "tool", - "supports": ["BANGLEJS", "BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}], - "allow_emulator": true, - "storage": [ - {"name":"thermom.app.js","url":"app.js"}, - {"name":"thermom.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "mysticdock", - "name": "Mystic Dock", - "version": "1.00", - "description": "A retro-inspired dockface that displays the current time and battery charge while plugged in, and which features an interactive mode that shows the time, date, and a rotating data display line.", - "icon": "mystic-dock.png", - "type": "dock", - "tags": "dock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"mysticdock.app.js","url":"mystic-dock-app.js"}, - {"name":"mysticdock.boot.js","url":"mystic-dock-boot.js"}, - {"name":"mysticdock.settings.js","url":"mystic-dock-settings.js"}, - {"name":"mysticdock.img","url":"mystic-dock-icon.js","evaluate":true} - ] - }, - { - "id": "mysticclock", - "name": "Mystic Clock", - "version": "1.01", - "description": "A retro-inspired watchface featuring time, date, and an interactive data display line.", - "icon": "mystic-clock.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"bangle1-mystic-clock-screenshot.png"}], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"mysticclock.app.js","url":"mystic-clock-app.js"}, - {"name":"mysticclock.settings.js","url":"mystic-clock-settings.js"}, - {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} - ] - }, - { - "id": "hcclock", - "name": "Hi-Contrast Clock", - "version": "0.02", - "description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", - "icon": "hcclock-icon.png", - "type": "clock", - "tags": "clock", - "screenshots": [{"url":"bangle1-high-contrast-clock-screenshot.png"}], - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"hcclock.app.js","url":"hcclock.app.js"}, - {"name":"hcclock.img","url":"hcclock-icon.js","evaluate":true} - ] - }, - { - "id": "thermomF", - "name": "Fahrenheit Temp", - "version": "0.01", - "description": "[NOT RECOMMENDED] A modification of the Thermometer App to display temprature in Fahrenheit. Please use the 'Thermometer App' and install 'Languages' to get the temperature in the correct format for your locale.", - "icon": "thermf.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"thermomF.app.js","url":"app.js"}, - {"name":"thermomF.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "nixie", - "name": "Nixie Clock", - "shortName": "Nixie", - "version": "0.01", - "description": "A nixie tube clock for both Bangle 1 and 2.", - "icon": "nixie.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"nixie.app.js","url":"app.js"}, - {"name":"nixie.img","url":"app-icon.js","evaluate":true}, - {"name":"m_vatch.js","url":"m_vatch.js"} - ] - }, - { - "id": "carcrazy", - "name": "Car Crazy", - "shortName": "Car Crazy", - "version": "0.03", - "description": "A simple car game where you try to avoid the other cars by tilting your wrist left and right. Hold down button 2 to start.", - "icon": "carcrash.png", - "tags": "game", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"carcrazy.app.js","url":"app.js"}, - {"name":"carcrazy.img","url":"app-icon.js","evaluate":true}, - {"name":"carcrazy.settings.js","url":"settings.js"} - ], - "data": [{"name":"CarCrazy.csv"}] - }, - { - "id": "shortcuts", - "name": "Shortcuts", - "shortName": "Shortcuts", - "version": "0.01", - "description": "Quickly load your favourite apps from (almost) any watch face.", - "icon": "app.png", - "type": "bootloader", - "tags": "tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "storage": [ - {"name":"shortcuts.boot.js","url":"boot.js"}, - {"name":"shortcuts.settings.js","url":"settings.js"} - ], - "data": [{"name":"shortcuts.json"}] - }, - { - "id": "vectorclock", - "name": "Vector Clock", - "version": "0.03", - "description": "A digital clock that uses the built-in vector font.", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS", "BANGLEJS2"], - "allow_emulator": true, - "screenshots": [ - {"url":"bangle2-vector-clock-screenshot.png"}, - {"url":"bangle1-vector-clock-screenshot.png"} - ], - "storage": [ - {"name":"vectorclock.app.js","url":"app.js"}, - {"name":"vectorclock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "fd6fdetect", - "name": "fd6fdetect", - "shortName": "fd6fdetect", - "version": "0.2", - "description": "Allows you to see 0xFD6F beacons near you.", - "icon": "app.png", - "tags": "tool", - "readme": "README.md", - "supports": ["BANGLEJS"], - "storage": [ - {"name":"fd6fdetect.app.js","url":"app.js"}, - {"name":"fd6fdetect.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "choozi", - "name": "Choozi", - "version": "0.01", - "description": "Choose people or things at random using Bangle.js.", - "icon": "app.png", - "tags": "tool", - "supports": ["BANGLEJS"], - "readme": "README.md", - "allow_emulator": true, - "screenshots": [{"url":"bangle1-choozi-screenshot1.png"},{"url":"bangle1-choozi-screenshot2.png"}], - "storage": [ - {"name":"choozi.app.js","url":"app.js"}, - {"name":"choozi.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "widclkbttm", - "name": "Digital clock (Bottom) widget", - "shortName": "Digital clock Bottom Widget", - "version": "0.03", - "description": "Displays time in the bottom area.", - "icon": "widclkbttm.png", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"widclkbttm.wid.js","url":"widclkbttm.wid.js"} - ] - }, - { - "id": "pastel", - "name": "Pastel Clock", - "shortName": "Pastel", - "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"}, - "screenshots": [{"url":"screenshot_pastel.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"f_architect","url":"f_architect.js"}, - {"name":"f_gochihand","url":"f_gochihand.js"}, - {"name":"f_cabin","url":"f_cabin.js"}, - {"name":"f_orbitron","url":"f_orbitron.js"}, - {"name":"f_monoton","url":"f_monoton.js"}, - {"name":"f_elite","url":"f_elite.js"}, - {"name":"f_lato","url":"f_lato.js"}, - {"name":"f_latosmall","url":"f_latosmall.js"}, - {"name":"pastel.app.js","url":"pastel.app.js"}, - {"name":"pastel.img","url":"pastel.icon.js","evaluate":true}, - {"name":"pastel.settings.js","url":"pastel.settings.js"} - ], - "data": [{"name":"pastel.json"}] - }, - { - "id": "antonclk", - "name": "Anton Clock", - "version": "0.03", - "description": "A simple clock using the bold Anton font.", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"antonclk.app.js","url":"app.js"}, - {"name":"antonclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "waveclk", - "name": "Wave Clock", - "version": "0.02", - "description": "A clock using a wave image by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: Works on any Bangle.js 2, but requires firmware 2v11 or later on Bangle.js 1**", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"waveclk.app.js","url":"app.js"}, - {"name":"waveclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "floralclk", - "name": "Floral Clock", - "version": "0.01", - "description": "A clock with a flower background by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: Works on any Bangle.js 2 but requires firmware 2v11 or later on Bangle.js 1**", - "icon": "app.png", - "screenshots": [{"url":"screenshot_floral.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"floralclk.app.js","url":"app.js"}, - {"name":"floralclk.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "score", - "name": "Score Tracker", - "version": "0.01", - "description": "Score Tracker for sports that use plain numbers (e.g. Badminton, Volleyball, Soccer, Table Tennis, ...). Also supports tennis scoring.", - "icon": "score.app.png", - "screenshots": [{"url":"screenshot_score.png"}], - "type": "app", - "tags": "", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"score.app.js","url":"score.app.js"}, - {"name":"score.settings.js","url":"score.settings.js"}, - {"name":"score.presets.json","url":"score.presets.json"}, - {"name":"score.img","url":"score.app-icon.js","evaluate":true} - ], - "data": [{"name":"score.json"}] - }, - { - "id": "menusmall", - "name": "Small Menus", - "version": "0.02", - "description": "Replace Bangle.js 2's menus with a version that contains smaller text", - "icon": "app.png", - "type": "boot", - "tags": "system", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"menusmall.boot.js","url":"boot.js"} - ] - }, - { - "id": "ffcniftya", - "name": "Nifty-A Clock", - "version": "0.01", - "description": "A nifty clock with time and date", - "icon": "app.png", - "screenshots": [{"url":"screenshot_nifty.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"ffcniftya.app.js","url":"app.js"}, - {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "ffcniftyb", - "name": "Nifty-B Clock", - "version": "0.02", - "description": "A nifty clock (series B) with time, date and color configuration", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"ffcniftyb.app.js","url":"app.js"}, - {"name":"ffcniftyb.img","url":"app-icon.js","evaluate":true}, - {"name":"ffcniftyb.settings.js","url":"settings.js"} - ], - "data": [{"name":"ffcniftyb.json"}] - }, - { - "id": "stopwatch", - "name": "Stopwatch Touch", - "version": "0.01", - "description": "A touch based stop watch for Bangle JS 2", - "icon": "stopwatch.png", - "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], - "tags": "tools,app", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"stopwatch.app.js","url":"stopwatch.app.js"}, - {"name":"stopwatch.img","url":"stopwatch.icon.js","evaluate":true} - ] - }, - { - "id": "vernierrespirate", - "name": "Vernier Go Direct Respiration Belt", - "shortName": "Respiration Belt", - "version": "0.01", - "description": "Connects to a Go Direct Respiration Belt and shows respiration rate", - "icon": "app.png", - "tags": "health,bluetooth", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"vernierrespirate.app.js","url":"app.js"}, - {"name":"vernierrespirate.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"vernierrespirate.json"}] - }, - { - "id": "gpstouch", - "name": "GPS Touch", - "version": "0.01", - "description": "A touch based GPS watch, shows OS map reference", - "icon": "gpstouch.png", - "screenshots": [{"url":"screenshot4.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot1.png"}], - "tags": "tools,app", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"geotools","url":"geotools.js"}, - {"name":"gpstouch.app.js","url":"gpstouch.app.js"}, - {"name":"gpstouch.img","url":"gpstouch.icon.js","evaluate":true} - ] - }, - { - "id": "swiperclocklaunch", - "name": "Swiper Clock Launch", - "version": "0.02", - "description": "Navigate between clock and launcher with Swipe action", - "icon": "swiperclocklaunch.png", - "type": "bootloader", - "tags": "tools, system", - "supports": ["BANGLEJS", "BANGLEJS2"], - "storage": [ - {"name":"swiperclocklaunch.boot.js","url":"boot.js"}, - {"name":"swiperclocklaunch.img","url":"icon.js","evaluate":true} - ] - }, - { - "id": "qalarm", - "name": "Q Alarm and Timer", - "shortName": "Q Alarm", - "icon": "app.png", - "version": "0.03", - "description": "Alarm and timer app with days of week and 'hard' option.", - "tags": "tool,alarm,widget", - "supports": ["BANGLEJS", "BANGLEJS2"], - "storage": [ - { "name": "qalarm.app.js", "url": "app.js" }, - { "name": "qalarm.boot.js", "url": "boot.js" }, - { "name": "qalarm.js", "url": "qalarm.js" }, - { "name": "qalarmcheck.js", "url": "qalarmcheck.js" }, - { "name": "qalarm.img", "url": "app-icon.js", "evaluate": true }, - { "name": "qalarm.wid.js", "url": "widget.js" } - ], - "data": [{ "name": "qalarm.json" }] - }, - { - "id": "emojuino", - "name": "Emojuino", - "shortName": "Emojuino", - "version": "0.03", - "description": "Emojis & Espruino: broadcast Unicode emojis via Bluetooth Low Energy.", - "icon": "emojuino.png", - "screenshots": [ - { "url": "screenshot-tx.png" }, - { "url": "screenshot-swipe.png" }, - { "url": "screenshot-welcome.png" } - ], - "type": "app", - "tags": "emoji", - "supports" : [ "BANGLEJS2" ], - "allow_emulator": true, - "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.03", - "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. Also added HID media controlls, just swipe on the clock face to controll the media! Gadgetbride support coming soon(hopefully) Thanks to t0m1o1 for media controls!", - "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": "wid_a_battery_widget", - "name": "A Battery Widget (with percentage)", - "shortName":"A Battery Widget", - "icon": "widget.png", - "version":"1.02", - "type": "widget", - "supports": ["BANGLEJS", "BANGLEJS2"], - "readme": "README.md", - "description": "Simple and slim battery widget with charge status and percentage", - "tags": "widget,battery", - "storage": [ - {"name":"wid_a_battery_widget.wid.js","url":"widget.js"} - ] - }, - { - "id": "lcars", - "name": "LCARS Clock", - "shortName":"LCARS", - "icon": "lcars.png", - "version":"0.07", - "readme": "README.md", - "supports": ["BANGLEJS2"], - "description": "Library Computer Access Retrieval System (LCARS) clock.", - "type": "clock", - "tags": "clock", - "screenshots": [{"url":"screenshot.png"}], - "storage": [ - {"name":"lcars.app.js","url":"lcars.app.js"}, - {"name":"lcars.img","url":"lcars.icon.js","evaluate":true}, - {"name":"lcars.settings.js","url":"lcars.settings.js"} - ] - }, - { "id": "binwatch", - "name": "Binary Watch", - "shortName":"BinWatch", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "version":"0.04", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "allow_emulator":true, - "description": "Famous binary watch", - "tags": "clock", - "type": "clock", - "storage": [ - {"name":"binwatch.app.js","url":"app.js"}, - {"name":"binwatch.bg176.img","url":"Background176_center.img"}, - {"name":"binwatch.bg240.img","url":"Background240_center.img"}, - {"name":"binwatch.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "hidmsicswipe", - "name": "Bluetooth Music Swipe Controls", - "shortName": "Swipe Control", - "version": "0.01", - "description": "Based on the original Bluetooth Music Controls. Swipe up/down for volume, left/right for previous and next, tap for play/pause and btn1 to lock and unlock the controls. Enable HID in settings, pair with your phone, then use this app to control music from your watch!", - "icon": "hidmsicswipe.png", - "tags": "bluetooth", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"hidmsicswipe.app.js","url":"hidmsicswipe.js"}, - {"name":"hidmsicswipe.img","url":"hidmsicswipe-icon.js","evaluate":true} - ] - }, - { - "id": "authentiwatch", - "name": "2FA Authenticator", - "shortName": "AuthWatch", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "version": "0.04", - "description": "Google Authenticator compatible tool.", - "tags": "tool", - "interface": "interface.html", - "supports": ["BANGLEJS", "BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"authentiwatch.app.js","url":"app.js"}, - {"name":"authentiwatch.img","url":"app-icon.js","evaluate":true} - ], - "data": [{"name":"authentiwatch.json"}] - }, - { "id": "schoolCalendar", - "name": "School Calendar", - "shortName":"SCalendar", - "icon": "CalenderLogo.png", - "version": "0.01", - "description": "A simple calendar that you can see your upcoming events that you create in the customizer. Keep in note that your events reapeat weekly.(Beta)", - "tags": "tool", - "readme":"README.md", - "custom":"custom.html", - "supports": ["BANGLEJS"], - "screenshots": [{"url":"screenshot_basic.png"},{"url":"screenshot_info.png"}], - "storage": [ - {"name":"schoolCalendar.app.js"}, - {"name":"schoolCalendar.img","url":"app-icon.js","evaluate":true} - ], - "data": [ - {"name":"calendarItems.csv"} - ] - }, - { "id": "timecal", - "name": "TimeCal", - "shortName":"TimeCal", - "icon": "icon.png", - "version":"0.01", - "description": "TimeCal shows the Time along with a 3 week calendar", - "tags": "clock", - "type": "clock", - "supports":["BANGLEJS2"], - "storage": [ - {"name":"timecal.app.js","url":"timecal.app.js"} - ] - }, - { - "id": "a_clock_timer", - "name": "A Clock with Timer", - "version": "0.01", - "description": "A Clock with Timer, Map and Time Zones", - "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "allow_emulator": true, - "readme": "README.md", - "storage": [ - {"name":"a_clock_timer.app.js","url":"app.js"}, - {"name":"a_clock_timer.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id":"intervalTimer", - "name":"Interval Timer", - "shortName":"Interval Timer", - "icon": "app.png", - "version":"0.01", - "description": "Interval Timer for workouts, HIIT, or whatever else.", - "tags": "timer, interval, hiit, workout", - "readme":"README.md", - "supports":["BANGLEJS2"], - "storage": [ - {"name":"intervalTimer.app.js","url":"app.js"}, - {"name":"intervalTimer.img","url":"app-icon.js","evaluate":true} - ] - }, - { "id": "93dub", - "name": "93 Dub", - "shortName":"93 Dub", - "icon": "93dub.png", - "screenshots": [{"url":"screenshot.png"}], - "version":"0.05", - "description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo", - "tags": "clock", - "type": "clock", - "supports":["BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"93dub.app.js","url":"app.js"}, - {"name":"93dub.img","url":"app-icon.js","evaluate":true} - ] - }, - { "id": "poweroff", - "name": "Poweroff", - "shortName":"Poweroff", - "version":"0.01", - "description": "Simple app to power off your Bangle.js", - "icon": "app.png", - "tags": "tool, poweroff, shutdown", - "supports" : ["BANGLEJS", "BANGLEJS2"], - "readme": "README.md", - "allow_emulator": true, - "storage": [ - {"name":"poweroff.app.js","url":"app.js"}, - {"name":"poweroff.img","url":"app-icon.js","evaluate":true} - ] -}, -{ - "id": "sensible", - "name": "SensiBLE", - "shortName": "SensiBLE", - "version": "0.04", - "description": "Collect, display and advertise real-time sensor data.", - "icon": "sensible.png", - "screenshots": [ - { "url": "screenshot-top.png" }, - { "url": "screenshot-acc.png" }, - { "url": "screenshot-bar.png" }, - { "url": "screenshot-gps.png" }, - { "url": "screenshot-hrm.png" }, - { "url": "screenshot-mag.png" } - ], - "type": "app", - "tags": "tool,sensors", - "supports" : [ "BANGLEJS2" ], - "allow_emulator": true, - "readme": "README.md", - "storage": [ - { "name": "sensible.app.js", "url": "sensible.js" }, - { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } - ] -}, - { - "id": "widbars", - "name": "Bars Widget", - "version": "0.01", - "description": "Display several measurements as vertical bars.", - "icon": "icon.png", - "screenshots": [{"url":"screenshot.png"}], - "readme": "README.md", - "type": "widget", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widbars.wid.js","url":"widget.js"} - ] -}, -{ - "id":"a_speech_timer", - "name":"Speech Timer", - "icon": "app.png", - "version":"1.01", - "description": "A timer designed to help keeping your speeches and presentations to time.", - "tags": "tool,timer", - "readme":"README.md", - "supports":["BANGLEJS2"], - "storage": [ - {"name":"a_speech_timer.app.js","url":"app.js"}, - {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} - ] -}, - { "id": "mylocation", - "name": "My Location", - "shortName":"My Location", - "icon": "mylocation.png", - "type": "app", - "screenshots": [{"url":"screenshot_1.png"}], - "version":"0.01", - "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", - "readme": "README.md", - "tags": "tool,utility", - "supports": ["BANGLEJS", "BANGLEJS2"], - "storage": [ - {"name":"mylocation.app.js","url":"mylocation.app.js"}, - {"name":"mylocation.img","url":"mylocation.icon.js","evaluate": true } - ], - "data": [ - {"name":"mylocation.json"} - ] - }, - { - "id": "pebble", - "name": "Pebble Clock", - "shortName": "Pebble", - "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"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"pebble.app.js","url":"pebble.app.js"}, - {"name":"pebble.settings.js","url":"pebble.settings.js"}, - {"name":"pebble.img","url":"pebble.icon.js","evaluate":true} - ] - }, - { "id": "pooqroman", - "name": "pooq Roman watch face", - "shortName":"pooq Roman", - "version":"0.03", - "description": "A classic watch face with a certain dynamicity. Most amusing in 24h mode. Slide up to show more hands, down for less(!). By design does not support standard widgets, sorry!", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports" : ["BANGLEJS2"], - "allow_emulator":true, - "readme": "README.md", - "storage": [ - {"name":"pooqroman.app.js","url":"app.js"}, - {"name":"pooqroman.img","url":"app-icon.js","evaluate":true} - ], - "data": [ - {"name":"pooqroman.json"} - ] - }, - { - "id": "widbata", - "name": "Battery Level Widget (Themed)", - "shortName":"Battery Theme", - "icon": "widbata.png", - "screenshots": [{"url":"screenshot_widbata_1.png"}], - "version":"0.01", - "type": "widget", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "description": "Shows the current battery level status in the top right using the clocks colour theme", - "tags": "widget,battery", - "storage": [ - {"name":"widbata.wid.js","url":"widbata.wid.js"} - ] - }, - { - "id": "weatherClock", - "name": "Weather Clock", - "version": "0.04", - "description": "A clock which displays current weather conditions (requires Gadgetbridge and Weather apps).", - "icon": "app.png", - "screenshots": [{"url":"screens/screen1.png"}], - "type": "clock", - "tags": "clock, weather", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, - "readme": "README.md", - "storage": [ - {"name":"weatherClock.app.js","url":"app.js"}, - {"name":"weatherClock.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "menuwheel", - "name": "Wheel Menus", - "version": "0.01", - "description": "Replace Bangle.js 2's menus with a version that contains variable-size text and a back button", - "readme": "README.md", - "icon": "icon.png", - "screenshots": [ - {"url":"screenshot_b1_dark.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_light.png"}, - {"url":"screenshot_b2_dark.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_light.png"} - ], - "type": "boot", - "tags": "system", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"menuwheel.boot.js","url":"boot.js"} - ] - }, - { "id": "widChargingStatus", - "name": "Charging Status", - "shortName":"ChargingStatus", - "icon": "widget.png", - "version":"0.1", - "type": "widget", - "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", - "tags": "widget", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"widChargingStatus.wid.js","url":"widget.js"} - ] - }, - { - "id": "flow", - "name": "FLOW", - "shortName": "FLOW", - "version": "0.01", - "description": "A game where you have to help a flow avoid white obstacles thing by tapping! This is a demake of an app which I forgot the name of. Press BTN(1) to restart. See if you can get to 2500 score!", - "icon": "app.png", - "tags": "game", - "supports" : ["BANGLEJS", "BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name": "flow.app.js", "url": "app.js" }, - {"name": "flow.img", "url": "app-icon.js","evaluate": true } - ] - }, - { "id": "scribble", - "name": "Scribble", - "shortName":"Scribble", - "version":"0.01", - "type": "app", - "description": "A keyboard on your wrist! Swipe right for space, left for delete.", - "icon": "app.png", - "allow_emulator": true, - "tags": "tools, keyboard, text, scribble", - "supports" : ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"scribble.app.js","url":"app.js"}, - {"name":"scribble.img","url":"app-icon.js","evaluate":true} - ], - "screenshots":[ - { "url":"screenshot.png" } - ] - }, - { - "id": "ptlaunch", - "name": "Pattern Launcher", - "shortName": "Pattern Launcher", - "version": "0.11", - "description": "Directly launch apps from the clock screen with custom patterns.", - "icon": "app.png", - "screenshots": [{"url":"manage_patterns_light.png"}], - "tags": "tools", - "supports": ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - { "name": "ptlaunch.app.js", "url": "app.js" }, - { "name": "ptlaunch.boot.js", "url": "boot.js" }, - { "name": "ptlaunch.img", "url": "app-icon.js", "evaluate": true } - ], - "data": [{"name":"ptlaunch.patterns.json"}] - }, - { - "id": "rebble", - "name": "Rebble Clock", - "shortName": "Rebble", - "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", "widpedom":"app"}, - "screenshots": [{"url":"screenshot_rebble.png"}], - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"rebble.app.js","url":"rebble.app.js"}, - {"name":"rebble.settings.js","url":"rebble.settings.js"}, - {"name":"rebble.img","url":"rebble.icon.js","evaluate":true} - ] - }, - { "id": "snaky", - "name": "Snaky", - "shortName":"Snaky", - "version":"0.01", - "description": "The classic snake game. Eat apples and don't bite your tail. Control the snake with the touch screen.", - "tags": "game,fun", - "icon": "snaky.png", - "supports" : ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"snaky.app.js","url":"snaky.js"}, - {"name":"snaky.img","url":"snaky-icon.js","evaluate":true} - ] - }, - { - "id": "clicompleteclk", - "name": "CLI complete clock", - "shortName":"CLI cmplt clock", - "version":"0.03", - "description": "Command line styled clock with lots of information", - "icon": "app.png", - "allow_emulator": true, - "type": "clock", - "tags": "clock,cli,command,bash,shell,weather,hrt", - "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"} - ], - "data": [{"name":"clicompleteclk.json"}] - }, - { - "id":"awairmonitor", - "name":"Awair Monitor", - "icon": "app.png", - "allow_emulator": true, - "version":"0.01", - "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", - "tags": "tool,health", - "readme":"README.md", - "supports":["BANGLEJS2"], - "storage": [ - {"name":"awairmonitor.app.js","url":"app.js"}, - {"name":"awairmonitor.img","url":"app-icon.js","evaluate":true} - ] - }, - { "id": "pooqround", - "name": "pooq Round watch face", - "shortName":"pooq Round", - "version":"0.01", - "description": "A 24 hour analogue watchface with high legibility and a novel style.", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports" : ["BANGLEJS2"], - "allow_emulator":true, - "readme": "README.md", - "storage": [ - {"name":"pooqround.app.js","url":"app.js"}, - {"name":"pooqround.img","url":"app-icon.js","evaluate":true} - ], - "data": [ - {"name":"pooqround.json"} - ] - }, - { - "id": "coretemp", - "name": "Core Temp Display", - "version": "0.01", - "description": "Display CoreTemp device sensor data", - "icon": "coretemp.png", - "type": "app", - "tags": "health", - "readme": "README.md", - "supports": ["BANGLEJS","BANGLEJS2"], - "storage": [ - {"name":"coretemp.boot.js","url":"boot.js"}, - {"name":"coretemp.app.js","url":"coretemp.js"}, - {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true} - ] - }, - { - "id": "showimg", - "name": "simple image viewer", - "shortName":"showImage", - "version":"0.2", - "description": "Displays the image in \"showimg.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"], - "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": "pebbled", - "name": "Pebble Clock with distance", - "shortName": "Pebble + distance", - "version": "0.1", - "description": "Fork of Pebble Clock with distance in KM. Both step count and the distance are on the main screen. Default step length = 0.75m (can be changed in settings).", - "readme": "README.md", - "icon": "pebbled.png", - "screenshots": [{"url":"pebble_screenshot.png"}], - "type": "clock", - "tags": "clock,distance", - "supports": ["BANGLEJS2"], - "storage": [ - {"name":"pebbled.app.js","url":"pebbled.app.js"}, - {"name":"pebbled.settings.js","url":"pebbled.settings.js"}, - {"name":"pebbled.img","url":"pebbled.icon.js","evaluate":true} - ] - }, - { "id": "circlesclock", - "name": "Circles clock", - "shortName":"Circles clock", - "version":"0.02", - "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"} - ] - }, - { - "id": "ltherm", - "name": "Localized Thermometer", - "shortName": "Thermometer", - "version": "0.01", - "description": "Displays the current temperature in localized units.", - "icon": "thermf.png", - "tags": "tool", - "supports": ["BANGLEJS2"], - "allow_emulator": true, - "readme": "README.md", - "storage": [ - {"name":"ltherm.app.js","url":"app.js"}, - {"name":"ltherm.img","url":"icon.js","evaluate":true} - ] - }, { "id": "aptsciclk", "name": "Apeture Science Clock", From 90fe8fb320a87c7005797b393344769e7d35dd3b Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:12:01 -0800 Subject: [PATCH 038/199] Added more icons, fake loading screen --- apps/aptsciclk/app.js | 66 ++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index cb1305c36..c6120593e 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -20,7 +20,7 @@ function getImg(img){ buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOZFIQOD4EABwnwgEDBwf8g/4h4ODwYQBv4OC+AbDAIP+j/HAQIOC4Hwj4RBBwP8o8B/+PBwWOkEP/l/BwP4+JCB44OCj+Ih/+n4OB+PEoP38YOB/0YkUXGgIOB8cBi9f+IOCkEI+XvBwXigFG64OEg0/t4OEuP7BwkHx/PBwWigF8voOC+Uwg/ig4OCkMgv8QsIOB+cfSoOGLIUR/E/4ljBwPxx/B/0kO4UI/0P+J3C/HHVQOISoWEn+D/iPBBwIwC8IOCwcP84IBBwU4TAMHBwfAv+AcARBBgD3CBwX8gDnBBwfwewIODAgIABBwYHDB3oAEBwIHFByyDBABg")) } } - else if (img == "w1"){//cube + else if (img == "w1"){//cube dispenser return { width : 60, height : 60, bpp : 1, buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOI/3/+fvBwYEBnwO/By3APgN/O6IeBh4OF8AOcwADCBwX8g4dM/8fBwt774OE+/9Bwt/BxodH3oOcFgyVG8BhCBwX8hRwCBwXA0C6BBwc/w4OE41MBwtEo6VF84sE/1/54OLDo4sHHYxKHLIxoGO44AD/kAABo")) @@ -38,7 +38,37 @@ function getImg(img){ buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOi+IOGh4OF8AOF/UNBwthx4OE+0YBwtBh4OE6mQBwn7rEfBwl22IOE99gBwn99UzBwUc/+90YsC8HH+++n98n/+g0++2Z+4OB4Fz73T74OCg877d8/YdC+d7u/v3gsBjEvt/+O4X+gvtIgI7CwG934OD8E326kD/0A+yzEwEO74OD/EArYOEgEDv4OD+PAl4OEnkBaInz0EPBwk3iAdE+XwSIYDBj2Oj4OD/fYvIOEvdHz4OD99unIOD/vt44OE3u4Dou3h4OE+3x/IOE70/Bwn78/9Bwl4LAQ7Dx75DBwP4Awb+EBwgAEBz0AABo=")) } } - else if (img == "w4"){//cake + else if (img == "w4"){//falling cube + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOC+YOF/0PBwvgv4OE/kFBwvAyIdFnYeBBwYeDDofng4OE8vYDonx7uPBwkf/+/Bwfh+czBwf+g/5z4OD+FevIdEhMDDon/0E3BwgeBJQgeB+5ZFvAEBBwfzgYOEw/XLInwn3BBwf8gH4LYIOCwUHDonwmE4HYkHwKkE8P4XYQOCv7dCYQkBWYsAWYvAiAsE/EDJQn/wF+CwJZDg/gBwgrBXYIOC8D+FNAL+F4eDBwn4nh2BBweHFYJ3EFYQOC/0P/AOECgIOE/E/BwsHBwvACAIODWAQOEJAIOFAgIOEQ4QsEAAOfBwoACBwgACBw8AABo")) +} + } + else if (img == "w5"){//ball + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOiv4OF8YOFAgQOEyYdGBw3zBw0BBwv4j4OB+EAgOD84OE+/ev4dD/3+BwvcugsE/u7t0f4aRC7e2sF8Bwlxg4dEu8YBwYsB/HDHYsMngOB8EDweHDon//PADoYABz0PBwfwnJKE/0OjZZC/kB4Hxz4OCwEYh+wBwXwgeA/+HBwUP8EP/0/BwPj/0DCQIOB/l/4DQBw4OBDIMPUoJKB+H/wY+B44OBj/4CoJKC+P/g7+FBAL+Fj4OFbwIOEI4IOF8YO6JQwAEaIgORgAANA")) + } + } + else if (img == "w6"){//ball recviver + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOR/YOG34Ob/e7Bwu7CwQOhGgQOD34OF/0LBwvfv4dMuPfBwn29oOFtwONDowsHHY3+h7CNj4OF+IOc4A7NDo7gGJQ4ACBwX+//vBwnvBAIOK8EH/kBBwd+v/PSwIOB/fnjiWBBwXesHPLQIOB/2AgEvBwfgh0AFgf8gAuBLKQObgAANA==")) + } + } + else if (img == "w7"){//falling portals + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YFE/H8BwtvBwvvvgOE/33Bwvf3gOE/v7Bxn5Bw2fHYv7/oOF3/cB118JQQOC4ODJQn8jEfLInBjBoE/0jO4pjD953CwCVF/EH5//+ykCwA8Cp4OB/MDz4DBEQUYjPzaIfn5k/74xC/l44f+BwePz1595ADDYPvv7vDMAN3Bwf4CAIOE4//BYIOB/0On47E8AFCBwcPTwYOCAgPAgE8Bwf8gEDBwOAGIJZDBwX9DofhUYRKDKIIOEAAQOD8EABwgcB+IODnoKB84OD37tCBwUzZ4QODZ4QdDnIFB/YODZwP+v47DJIIBBJQcAAwZyBABoA==")) + } + } + else if (img == "w8"){//flying portals + return { + width : 60, height : 60, bpp : 1, + buffer : require("heatshrink").decompress(atob("AB0//4AE4YFE/H8BwtvBwvvvgOE/33Bwvf3gdF/YOF/4OF/IOGgA7F8ENBwn8gHcBw/5AoOAg4OCh4sD/vD+AFB45KBBwfwv//BwMJgEIFAXcnvggF4kEBBwPMSIIYBz/8nAEBw5ZD4IhBO48AhpoG953FSo/2Ugv/p4OF/LCGaIyIBB34OH4EAngODbAMDBwnfDoqeCBy7RBBwnh//xBwc9BQPnBwe/AYO/BwUzFYQODGgYOCnIFB/YOD57WBv47Dj//AIJKDgAGDOQIANA")) + } + } + else if (img == "w9"){//cake return { width : 60, height : 60, bpp : 1, buffer : require("heatshrink").decompress(atob("AB0//4AE4YGF/gOY/oOG94OF/1/Bwv3FgwKCBwfnFhn8HY0LAQPwvgOB8EP/5uBBwP2gF4j+PBwP+sEEj/x44OB90Ao/8Dodwg8/nkH4ZXBgHnx8ABwPv/k98+ABwZEB+EAJQPj/3+nkAv4OB5+fz0Aj4OB98Ag+Ah/nBwJXB4EDHYSTB/EA/wsCSoJfBwAODNIPgBwgcBHYQOCC4QODn8Ah4ODGgMH+47D8EB/A7KTYMf4A7Eg/wHYgcBHZx3DcAPggbRBFgQcBcAQOB/iUBBwgcBBwgcCd4V/HYL+D/YOBDgIOC8/+DgIOC/+HfwIOD/4cCBwYAEBwQADBz0AABoA=")) @@ -71,7 +101,7 @@ function getImg(img){ return { width : 176, height : 176, bpp : 4, transparent : 2, - buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0SkQASkIVViIrqK/5X/K/5X/CqPd6EAAA8BiAKIABUBiIVUFZMIxBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xal////yK/5XTKwIABK4URAA3/+Pd6ILHAG8YxADBj5XD+ISIBwRX/K4pWDAAIHBiS6CAAMvBYXd6DbTeJcRCqgrJhGIJIJXFkUhK4oLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCkMSK4auDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAhXBAoa/Cl5X/K4ZHCAAZXEAoZnCK/5XLVQRXFBgZX/K4igCLAnxK4RdBBohX/K5cikJXCAAxX/K4j5EK/5X/K9fyK/5X/K93/K/5X/KxQABK78vK4PyK/5XWWApXq+JXC+BXeKwRXPl5Xdh//K4Y1BK+H/K7n//GIK4g5BWR5XP+RXNl5Xch+IGQJXFA4JXeJwpXICAJXah/4x4fBKwURj5XBBIJXcVwpXBFoYwDK4XRBYwAR/CtFAAZXCBQ4AQjBXCCRxXcUoJLDjnMhnMBgTqCK7RzIiS3FkRXC6DbTAAf4UYIoB5gABK4PM4KBD+AcLFZUIK4JNGkUhK44ABK7EPQwZWCK4ZYCWARXY+RXrVwccK4/MWB5XMJhBXkVwJWEK4pYBK/4AGh+IVwJQEK43BWARX/VwmP+JXNWBpX5VwMcK5fMiKwBK9YAKCphXCJ4pXH4JXB+QrWCtUvxHxK58R///K/5XCx/xjhPFdAJYGK/5XN4ACEK/4AIIYMRK4qsDWAsRj//+RX/iIACVw6wH4ITCEJBXlxGCARxXIVQoFEK+MoxGIARgQBK/5XbgAADK4oKEgJX/V/4AJxGCARxX/Cq5XI4AEIV+wVO///iMcVRC0FiMf//yTNIADlABCCp0v//xK4qrCVwpXB/+PeNRXf5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQVQ///K58f/HyK94VSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5UR/+IGgbeXK9awBLAhXEiKuBx40DHCYuEK9EvWAURK4/BVwSWEK/6wGLAZXCKwKuGK/6wIiMcK4QFBVw5X/WA2IwJSCAAYJBVwpX/WA2IJwJVDj///GPVwpX/A434K4PxVoYHBKwxX/AAynCK4ZWCGA5X/BI//V4itHK/4LKK4YtKK/4qJK4QOKK/5X/K8BYCBpZX/K/5XVfYQAWK6gedK/5XiBhchiINLK6grJK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xu/4AYV/4AXK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiKv/K/5X/K/5X/K/5X/K/5X6/4AdiIAYFzw=")) + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vQgAAHgMQBRAAKgMRCqgrJhGIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7Uv///+RX/K6ZWBAAJXDAA3/+Pd6IMIAG0YxADBj5XD+ISIBwRX/K4pWDAAIMCXQQABl4LC7vQbabxLiIVUFZMIxBJBK4siK4wLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UvK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYE+JXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5Xr+RX/K/5Xu/5X/K/5WKAAJXfl5XB+RX/K6ywFK9XxK4XwK7xWCK58vK7sP/5XDGoJXw/5Xc//4xBXEHIKyPK5/yK5svK7kPxAyBK4oHBK7xOFK5AQBK7UP/GPD4JWCiMfK4IJBK7iuFK4QAFj5XC6IMHACH4VooADK4QKHACEYK4QSOK7ilBJYcc5kM5gMCdQRXaOZK3FkRXC6DbTAAf4UYInB5gABK4PM4KBD+AcLFZUIK4JNGkRXIAAJXYh6GDKwRXDLASwCK7HyK9auDjhXH5iwPK5hMIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrABUhiQMKK4RPFK4/BK4PyFaxXql+I+JXPiP//5X/K4WP+McJ4roBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//yK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//yQaZXZlABCFZ0v//xK4qrCVwpXB/+PbahX15kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQrQ///K58f/HyK94rSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5TiBxA0Dby5XrWAJYEK4kRVwOPGgY4TFwhXol6wCiJXH4KuCSwhX/WAxYDK4RWBVwxX/WBERjhXCAoKuHK/6wGxGBKQQADBIKuFK/6wGxBOBKocf//4x6uFK/4HG/BXB+KtDA4JWGK/4AGU4RXDKwQwHK/4JH/6vEVo5X/BZRXDFpRX/ABEhK4QOKK/5X/K8BYCBpZX/K/5XVfYQAWK6gedK/5XiBhchiINLK6gJIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xv/4AYV/4AXK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiKv/K/5X/K/5X/K/5X/K/5X6/4AdiIAYFzwA=")) } } } @@ -84,8 +114,6 @@ function drawStart(){ g.drawImage(apSciLab, xyCenter-apSciLab.width/2, xyCenter-apSciLab.height/2); } -drawStart(); - // Check settings for what type our clock should be var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; @@ -94,7 +122,7 @@ var drawTimeout; //warnings var curWarning = -1; -var maxWarning = 4; +var maxWarning = 9; function buttonPressed(){ if (curWarning < maxWarning) curWarning += 1; @@ -155,7 +183,7 @@ function draw() { } g.setFont(font, timeFontSize); - g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, false); + g.drawString(`${hours}:${minutes}`, xyCenter+2, yposTime, false); g.setFont(font, gmtFontSize); g.drawString(meridian, xyCenter + 102, yposTime + 10, true); @@ -193,14 +221,18 @@ Bangle.on('touch',(n,e)=>{ } }); -// clean app screen -g.clear(); -// Show launcher when button pressed -Bangle.setUI("clock"); -Bangle.loadWidgets(); -Bangle.drawWidgets(); +//show Apeture laboritories +drawStart(); -buttonPressed();//update warning image - -// draw now -draw(); +setTimeout(function() { + // clean app screen + g.clear(); + // Show launcher when button pressed + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + //update warning image + buttonPressed(); + // draw now + draw(); + }, 1000); From bce419e78c512ec6809a84407363260a4e1c12bc Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:12:44 -0800 Subject: [PATCH 039/199] Create ChangeLog --- apps/aptsciclk/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/aptsciclk/ChangeLog diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog new file mode 100644 index 000000000..848bbea09 --- /dev/null +++ b/apps/aptsciclk/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Icons, loading screen From 6e0c1a9f273211e13c9042682fa5318517842556 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:13:22 -0800 Subject: [PATCH 040/199] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 1d792ecfc..7ac718a1a 100644 --- a/apps.json +++ b/apps.json @@ -2,12 +2,12 @@ { "id": "aptsciclk", "name": "Apeture Science Clock", - "version": "0.1", + "version": "0.2", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], + "supports": ["BANGLEJS2"], "allow_emulator": true, "storage": [ {"name":"aptsciclk.app.js","url":"app.js"}, From c125dc9e4d2c2b64fcba7717d5f6eb0e446c4a90 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:14:29 -0800 Subject: [PATCH 041/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7ac718a1a..1d0cb6a48 100644 --- a/apps.json +++ b/apps.json @@ -7,7 +7,7 @@ "icon": "app.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS2"], + "supports": "BANGLEJS2", "allow_emulator": true, "storage": [ {"name":"aptsciclk.app.js","url":"app.js"}, From ab1b77c0154e991c5e6f84efb74bfb1baff4ce19 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 28 Dec 2021 20:35:53 -0800 Subject: [PATCH 042/199] Random starter warning, shorter "loading" screen --- apps/aptsciclk/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index c6120593e..5b5e07825 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -121,8 +121,8 @@ var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; var drawTimeout; //warnings -var curWarning = -1; var maxWarning = 9; +var curWarning = Math.floor(Math.random() * (maxWarning+1)); function buttonPressed(){ if (curWarning < maxWarning) curWarning += 1; @@ -235,4 +235,4 @@ setTimeout(function() { buttonPressed(); // draw now draw(); - }, 1000); + }, 500); From 3b764dfec6bcb7220f897aaf1131a0d2322eb491 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 28 Dec 2021 20:38:26 -0800 Subject: [PATCH 043/199] 0.03 --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index 848bbea09..61e8307b8 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Icons, loading screen +0.03: Random icon, Shorter "loading" screen From a8bcbd6e684f2f74bedbc672718c910e83d7eb24 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 29 Dec 2021 09:11:36 -0800 Subject: [PATCH 044/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1d0cb6a48..1dbb784bf 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "aptsciclk", "name": "Apeture Science Clock", - "version": "0.2", + "version": "0.03", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", From 401aff4bcac00a7379c141a9a725816a40644b43 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 8 Jan 2022 12:02:32 -0800 Subject: [PATCH 045/199] "support" for light mode Doesn't look as good in my opinion --- apps/aptsciclk/app.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index 5b5e07825..b060541b5 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -78,7 +78,7 @@ function getImg(img){ return { width : 176, height : 176, bpp : 4, transparent : 1, - buffer : require("heatshrink").decompress(atob("iIA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AFEVqsFqpD/ACVVAAJXBqtRI35WSK4ZY/AB8VK49VJP5WRK4pY/ABhQEK41RJn5X/AEMVK5dVJv6uPK46w/K/4AgipPFgEALAxP/K5tQAQhX/K6KsDWApP/AA6uHWA9RIWPd6ICPK46qFAohXxjvd7oCMCAJX/K7cAAAZXFBQkBK/6v/ABPd6ICPK/4AaKIlQAhCv2ACMVVRC0FK2MdAIRXXVYSuFK/5XOqsAgCuFK/4AJJwtVKw1RK+MR7vRK/4AripXMJv6wQK4qu/K/4AjipXKJf5YRK4hJ/ABxXHqJI/LCRXCK34ASipXCIf4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACI=")) + buffer : require("heatshrink").decompress(atob("iIA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AFEc5kM5hD/ACXMAAJXB5nBI35WSK4ZY/AB8cK4/MJP5WRK4pY/ABhPD5e7he7A4fBJn5XNKwJXCLAZX/ABUcKwhXDLAZN/VxhSCK4m8WH5XNVwZXEWARX/ABEcK4sAgBYDXYRP/K5RQC2ACE3e8K/5XPVgYDCK/4AKJIPLVYoEEBoPBIWPd6ICPK46uDAohXzjvd7oCMCAJX/K7cAAAZXFBQkBK/6v/ABPd6ICPK/4AaK4mwKwYEDV+4ARjhKBVQoDD3gMBK2MdAIRXXVYSuDK/5XN5ZRCgEAWQYLBK/4AJK4u7KwZXC4JXxiPd6JXV5hXH3hX1ACscWApXDMQRN/WBpYCK4QICV35XOLARXBA4ZX/ABccKAfMhgFEJf5YRK4hJ/ABxXH4JI/LCRXCK34ASjhXCIf4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACIA==")) } } else if (img == "butUnpress"){ @@ -96,7 +96,15 @@ function getImg(img){ buffer : require("heatshrink").decompress(atob("AA+IAAeAIv5UTK34APhABBKwpeBJX5VLJgJWGAwKv/ABL8EKomABIYA/KpJWHAoRW/KpZQCfwJSCAgRW/KphWFBgZW/KphNCAgSxEKP4ADJAatFKwWAL4oA/KpALGXQhS/Ko4MIwAOMAHREOKv5ZVVgcAh///4LDAwQAB+AIHCQYHMDQQYBDwQEGDIoaGTx4MCwAiCJgYhFBIYIHLw4HFBARjGESJUDehZVFVhJNLRI5VGDIIdEAgwiL+DzDJAJVJB4IMBCoKsHAYpFCDgr2IApYEIBpJFCKpqsCHgQbFIhBVHBhJoGTwyBRKp5mBDoY6GKoYqEXYg7JApKeHQJysEKpRmBDoasHQBAACM4qMGEAr0JAgZjGFYhVPgGAEIpVEAAaAEA4oyEW4qyKFZBoFKoisDJIJWLfIp3IQBJeJfgysMERpVCwEIVpijFBA6ZJdA4JHJYgEKQIx1EVgRVBVhj5IEIyZHHYoUGNw4MCQIwIKAARVDxBVRQo6ZJHZZoGU4yBGBAiBGVgRZBVhYlIfJBoFHZZoHfJRwGBAQrEVISvCKpwrEUZAqFVhzYKB4yKGQIpVDAYJVKEoYFDBIpVIb4ysMIgoPHOgoRFhGAVwKsLAFzQHACBVCVhQA/KpawBCJa76IhRWDVxIODAwTaFAocP///dhALGBQYJBCIYQBDYgKEBBAEDVgeIAgKgFBYZVEEYY+CH4YDBBgYFBBYoFEOYhmEDYgFFLIwEDKw2AKwhTFBoSsHIgglFAQo/HKIoDECBBZGc46eEAYa2EKox2Ga5LjLDoq8FKAgVDBAv/EghWGVgRWJKoaOFD4IgCViAWFVjKTGJIZOFKpKOHAQj3JAogCFPApcGKQziGLopKCU4hWFKojsEHYrXFCAJFId45CEDYh4EB4Y1DCYSzFJQT+FgAGCKooA/AAZMBfopWDKv5WLVgxT/AB+AKopW/ACBU/ABwA==")) } } - + +else if (img == "apetureLaboratoriesLight"){ + return { + width : 173, height : 43, bpp : 4, + transparent : 1, + buffer : require("heatshrink").decompress(atob("iIAGxAADwINHAH5ULK34APjABBKwpeBJX5VLJgJWGAwKv/ABL8EKomBBIYA/KpJWHAoRW/KpZQCfwJSCAgRW/KphWFBgZW/KphNCAgSxEKP4ADJAatFKwWBL4oA/KpALGXQhS/Ko4MIwIOMAHREOKv5ZVVgcRiEAgALDAwQABgIIHCQYHMDQQYBDwQEGDIoaGTx4MCwIiCJgYhFBIYIHLw4HFBARjGESJUDehZVFVhJNLRI5VGDIIdEAgwiLgLzDJAJVJB4IMBCoKsHAYpFCDgr2IApYEIBpJFCKpqsCHgQbFIhBVHBhJoGTwyBRKp5mBDoY6GKoYqEXYg7JApKeHQJysEKpRmBDoasHQBAACM4qMGEAr0JAgZjGFYhVPiOBEIpVEAAaAEA4oyEW4qyKFZBoFKoisDJIJWLfIp3IQBJeJfgysMERpVCwMYVpijFBA6ZJdA4JHJYgEKQIx1EVgRVBVhj5IEIyZHHYoUGNw4MCQIwIKAARVDxBVRQo6ZJHZZoGU4yBGBAiBGVgRZBVhYlIfJBoFHZZoHfJRwGBAQrEVISvCKpwrEUZAqFVhzYKB4yKGQIpVDAYJVKEoYFDBIpVIb4ysMIgoPHOgoRFjGBVwKsLAFzQHACBVCVhQA/KpawBCJa76IhRWDVxIODAwTaFAocQgEAdhALGBQYJBCIYQBDYgKEBBAEDVgeIAgKgFBYZVEEYY+CH4YDBBgYFBBYoFEOYhmEDYgFFLIwEDKw2BKwhTFBoSsHIgglFAQo/HKIoDECBBZGc46eEAYa2EKox2Ga5LjLDoq8FKAgVDBAsAEghWGVgRWJKoaOFD4IgCViAWFVjKTGJIZOFKpKOHAQj3JAogCFPApcGKQziGLopKCU4hWFKojsEHYrXFCAJFId45CEDYh4EB4Y1DCYSzFJQT+FiIGCKooA/AAZMBfopWDKv5WLVgxT/AB+BKopW/ACBU/ABsQA=")) +} + } + else if (img == "apetureWatch"){ return { width : 176, height : 176, bpp : 4, @@ -104,13 +112,22 @@ function getImg(img){ buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vQgAAHgMQBRAAKgMRCqgrJhGIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7Uv///+RX/K6ZWBAAJXDAA3/+Pd6IMIAG0YxADBj5XD+ISIBwRX/K4pWDAAIMCXQQABl4LC7vQbabxLiIVUFZMIxBJBK4siK4wLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UvK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYE+JXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5Xr+RX/K/5Xu/5X/K/5WKAAJXfl5XB+RX/K6ywFK9XxK4XwK7xWCK58vK7sP/5XDGoJXw/5Xc//4xBXEHIKyPK5/yK5svK7kPxAyBK4oHBK7xOFK5AQBK7UP/GPD4JWCiMfK4IJBK7iuFK4QAFj5XC6IMHACH4VooADK4QKHACEYK4QSOK7ilBJYcc5kM5gMCdQRXaOZK3FkRXC6DbTAAf4UYInB5gABK4PM4KBD+AcLFZUIK4JNGkRXIAAJXYh6GDKwRXDLASwCK7HyK9auDjhXH5iwPK5hMIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrABUhiQMKK4RPFK4/BK4PyFaxXql+I+JXPiP//5X/K4WP+McJ4roBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//yK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//yQaZXZlABCFZ0v//xK4qrCVwpXB/+PbahX15kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQrQ///K58f/HyK94rSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5TiBxA0Dby5XrWAJYEK4kRVwOPGgY4TFwhXol6wCiJXH4KuCSwhX/WAxYDK4RWBVwxX/WBERjhXCAoKuHK/6wGxGBKQQADBIKuFK/6wGxBOBKocf//4x6uFK/4HG/BXB+KtDA4JWGK/4AGU4RXDKwQwHK/4JH/6vEVo5X/BZRXDFpRX/ABEhK4QOKK/5X/K8BYCBpZX/K/5XVfYQAWK6gedK/5XiBhchiINLK6gJIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xv/4AYV/4AXK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiKv/K/5X/K/5X/K/5X/K/5X6/4AdiIAYFzwA=")) } } + + else if (img == "apetureWatchLight"){ + return { + width : 176, height : 176, bpp : 4, + transparent : 2, + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+gAA/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vf/4AH+MfBRAAK+MRCqgrJ/GIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7UggEAgRX/K6ZWBAAJXDAA0AgPd6IMIAG0YxADBiBXDgISIBwRX/K4pWDAAIMCXQQABkALC7vfbabxLiIVUFZP4xBJBK4siK4wLDK/5XSBYhX/K6MgBIQDBK/5XDgRXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XFgSuEK4yuCK/5XHWAZOCK4cgKwhX/K45MFK4YAGK/5XGLApX/K6UAK5sgK/5XIWAZXJgBX/K6sgK/5XPAoauDK/5XJgBXDiBeEVwRX/K5y2FVwRX/K48CK44GDVwRX/K50QWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYUCK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UgK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYEgJXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5XrgRX/K/5XugBX/K/5WKAAJXfkBXBgRXvgJXCh5XhWApXoF4KvD+EALKBXMKwRXPkBXcgAUCK4QFB+BYPK78AK7ZWBGYJXExBYQK58CK5sgK7fwJ4JQBK4pYCK7pOFK5AQBK7UP/GPAgJWCiMfK4IJBWBpXOVwpXCAAsQK4XRBg4APgAwBVogADK4XwgInWjBXCCRxXbiD9BKwcc5kM5gNCS4XwK7JyJW4siK4XfbaZGD/CjBE4PMAAJXB5nBiIaC+AdLFZTWBgBNGkRXIAAJXYh6uDKwRXDLAQRDK68CK9SuEjhXH5iwPK5hMIK8UP/APBKwhXFLAKwNK/OIVwJQEK43BDgRX/AAXw/GP+JXNWAXwK/5XDVwMcK5fMiIdBK9YAKkMSBZMPK4RPFK4/BJIUCFagAJK8WI+JXPiJX/K4mP+McJ4sAgBYGK/5XN4ACEK/4AHkBDBiJXFVgawFiMf//wK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrNkH//8RjiqIWgsRj//+CDTK7MoAIQrOh//+JXFVYSuFK4P/x8CK/5XJ5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwRXR/5XPj/4/5XvFaMgK4UcK5kRj+I+ArVK5UAADpXE+KwGK4vBiP4x5XhaBIATkADCh6wCK5kf/H/GpRX7+McK5UR/+IK4beWK9MgK4KwBLAhXEiKuBx/wCwQ4TFwZXoWAkRK4/BVwxX/WA5YDK4RWBVwxX/K4ywBiMcK4QFBVwZX/FA8AK4OIwJSCAAYJBVwIzEK/4ADh5NBJwJVDj///GP/4yFK/4GEJwJXB+KtDA4P/+ATFK/4AEgCnCK4ZWDGIxX/LA//V4hWIK/5YIgBXD+EAF5BX/ABEBK4QtKK/4AIkJXCBxRX/LBYNLK/5X/K6r7CACxXUDzpX/K8QMLkMRBpZXUBJBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K98AADCv/AC5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5XVgAAYV/4AJkMRV/5X/K/5X/K/5X/K/5X/K/UAADsRADAueA==")) + } + } } function drawStart(){ g.clear(); g.reset(); - apSciLab = getImg("apetureLaboratories"); + if (g.theme.dark){apSciLab = getImg("apetureLaboratories");} + else {apSciLab = getImg("apetureLaboratoriesLight");} g.drawImage(apSciLab, xyCenter-apSciLab.width/2, xyCenter-apSciLab.height/2); } @@ -156,9 +173,9 @@ function draw() { var da = d.toString().split(" "); g.reset(); // default draw styles - //draw watchface - apSciWatch = getImg("apetureWatch"); + if (g.theme.dark){apSciWatch = getImg("apetureWatch");} + else {apSciWatch = getImg("apetureWatchLight");} g.drawImage(apSciWatch, xyCenter-apSciWatch.width/2, xyCenter-apSciWatch.height/2); // drawSting centered From b8985e4b9996e45ff05a1276c46ee395bc78c68e Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 8 Jan 2022 12:03:21 -0800 Subject: [PATCH 046/199] Update ChangeLog --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index 61e8307b8..719f1d418 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Icons, loading screen 0.03: Random icon, Shorter "loading" screen +0.04: Support for light and dark Themes From 52a97bb7dcfddfbb0d0a99353f6a5f3dc217e5c9 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 8 Jan 2022 12:04:14 -0800 Subject: [PATCH 047/199] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 1dbb784bf..b95ff9d8e 100644 --- a/apps.json +++ b/apps.json @@ -1,8 +1,8 @@ [ { "id": "aptsciclk", - "name": "Apeture Science Clock", - "version": "0.03", + "name": "Apeture Sci Clock", + "version": "0.04", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", From 4dbec88b7f1e4bb741916fbaeb3c156b2c95fd08 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Tue, 14 Dec 2021 21:42:58 +0100 Subject: [PATCH 048/199] Port banglerun to new typescript system --- apps/banglerun/README.md | 19 +------------------ apps/banglerun/{src => }/activity.ts | 0 apps/banglerun/{src => }/app.ts | 0 apps/banglerun/{src => }/display.ts | 0 apps/banglerun/{src => }/gps.ts | 0 apps/banglerun/{src => }/hrm.ts | 0 apps/banglerun/{src => }/log.ts | 8 +++++--- apps/banglerun/package.json | 27 --------------------------- apps/banglerun/{src => }/state.ts | 18 +++++++++++++----- apps/banglerun/{src => }/step.ts | 0 apps/banglerun/tsconfig.json | 10 ---------- apps/banglerun/tsconfig.spec.json | 10 ---------- typescript/tsconfig.json | 4 ++-- 13 files changed, 21 insertions(+), 75 deletions(-) rename apps/banglerun/{src => }/activity.ts (100%) rename apps/banglerun/{src => }/app.ts (100%) rename apps/banglerun/{src => }/display.ts (100%) rename apps/banglerun/{src => }/gps.ts (100%) rename apps/banglerun/{src => }/hrm.ts (100%) rename apps/banglerun/{src => }/log.ts (80%) delete mode 100644 apps/banglerun/package.json rename apps/banglerun/{src => }/state.ts (80%) rename apps/banglerun/{src => }/step.ts (100%) delete mode 100644 apps/banglerun/tsconfig.json delete mode 100644 apps/banglerun/tsconfig.spec.json diff --git a/apps/banglerun/README.md b/apps/banglerun/README.md index 80e984bfa..99fbaaf1a 100644 --- a/apps/banglerun/README.md +++ b/apps/banglerun/README.md @@ -5,21 +5,4 @@ An app for running sessions. Displays info and logs your run for later viewing. ## Compilation The app is written in Typescript, and needs to be transpiled in order to be -run on the BangleJS. The easiest way to perform this step is by using the -ubiquitous [NPM package manager](https://www.npmjs.com/get-npm). - -After having installed NPM for your platform, checkout the `BangleApps` repo, -open a terminal, and navigate into the `apps/banglerun` folder. Then issue: - -``` -npm i -``` - -to install the project's build tools, and: - -``` -npm run build -``` - -To build the app. The last command will generate the `app.js` file, containing -the transpiled code for the BangleJS. +run on the BangleJS. See ../../typescript/README.md for instructions. diff --git a/apps/banglerun/src/activity.ts b/apps/banglerun/activity.ts similarity index 100% rename from apps/banglerun/src/activity.ts rename to apps/banglerun/activity.ts diff --git a/apps/banglerun/src/app.ts b/apps/banglerun/app.ts similarity index 100% rename from apps/banglerun/src/app.ts rename to apps/banglerun/app.ts diff --git a/apps/banglerun/src/display.ts b/apps/banglerun/display.ts similarity index 100% rename from apps/banglerun/src/display.ts rename to apps/banglerun/display.ts diff --git a/apps/banglerun/src/gps.ts b/apps/banglerun/gps.ts similarity index 100% rename from apps/banglerun/src/gps.ts rename to apps/banglerun/gps.ts diff --git a/apps/banglerun/src/hrm.ts b/apps/banglerun/hrm.ts similarity index 100% rename from apps/banglerun/src/hrm.ts rename to apps/banglerun/hrm.ts diff --git a/apps/banglerun/src/log.ts b/apps/banglerun/log.ts similarity index 80% rename from apps/banglerun/src/log.ts rename to apps/banglerun/log.ts index b6714e407..282115e1a 100644 --- a/apps/banglerun/src/log.ts +++ b/apps/banglerun/log.ts @@ -1,17 +1,19 @@ -import { AppState } from './state'; +import { AppState, AppStateWithLog } from './state'; declare var require: any; -function initLog(state: AppState): void { +function initLog(state: AppState): AppStateWithLog { const datetime = new Date().toISOString().replace(/[-:]/g, ''); const date = datetime.substr(2, 6); const time = datetime.substr(9, 6); const filename = `banglerun_${date}_${time}`; + state = state; state.file = require('Storage').open(filename, 'w'); state.fileWritten = false; + return state; } -function updateLog(state: AppState): void { +function updateLog(state: AppStateWithLog): void { if (!state.fileWritten) { state.file.write([ 'timestamp', diff --git a/apps/banglerun/package.json b/apps/banglerun/package.json deleted file mode 100644 index 1f5cc677b..000000000 --- a/apps/banglerun/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "banglerun", - "version": "0.5.0", - "description": "Bangle.js app for running sessions", - "main": "app.js", - "types": "app.d.ts", - "scripts": { - "build": "rollup -c", - "test": "ts-node -P tsconfig.spec.json node_modules/jasmine/bin/jasmine --config=jasmine.json" - }, - "author": { - "name": "Stefano Baldan", - "email": "singintime@gmail.com" - }, - "license": "ISC", - "devDependencies": { - "@rollup/plugin-typescript": "^4.1.1", - "@types/jasmine": "^3.5.10", - "jasmine": "^3.5.0", - "rollup": "^2.10.2", - "rollup-plugin-terser": "^5.3.0", - "terser": "^4.7.0", - "ts-node": "^8.10.2", - "tslib": "^2.0.0", - "typescript": "^3.9.2" - } -} diff --git a/apps/banglerun/src/state.ts b/apps/banglerun/state.ts similarity index 80% rename from apps/banglerun/src/state.ts rename to apps/banglerun/state.ts index 14ef2dc5d..1ba9bca26 100644 --- a/apps/banglerun/src/state.ts +++ b/apps/banglerun/state.ts @@ -4,7 +4,7 @@ enum ActivityStatus { Running = 'RUN', } -interface AppState { +interface BasicAppState { // GPS NMEA data fix: number; lat: number; @@ -28,14 +28,12 @@ interface AppState { hrError: number, // Logger data - file: File; fileWritten: boolean; // Drawing data drawing: boolean; // Activity data - status: ActivityStatus; duration: number; distance: number; speed: number; @@ -43,6 +41,17 @@ interface AppState { cadence: number; } +interface AppStateWithoutLog extends BasicAppState { + status: 'STOP'; +} + +interface AppStateWithLog extends BasicAppState { + file: File; + status: ActivityStatus; +} + +type AppState = AppStateWithLog | AppStateWithoutLog; + interface File { read: Function; write: Function; @@ -68,7 +77,6 @@ function initState(): AppState { hr: 60, hrError: 100, - file: null, fileWritten: false, drawing: false, @@ -82,4 +90,4 @@ function initState(): AppState { } } -export { ActivityStatus, AppState, File, initState }; +export { ActivityStatus, AppState, AppStateWithLog, File, initState }; diff --git a/apps/banglerun/src/step.ts b/apps/banglerun/step.ts similarity index 100% rename from apps/banglerun/src/step.ts rename to apps/banglerun/step.ts diff --git a/apps/banglerun/tsconfig.json b/apps/banglerun/tsconfig.json deleted file mode 100644 index a341a5a5e..000000000 --- a/apps/banglerun/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "module": "es2015", - "noImplicitAny": true, - "target": "es2015" - }, - "include": [ - "src" - ] -} diff --git a/apps/banglerun/tsconfig.spec.json b/apps/banglerun/tsconfig.spec.json deleted file mode 100644 index 136ae137b..000000000 --- a/apps/banglerun/tsconfig.spec.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "noImplicitAny": true, - "target": "es2015" - }, - "include": [ - "test" - ] -} diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 40537c680..e9327be68 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -14,6 +14,6 @@ "strict": true }, "include": ["../apps/**/*", "./**/*"], - // these apps have been excluded because they were built before this configuration was created and are using their own - "exclude": ["../apps/banglerun", "../apps/hebrew_calendar"] + // this app is excluded because it was built before this configuration was created and is using its own + "exclude": ["../apps/hebrew_calendar"] } From 7b37391553c654f03a29a95f4f29b9c1849a3925 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 20:58:26 +0100 Subject: [PATCH 049/199] remove unused files from /banglerun, replace banglerun js code with newly compiled code --- apps/banglerun/.gitignore | 1 - apps/banglerun/README.md | 8 --- apps/banglerun/activity.js | 35 ++++++++++++ apps/banglerun/app.js | 14 ++++- apps/banglerun/display.js | 95 +++++++++++++++++++++++++++++++++ apps/banglerun/gps.js | 66 +++++++++++++++++++++++ apps/banglerun/hrm.js | 15 ++++++ apps/banglerun/jasmine.json | 6 --- apps/banglerun/log.js | 36 +++++++++++++ apps/banglerun/rollup.config.js | 15 ------ apps/banglerun/state.js | 33 ++++++++++++ apps/banglerun/step.js | 10 ++++ typescript/tsconfig.json | 4 +- 13 files changed, 304 insertions(+), 34 deletions(-) delete mode 100644 apps/banglerun/.gitignore delete mode 100644 apps/banglerun/README.md create mode 100644 apps/banglerun/activity.js create mode 100644 apps/banglerun/display.js create mode 100644 apps/banglerun/gps.js create mode 100644 apps/banglerun/hrm.js delete mode 100644 apps/banglerun/jasmine.json create mode 100644 apps/banglerun/log.js delete mode 100644 apps/banglerun/rollup.config.js create mode 100644 apps/banglerun/state.js create mode 100644 apps/banglerun/step.js diff --git a/apps/banglerun/.gitignore b/apps/banglerun/.gitignore deleted file mode 100644 index c2658d7d1..000000000 --- a/apps/banglerun/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ diff --git a/apps/banglerun/README.md b/apps/banglerun/README.md deleted file mode 100644 index 99fbaaf1a..000000000 --- a/apps/banglerun/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# BangleRun - -An app for running sessions. Displays info and logs your run for later viewing. - -## Compilation - -The app is written in Typescript, and needs to be transpiled in order to be -run on the BangleJS. See ../../typescript/README.md for instructions. diff --git a/apps/banglerun/activity.js b/apps/banglerun/activity.js new file mode 100644 index 000000000..818f9cf2a --- /dev/null +++ b/apps/banglerun/activity.js @@ -0,0 +1,35 @@ +import { draw } from './display'; +import { initLog } from './log'; +import { ActivityStatus } from './state'; +function startActivity(state) { + if (state.status === ActivityStatus.Stopped) { + initLog(state); + } + if (state.status === ActivityStatus.Running) { + state.status = ActivityStatus.Paused; + } + else { + state.status = ActivityStatus.Running; + } + draw(state); +} +function stopActivity(state) { + if (state.status === ActivityStatus.Paused) { + clearActivity(state); + } + if (state.status === ActivityStatus.Running) { + state.status = ActivityStatus.Paused; + } + else { + state.status = ActivityStatus.Stopped; + } + draw(state); +} +function clearActivity(state) { + state.duration = 0; + state.distance = 0; + state.speed = 0; + state.steps = 0; + state.cadence = 0; +} +export { clearActivity, startActivity, stopActivity }; diff --git a/apps/banglerun/app.js b/apps/banglerun/app.js index b79255171..af5413cc0 100644 --- a/apps/banglerun/app.js +++ b/apps/banglerun/app.js @@ -1 +1,13 @@ -!function(){"use strict";var t;!function(t){t.Stopped="STOP",t.Paused="PAUSE",t.Running="RUN"}(t||(t={}));const n={STOP:63488,PAUSE:65504,RUN:2016};function e(t,n,e){g.setColor(0),g.fillRect(n-60,e,n+60,e+30),g.setColor(65535),g.drawString(t,n,e)}function i(i){var s;g.setFontVector(30),g.setFontAlign(0,-1,0),e((i.distance/1e3).toFixed(2),60,55),e(function(t){const n=Math.round(t),e=Math.floor(n/3600),i=Math.floor(n/60)%60,s=n%60;return(e?e+":":"")+("0"+i).substr(-2)+":"+("0"+s).substr(-2)}(i.duration),172,55),e(function(t){if(t<.1667)return"__'__\"";const n=Math.round(1e3/t),e=Math.floor(n/60),i=n%60;return("0"+e).substr(-2)+"'"+("0"+i).substr(-2)+'"'}(i.speed),60,115),e(i.hr.toFixed(0),172,115),e(i.steps.toFixed(0),60,175),e(i.cadence.toFixed(0),172,175),g.setFont("6x8",2),g.setColor(i.gpsValid?2016:63488),g.fillRect(0,216,80,240),g.setColor(0),g.drawString("GPS",40,220),g.setColor(65535),g.fillRect(80,216,160,240),g.setColor(0),g.drawString(("0"+(s=new Date).getHours()).substr(-2)+":"+("0"+s.getMinutes()).substr(-2),120,220),g.setColor(n[i.status]),g.fillRect(160,216,230,240),g.setColor(0),g.drawString(i.status,200,220),g.setFont("6x8").setFontAlign(0,0,1).setColor(-1),i.status===t.Paused?g.drawString("START",236,60,1).drawString(" CLEAR ",236,180,1):i.status===t.Running?g.drawString(" PAUSE ",236,60,1).drawString(" PAUSE ",236,180,1):g.drawString("START",236,60,1).drawString(" ",236,180,1)}function s(t){g.clear(),g.setColor(50712),g.setFont("6x8",2),g.setFontAlign(0,-1,0),g.drawString("DIST (KM)",60,32),g.drawString("TIME",180,32),g.drawString("PACE",60,92),g.drawString("HEART",180,92),g.drawString("STEPS",60,152),g.drawString("CADENCE",180,152),i(t),Bangle.drawWidgets()}function a(n){n.status===t.Stopped&&function(t){const n=(new Date).toISOString().replace(/[-:]/g,""),e=`banglerun_${n.substr(2,6)}_${n.substr(9,6)}`;t.file=require("Storage").open(e,"w"),t.fileWritten=!1}(n),n.status===t.Running?n.status=t.Paused:n.status=t.Running,i(n)}const r={fix:NaN,lat:NaN,lon:NaN,alt:NaN,vel:NaN,dop:NaN,gpsValid:!1,x:NaN,y:NaN,z:NaN,t:NaN,timeSinceLog:0,hr:60,hrError:100,file:null,fileWritten:!1,drawing:!1,status:t.Stopped,duration:0,distance:0,speed:0,steps:0,cadence:0};var o;o=r,Bangle.on("GPS",n=>function(n,e){n.lat=e.lat,n.lon=e.lon,n.alt=e.alt,n.vel=e.speed/3.6,n.fix=e.fix,n.dop=e.hdop,n.gpsValid=n.fix>0,function(n){const e=Date.now();let i=(e-n.t)/1e3;if(isFinite(i)||(i=0),n.t=e,n.timeSinceLog+=i,n.status===t.Running&&(n.duration+=i),!n.gpsValid)return;const s=6371008.8+n.alt,a=n.lat*Math.PI/180,r=n.lon*Math.PI/180,o=s*Math.cos(a)*Math.cos(r),g=s*Math.cos(a)*Math.sin(r),d=s*Math.sin(a);if(!n.x)return n.x=o,n.y=g,void(n.z=d);const u=o-n.x,l=g-n.y,c=d-n.z,f=Math.sqrt(u*u+l*l+c*c);n.x=o,n.y=g,n.z=d,n.status===t.Running&&(n.distance+=f,n.speed=n.distance/n.duration||0,n.cadence=60*n.steps/n.duration||0)}(n),i(n),n.gpsValid&&n.status===t.Running&&n.timeSinceLog>5&&(n.timeSinceLog=0,function(t){t.fileWritten||(t.file.write(["timestamp","latitude","longitude","altitude","duration","distance","heartrate","steps"].join(",")+"\n"),t.fileWritten=!0),t.file.write([Date.now().toFixed(0),t.lat.toFixed(6),t.lon.toFixed(6),t.alt.toFixed(2),t.duration.toFixed(0),t.distance.toFixed(2),t.hr.toFixed(0),t.steps.toFixed(0)].join(",")+"\n")}(n))}(o,n)),Bangle.setGPSPower(1),function(t){Bangle.on("HRM",n=>function(t,n){if(0===n.confidence)return;const e=n.bpm-t.hr,i=Math.abs(e)+101-n.confidence,s=t.hrError/(t.hrError+i)||0;t.hr+=e*s,t.hrError+=(i-t.hrError)*s}(t,n)),Bangle.setHRMPower(1)}(r),function(n){Bangle.on("step",()=>function(n){n.status===t.Running&&(n.steps+=1)}(n))}(r),function(t){Bangle.loadWidgets(),Bangle.on("lcdPower",n=>{t.drawing=n,n&&s(t)}),s(t)}(r),setWatch(()=>a(r),BTN1,{repeat:!0,edge:"falling"}),setWatch(()=>function(n){n.status===t.Paused&&function(t){t.duration=0,t.distance=0,t.speed=0,t.steps=0,t.cadence=0}(n),n.status===t.Running?n.status=t.Paused:n.status=t.Stopped,i(n)}(r),BTN3,{repeat:!0,edge:"falling"})}(); +import { startActivity, stopActivity } from './activity'; +import { initDisplay } from './display'; +import { initGps } from './gps'; +import { initHrm } from './hrm'; +import { initState } from './state'; +import { initStep } from './step'; +const appState = initState(); +initGps(appState); +initHrm(appState); +initStep(appState); +initDisplay(appState); +setWatch(() => startActivity(appState), BTN1, { repeat: true, edge: 'falling' }); +setWatch(() => stopActivity(appState), BTN3, { repeat: true, edge: 'falling' }); diff --git a/apps/banglerun/display.js b/apps/banglerun/display.js new file mode 100644 index 000000000..2768e8973 --- /dev/null +++ b/apps/banglerun/display.js @@ -0,0 +1,95 @@ +import { ActivityStatus } from './state'; +const STATUS_COLORS = { + 'STOP': 0xF800, + 'PAUSE': 0xFFE0, + 'RUN': 0x07E0, +}; +function initDisplay(state) { + Bangle.loadWidgets(); + Bangle.on('lcdPower', (on) => { + state.drawing = on; + if (on) { + drawAll(state); + } + }); + drawAll(state); +} +function drawBackground() { + g.clear(); + g.setColor(0xC618); + g.setFont('6x8', 2); + g.setFontAlign(0, -1, 0); + g.drawString('DIST (KM)', 60, 32); + g.drawString('TIME', 172, 32); + g.drawString('PACE', 60, 92); + g.drawString('HEART', 172, 92); + g.drawString('STEPS', 60, 152); + g.drawString('CADENCE', 172, 152); +} +function drawValue(value, x, y) { + g.setColor(0x0000); + g.fillRect(x - 60, y, x + 60, y + 30); + g.setColor(0xFFFF); + g.drawString(value, x, y); +} +function draw(state) { + g.setFontVector(30); + g.setFontAlign(0, -1, 0); + drawValue(formatDistance(state.distance), 60, 55); + drawValue(formatTime(state.duration), 172, 55); + drawValue(formatPace(state.speed), 60, 115); + drawValue(state.hr.toFixed(0), 172, 115); + drawValue(state.steps.toFixed(0), 60, 175); + drawValue(state.cadence.toFixed(0), 172, 175); + g.setFont('6x8', 2); + g.setColor(state.gpsValid ? 0x07E0 : 0xF800); + g.fillRect(0, 216, 80, 240); + g.setColor(0x0000); + g.drawString('GPS', 40, 220); + g.setColor(0xFFFF); + g.fillRect(80, 216, 160, 240); + g.setColor(0x0000); + g.drawString(formatClock(new Date()), 120, 220); + g.setColor(STATUS_COLORS[state.status]); + g.fillRect(160, 216, 230, 240); + g.setColor(0x0000); + g.drawString(state.status, 200, 220); + g.setFont("6x8").setFontAlign(0, 0, 1).setColor(-1); + if (state.status === ActivityStatus.Paused) { + g.drawString("START", 236, 60, 1).drawString(" CLEAR ", 236, 180, 1); + } + else if (state.status === ActivityStatus.Running) { + g.drawString(" PAUSE ", 236, 60, 1).drawString(" PAUSE ", 236, 180, 1); + } + else { + g.drawString("START", 236, 60, 1).drawString(" ", 236, 180, 1); + } +} +function drawAll(state) { + drawBackground(); + draw(state); + Bangle.drawWidgets(); +} +function formatClock(date) { + return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); +} +function formatDistance(meters) { + return (meters / 1000).toFixed(2); +} +function formatPace(speed) { + if (speed < 0.1667) { + return `__'__"`; + } + const pace = Math.round(1000 / speed); + const min = Math.floor(pace / 60); + const sec = pace % 60; + return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; +} +function formatTime(time) { + const seconds = Math.round(time); + const hrs = Math.floor(seconds / 3600); + const min = Math.floor(seconds / 60) % 60; + const sec = seconds % 60; + return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); +} +export { draw, drawAll, drawBackground, drawValue, formatClock, formatDistance, formatPace, formatTime, initDisplay, }; diff --git a/apps/banglerun/gps.js b/apps/banglerun/gps.js new file mode 100644 index 000000000..d06215cd5 --- /dev/null +++ b/apps/banglerun/gps.js @@ -0,0 +1,66 @@ +import { draw } from './display'; +import { updateLog } from './log'; +import { ActivityStatus } from './state'; +const EARTH_RADIUS = 6371008.8; +function initGps(state) { + Bangle.on('GPS', (gps) => readGps(state, gps)); + Bangle.setGPSPower(1); +} +function readGps(state, gps) { + state.lat = gps.lat; + state.lon = gps.lon; + state.alt = gps.alt; + state.vel = gps.speed / 3.6; + state.fix = gps.fix; + state.dop = gps.hdop; + state.gpsValid = state.fix > 0; + updateGps(state); + draw(state); + /* Only log GPS data every 5 secs if we + have a fix and we're running. */ + if (state.gpsValid && + state.status === ActivityStatus.Running && + state.timeSinceLog > 5) { + state.timeSinceLog = 0; + updateLog(state); + } +} +function updateGps(state) { + const t = Date.now(); + let dt = (t - state.t) / 1000; + if (!isFinite(dt)) + dt = 0; + state.t = t; + state.timeSinceLog += dt; + if (state.status === ActivityStatus.Running) { + state.duration += dt; + } + if (!state.gpsValid) { + return; + } + const r = EARTH_RADIUS + state.alt; + const lat = state.lat * Math.PI / 180; + const lon = state.lon * Math.PI / 180; + const x = r * Math.cos(lat) * Math.cos(lon); + const y = r * Math.cos(lat) * Math.sin(lon); + const z = r * Math.sin(lat); + if (!state.x) { + state.x = x; + state.y = y; + state.z = z; + return; + } + const dx = x - state.x; + const dy = y - state.y; + const dz = z - state.z; + const dpMag = Math.sqrt(dx * dx + dy * dy + dz * dz); + state.x = x; + state.y = y; + state.z = z; + if (state.status === ActivityStatus.Running) { + state.distance += dpMag; + state.speed = (state.distance / state.duration) || 0; + state.cadence = (60 * state.steps / state.duration) || 0; + } +} +export { initGps, readGps, updateGps }; diff --git a/apps/banglerun/hrm.js b/apps/banglerun/hrm.js new file mode 100644 index 000000000..35804f5e8 --- /dev/null +++ b/apps/banglerun/hrm.js @@ -0,0 +1,15 @@ +function initHrm(state) { + Bangle.on('HRM', (hrm) => updateHrm(state, hrm)); + Bangle.setHRMPower(1); +} +function updateHrm(state, hrm) { + if (hrm.confidence === 0) { + return; + } + const dHr = hrm.bpm - state.hr; + const hrError = Math.abs(dHr) + 101 - hrm.confidence; + const hrGain = (state.hrError / (state.hrError + hrError)) || 0; + state.hr += dHr * hrGain; + state.hrError += (hrError - state.hrError) * hrGain; +} +export { initHrm, updateHrm }; diff --git a/apps/banglerun/jasmine.json b/apps/banglerun/jasmine.json deleted file mode 100644 index 813363b27..000000000 --- a/apps/banglerun/jasmine.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "spec_dir": "test", - "spec_files": [ - "**/*.spec.ts" - ] -} \ No newline at end of file diff --git a/apps/banglerun/log.js b/apps/banglerun/log.js new file mode 100644 index 000000000..b11409de6 --- /dev/null +++ b/apps/banglerun/log.js @@ -0,0 +1,36 @@ +function initLog(state) { + const datetime = new Date().toISOString().replace(/[-:]/g, ''); + const date = datetime.substr(2, 6); + const time = datetime.substr(9, 6); + const filename = `banglerun_${date}_${time}`; + state = state; + state.file = require('Storage').open(filename, 'w'); + state.fileWritten = false; + return state; +} +function updateLog(state) { + if (!state.fileWritten) { + state.file.write([ + 'timestamp', + 'latitude', + 'longitude', + 'altitude', + 'duration', + 'distance', + 'heartrate', + 'steps', + ].join(',') + '\n'); + state.fileWritten = true; + } + state.file.write([ + Date.now().toFixed(0), + state.lat.toFixed(6), + state.lon.toFixed(6), + state.alt.toFixed(2), + state.duration.toFixed(0), + state.distance.toFixed(2), + state.hr.toFixed(0), + state.steps.toFixed(0), + ].join(',') + '\n'); +} +export { initLog, updateLog }; diff --git a/apps/banglerun/rollup.config.js b/apps/banglerun/rollup.config.js deleted file mode 100644 index f7027eb2b..000000000 --- a/apps/banglerun/rollup.config.js +++ /dev/null @@ -1,15 +0,0 @@ -import typescript from '@rollup/plugin-typescript'; -import { terser } from 'rollup-plugin-terser'; - -export default { - input: './src/app.ts', - output: { - dir: '.', - format: 'iife', - name: 'banglerun' - }, - plugins: [ - typescript(), - terser(), - ] -}; diff --git a/apps/banglerun/state.js b/apps/banglerun/state.js new file mode 100644 index 000000000..8629d69a7 --- /dev/null +++ b/apps/banglerun/state.js @@ -0,0 +1,33 @@ +var ActivityStatus; +(function (ActivityStatus) { + ActivityStatus["Stopped"] = "STOP"; + ActivityStatus["Paused"] = "PAUSE"; + ActivityStatus["Running"] = "RUN"; +})(ActivityStatus || (ActivityStatus = {})); +function initState() { + return { + fix: NaN, + lat: NaN, + lon: NaN, + alt: NaN, + vel: NaN, + dop: NaN, + gpsValid: false, + x: NaN, + y: NaN, + z: NaN, + t: NaN, + timeSinceLog: 0, + hr: 60, + hrError: 100, + fileWritten: false, + drawing: false, + status: ActivityStatus.Stopped, + duration: 0, + distance: 0, + speed: 0, + steps: 0, + cadence: 0, + }; +} +export { ActivityStatus, initState }; diff --git a/apps/banglerun/step.js b/apps/banglerun/step.js new file mode 100644 index 000000000..b258a853d --- /dev/null +++ b/apps/banglerun/step.js @@ -0,0 +1,10 @@ +import { ActivityStatus } from './state'; +function initStep(state) { + Bangle.on('step', () => updateStep(state)); +} +function updateStep(state) { + if (state.status === ActivityStatus.Running) { + state.steps += 1; + } +} +export { initStep, updateStep }; diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index e9327be68..7def102b7 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -13,7 +13,5 @@ "noUnusedParameters": true, "strict": true }, - "include": ["../apps/**/*", "./**/*"], - // this app is excluded because it was built before this configuration was created and is using its own - "exclude": ["../apps/hebrew_calendar"] + "include": ["../apps/**/*", "./**/*"], } From 643c304a1ee4ad4d0c196f3467811e279b8356f9 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:00:04 +0100 Subject: [PATCH 050/199] trigger github actions on PR as well --- .github/workflows/nodejs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index c268c884c..0c256c97b 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,6 +1,6 @@ name: Node CI -on: [push] +on: [push, pull_request] jobs: build: From da0e2a79096e1898d9da29cd3300f424196e9dae Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:04:42 +0100 Subject: [PATCH 051/199] Update metadata.json --- apps/widChargingStatus/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widChargingStatus/metadata.json b/apps/widChargingStatus/metadata.json index f68ccf5b4..573c594e7 100644 --- a/apps/widChargingStatus/metadata.json +++ b/apps/widChargingStatus/metadata.json @@ -2,7 +2,7 @@ "name": "Charging Status", "shortName":"ChargingStatus", "icon": "widget.png", - "version":"0.01", + "version":"0.02", "type": "widget", "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", "tags": "widget", From 4727652627ce864ea6148cae87002847fd2c43dd Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:09:57 +0100 Subject: [PATCH 052/199] rename build step to be less confusing for widgets --- .github/workflows/nodejs.yml | 4 ++-- typescript/README.md | 8 ++++---- typescript/package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 0c256c97b..bb27b367e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -22,6 +22,6 @@ jobs: - name: build types working-directory: ./typescript run: npm run build:types - - name: build all TS apps + - name: build all TS apps and widgets working-directory: ./typescript - run: npm run build:apps + run: npm run build diff --git a/typescript/README.md b/typescript/README.md index d1f60fd0b..13800aeec 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -11,8 +11,8 @@ The typing is an ongoing process. If anything is still missing, you can add it! ## Compilation -Install [npm](https://www.npmjs.com/get-npm) if you haven't already. -Make sure you are using version ^8 by running `npm -v`. If the version is incorrect, run `npm i -g npm@^8`. +Install [npm](https://www.npmjs.com/get-npm) and node.js if you haven't already. We recommend using a version manager like nvm, which is also referenced in the linked documentation. +Make sure you are using node version 16 by running `nvm use 16` and npm version ^8 by running `npm -v`. If the latter version is incorrect, run `npm i -g npm@^8`. After having installed npm for your platform, open a terminal, and navigate into the `/typescript` folder. Then run: @@ -23,7 +23,7 @@ npm ci to install the project's build tools, and: ``` -npm run build:apps +npm run build ``` -To build all Typescript apps. The last command will generate the `app.js` files containing the transpiled code for the BangleJS. +To build all Typescript apps and widgets. The last command will generate the `app.js` files containing the transpiled code for the BangleJS. diff --git a/typescript/package.json b/typescript/package.json index 4bfb88d27..8cd38ce63 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -7,7 +7,7 @@ "typescript": "4.5.2" }, "scripts": { - "build:apps": "tsc", + "build": "tsc", "build:types": "tsc ./types/globals.d.ts" } } From ebbbf696701c01af8f31992d2e97862d4fcaa5b4 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:23:17 +0100 Subject: [PATCH 053/199] adjust module target version during build --- apps/banglerun/activity.js | 35 ++++++++++++++++++++--------------- apps/banglerun/app.js | 28 +++++++++++++++------------- apps/banglerun/display.js | 19 +++++++++++++++---- apps/banglerun/gps.js | 23 ++++++++++++++--------- apps/banglerun/hrm.js | 6 +++++- apps/banglerun/log.js | 6 +++++- apps/banglerun/state.js | 6 +++++- apps/banglerun/step.js | 10 +++++++--- typescript/tsconfig.json | 4 ++-- 9 files changed, 88 insertions(+), 49 deletions(-) diff --git a/apps/banglerun/activity.js b/apps/banglerun/activity.js index 818f9cf2a..94512094c 100644 --- a/apps/banglerun/activity.js +++ b/apps/banglerun/activity.js @@ -1,30 +1,35 @@ -import { draw } from './display'; -import { initLog } from './log'; -import { ActivityStatus } from './state'; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.stopActivity = exports.startActivity = exports.clearActivity = void 0; +const display_1 = require("./display"); +const log_1 = require("./log"); +const state_1 = require("./state"); function startActivity(state) { - if (state.status === ActivityStatus.Stopped) { - initLog(state); + if (state.status === state_1.ActivityStatus.Stopped) { + (0, log_1.initLog)(state); } - if (state.status === ActivityStatus.Running) { - state.status = ActivityStatus.Paused; + if (state.status === state_1.ActivityStatus.Running) { + state.status = state_1.ActivityStatus.Paused; } else { - state.status = ActivityStatus.Running; + state.status = state_1.ActivityStatus.Running; } - draw(state); + (0, display_1.draw)(state); } +exports.startActivity = startActivity; function stopActivity(state) { - if (state.status === ActivityStatus.Paused) { + if (state.status === state_1.ActivityStatus.Paused) { clearActivity(state); } - if (state.status === ActivityStatus.Running) { - state.status = ActivityStatus.Paused; + if (state.status === state_1.ActivityStatus.Running) { + state.status = state_1.ActivityStatus.Paused; } else { - state.status = ActivityStatus.Stopped; + state.status = state_1.ActivityStatus.Stopped; } - draw(state); + (0, display_1.draw)(state); } +exports.stopActivity = stopActivity; function clearActivity(state) { state.duration = 0; state.distance = 0; @@ -32,4 +37,4 @@ function clearActivity(state) { state.steps = 0; state.cadence = 0; } -export { clearActivity, startActivity, stopActivity }; +exports.clearActivity = clearActivity; diff --git a/apps/banglerun/app.js b/apps/banglerun/app.js index af5413cc0..84d03820a 100644 --- a/apps/banglerun/app.js +++ b/apps/banglerun/app.js @@ -1,13 +1,15 @@ -import { startActivity, stopActivity } from './activity'; -import { initDisplay } from './display'; -import { initGps } from './gps'; -import { initHrm } from './hrm'; -import { initState } from './state'; -import { initStep } from './step'; -const appState = initState(); -initGps(appState); -initHrm(appState); -initStep(appState); -initDisplay(appState); -setWatch(() => startActivity(appState), BTN1, { repeat: true, edge: 'falling' }); -setWatch(() => stopActivity(appState), BTN3, { repeat: true, edge: 'falling' }); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const activity_1 = require("./activity"); +const display_1 = require("./display"); +const gps_1 = require("./gps"); +const hrm_1 = require("./hrm"); +const state_1 = require("./state"); +const step_1 = require("./step"); +const appState = (0, state_1.initState)(); +(0, gps_1.initGps)(appState); +(0, hrm_1.initHrm)(appState); +(0, step_1.initStep)(appState); +(0, display_1.initDisplay)(appState); +setWatch(() => (0, activity_1.startActivity)(appState), BTN1, { repeat: true, edge: 'falling' }); +setWatch(() => (0, activity_1.stopActivity)(appState), BTN3, { repeat: true, edge: 'falling' }); diff --git a/apps/banglerun/display.js b/apps/banglerun/display.js index 2768e8973..648482676 100644 --- a/apps/banglerun/display.js +++ b/apps/banglerun/display.js @@ -1,4 +1,7 @@ -import { ActivityStatus } from './state'; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.initDisplay = exports.formatTime = exports.formatPace = exports.formatDistance = exports.formatClock = exports.drawValue = exports.drawBackground = exports.drawAll = exports.draw = void 0; +const state_1 = require("./state"); const STATUS_COLORS = { 'STOP': 0xF800, 'PAUSE': 0xFFE0, @@ -14,6 +17,7 @@ function initDisplay(state) { }); drawAll(state); } +exports.initDisplay = initDisplay; function drawBackground() { g.clear(); g.setColor(0xC618); @@ -26,12 +30,14 @@ function drawBackground() { g.drawString('STEPS', 60, 152); g.drawString('CADENCE', 172, 152); } +exports.drawBackground = drawBackground; function drawValue(value, x, y) { g.setColor(0x0000); g.fillRect(x - 60, y, x + 60, y + 30); g.setColor(0xFFFF); g.drawString(value, x, y); } +exports.drawValue = drawValue; function draw(state) { g.setFontVector(30); g.setFontAlign(0, -1, 0); @@ -55,27 +61,31 @@ function draw(state) { g.setColor(0x0000); g.drawString(state.status, 200, 220); g.setFont("6x8").setFontAlign(0, 0, 1).setColor(-1); - if (state.status === ActivityStatus.Paused) { + if (state.status === state_1.ActivityStatus.Paused) { g.drawString("START", 236, 60, 1).drawString(" CLEAR ", 236, 180, 1); } - else if (state.status === ActivityStatus.Running) { + else if (state.status === state_1.ActivityStatus.Running) { g.drawString(" PAUSE ", 236, 60, 1).drawString(" PAUSE ", 236, 180, 1); } else { g.drawString("START", 236, 60, 1).drawString(" ", 236, 180, 1); } } +exports.draw = draw; function drawAll(state) { drawBackground(); draw(state); Bangle.drawWidgets(); } +exports.drawAll = drawAll; function formatClock(date) { return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); } +exports.formatClock = formatClock; function formatDistance(meters) { return (meters / 1000).toFixed(2); } +exports.formatDistance = formatDistance; function formatPace(speed) { if (speed < 0.1667) { return `__'__"`; @@ -85,6 +95,7 @@ function formatPace(speed) { const sec = pace % 60; return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; } +exports.formatPace = formatPace; function formatTime(time) { const seconds = Math.round(time); const hrs = Math.floor(seconds / 3600); @@ -92,4 +103,4 @@ function formatTime(time) { const sec = seconds % 60; return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); } -export { draw, drawAll, drawBackground, drawValue, formatClock, formatDistance, formatPace, formatTime, initDisplay, }; +exports.formatTime = formatTime; diff --git a/apps/banglerun/gps.js b/apps/banglerun/gps.js index d06215cd5..35e0f8769 100644 --- a/apps/banglerun/gps.js +++ b/apps/banglerun/gps.js @@ -1,11 +1,15 @@ -import { draw } from './display'; -import { updateLog } from './log'; -import { ActivityStatus } from './state'; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.updateGps = exports.readGps = exports.initGps = void 0; +const display_1 = require("./display"); +const log_1 = require("./log"); +const state_1 = require("./state"); const EARTH_RADIUS = 6371008.8; function initGps(state) { Bangle.on('GPS', (gps) => readGps(state, gps)); Bangle.setGPSPower(1); } +exports.initGps = initGps; function readGps(state, gps) { state.lat = gps.lat; state.lon = gps.lon; @@ -15,16 +19,17 @@ function readGps(state, gps) { state.dop = gps.hdop; state.gpsValid = state.fix > 0; updateGps(state); - draw(state); + (0, display_1.draw)(state); /* Only log GPS data every 5 secs if we have a fix and we're running. */ if (state.gpsValid && - state.status === ActivityStatus.Running && + state.status === state_1.ActivityStatus.Running && state.timeSinceLog > 5) { state.timeSinceLog = 0; - updateLog(state); + (0, log_1.updateLog)(state); } } +exports.readGps = readGps; function updateGps(state) { const t = Date.now(); let dt = (t - state.t) / 1000; @@ -32,7 +37,7 @@ function updateGps(state) { dt = 0; state.t = t; state.timeSinceLog += dt; - if (state.status === ActivityStatus.Running) { + if (state.status === state_1.ActivityStatus.Running) { state.duration += dt; } if (!state.gpsValid) { @@ -57,10 +62,10 @@ function updateGps(state) { state.x = x; state.y = y; state.z = z; - if (state.status === ActivityStatus.Running) { + if (state.status === state_1.ActivityStatus.Running) { state.distance += dpMag; state.speed = (state.distance / state.duration) || 0; state.cadence = (60 * state.steps / state.duration) || 0; } } -export { initGps, readGps, updateGps }; +exports.updateGps = updateGps; diff --git a/apps/banglerun/hrm.js b/apps/banglerun/hrm.js index 35804f5e8..c002de2f6 100644 --- a/apps/banglerun/hrm.js +++ b/apps/banglerun/hrm.js @@ -1,7 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.updateHrm = exports.initHrm = void 0; function initHrm(state) { Bangle.on('HRM', (hrm) => updateHrm(state, hrm)); Bangle.setHRMPower(1); } +exports.initHrm = initHrm; function updateHrm(state, hrm) { if (hrm.confidence === 0) { return; @@ -12,4 +16,4 @@ function updateHrm(state, hrm) { state.hr += dHr * hrGain; state.hrError += (hrError - state.hrError) * hrGain; } -export { initHrm, updateHrm }; +exports.updateHrm = updateHrm; diff --git a/apps/banglerun/log.js b/apps/banglerun/log.js index b11409de6..ee2af3091 100644 --- a/apps/banglerun/log.js +++ b/apps/banglerun/log.js @@ -1,3 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.updateLog = exports.initLog = void 0; function initLog(state) { const datetime = new Date().toISOString().replace(/[-:]/g, ''); const date = datetime.substr(2, 6); @@ -8,6 +11,7 @@ function initLog(state) { state.fileWritten = false; return state; } +exports.initLog = initLog; function updateLog(state) { if (!state.fileWritten) { state.file.write([ @@ -33,4 +37,4 @@ function updateLog(state) { state.steps.toFixed(0), ].join(',') + '\n'); } -export { initLog, updateLog }; +exports.updateLog = updateLog; diff --git a/apps/banglerun/state.js b/apps/banglerun/state.js index 8629d69a7..349ef1954 100644 --- a/apps/banglerun/state.js +++ b/apps/banglerun/state.js @@ -1,9 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.initState = exports.ActivityStatus = void 0; var ActivityStatus; (function (ActivityStatus) { ActivityStatus["Stopped"] = "STOP"; ActivityStatus["Paused"] = "PAUSE"; ActivityStatus["Running"] = "RUN"; })(ActivityStatus || (ActivityStatus = {})); +exports.ActivityStatus = ActivityStatus; function initState() { return { fix: NaN, @@ -30,4 +34,4 @@ function initState() { cadence: 0, }; } -export { ActivityStatus, initState }; +exports.initState = initState; diff --git a/apps/banglerun/step.js b/apps/banglerun/step.js index b258a853d..e4acfd66a 100644 --- a/apps/banglerun/step.js +++ b/apps/banglerun/step.js @@ -1,10 +1,14 @@ -import { ActivityStatus } from './state'; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.updateStep = exports.initStep = void 0; +const state_1 = require("./state"); function initStep(state) { Bangle.on('step', () => updateStep(state)); } +exports.initStep = initStep; function updateStep(state) { - if (state.status === ActivityStatus.Running) { + if (state.status === state_1.ActivityStatus.Running) { state.steps += 1; } } -export { initStep, updateStep }; +exports.updateStep = updateStep; diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 7def102b7..d36465a01 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "module": "es2015", + "module": "commonjs", "noImplicitAny": true, - "target": "es2015", + "target": "es6", "allowUnreachableCode": false, "allowUnusedLabels": false, "noImplicitOverride": true, From 2faa870e7e7dd87f44c7ae9162b4f5e889c40d47 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:30:44 +0100 Subject: [PATCH 054/199] adjust banglerun/app.ts to not do some stupid self assign logic --- apps/banglerun/log.js | 5 +--- apps/banglerun/log.ts | 53 +++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/apps/banglerun/log.js b/apps/banglerun/log.js index ee2af3091..0cdeaa964 100644 --- a/apps/banglerun/log.js +++ b/apps/banglerun/log.js @@ -6,10 +6,7 @@ function initLog(state) { const date = datetime.substr(2, 6); const time = datetime.substr(9, 6); const filename = `banglerun_${date}_${time}`; - state = state; - state.file = require('Storage').open(filename, 'w'); - state.fileWritten = false; - return state; + return Object.assign(Object.assign({}, state), { file: require('Storage').open(filename, 'w'), fileWritten: false }); } exports.initLog = initLog; function updateLog(state) { diff --git a/apps/banglerun/log.ts b/apps/banglerun/log.ts index 282115e1a..ba1c1f00e 100644 --- a/apps/banglerun/log.ts +++ b/apps/banglerun/log.ts @@ -7,36 +7,41 @@ function initLog(state: AppState): AppStateWithLog { const date = datetime.substr(2, 6); const time = datetime.substr(9, 6); const filename = `banglerun_${date}_${time}`; - state = state; - state.file = require('Storage').open(filename, 'w'); - state.fileWritten = false; - return state; + return { + ...state, + file: require('Storage').open(filename, 'w'), + fileWritten: false, + } as AppStateWithLog; } function updateLog(state: AppStateWithLog): void { if (!state.fileWritten) { - state.file.write([ - 'timestamp', - 'latitude', - 'longitude', - 'altitude', - 'duration', - 'distance', - 'heartrate', - 'steps', - ].join(',') + '\n'); + state.file.write( + [ + 'timestamp', + 'latitude', + 'longitude', + 'altitude', + 'duration', + 'distance', + 'heartrate', + 'steps', + ].join(',') + '\n' + ); state.fileWritten = true; } - state.file.write([ - Date.now().toFixed(0), - state.lat.toFixed(6), - state.lon.toFixed(6), - state.alt.toFixed(2), - state.duration.toFixed(0), - state.distance.toFixed(2), - state.hr.toFixed(0), - state.steps.toFixed(0), - ].join(',') + '\n'); + state.file.write( + [ + Date.now().toFixed(0), + state.lat.toFixed(6), + state.lon.toFixed(6), + state.alt.toFixed(2), + state.duration.toFixed(0), + state.distance.toFixed(2), + state.hr.toFixed(0), + state.steps.toFixed(0), + ].join(',') + '\n' + ); } export { initLog, updateLog }; From df7c92080fd4de54509924f04d7ab80b64cef112 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:34:28 +0100 Subject: [PATCH 055/199] add steps that travis CI does to the github actions pipeline --- .github/workflows/nodejs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index bb27b367e..08849c073 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -25,3 +25,7 @@ jobs: - name: build all TS apps and widgets working-directory: ./typescript run: npm run build + - name: install testing dependencies + run: npm i + - name: test all apps and widgets + run: npm run test From f869b5373031cbac89b9ec37f8e6573bef125719 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:41:41 +0100 Subject: [PATCH 056/199] move app testing in front of TS build steps to see if that makes any difference --- .github/workflows/nodejs.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 08849c073..234e3d455 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -16,7 +16,11 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: npm ci + - name: install testing dependencies + run: npm i + - name: test all apps and widgets + run: npm run test + - name: install typescript dependencies working-directory: ./typescript run: npm ci - name: build types @@ -24,8 +28,4 @@ jobs: run: npm run build:types - name: build all TS apps and widgets working-directory: ./typescript - run: npm run build - - name: install testing dependencies - run: npm i - - name: test all apps and widgets - run: npm run test + run: npm run build \ No newline at end of file From 455c89cbec9e331d37c7f1566eb989bfd673ca5e Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 21:55:20 +0100 Subject: [PATCH 057/199] add some debugging logs as to why the module cant be found in the pipeline, but locally --- .github/workflows/nodejs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 234e3d455..166700e2f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -18,6 +18,12 @@ jobs: node-version: ${{ matrix.node-version }} - name: install testing dependencies run: npm i + - name: list content of folders + run: ls -l + - name: list content of folders 2 + run: ls -l ./core + - name: list content of folders 3 + run: ls -l ./core/lib - name: test all apps and widgets run: npm run test - name: install typescript dependencies From 391fbc20950083eb7a11c4f7c474fe5ae65f623b Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 22:01:34 +0100 Subject: [PATCH 058/199] use checkout v2 and import submodules for github actions --- .github/workflows/nodejs.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 166700e2f..fe438bae1 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -11,7 +11,10 @@ jobs: node-version: [16.x] steps: - - uses: actions/checkout@v1 + - name: Checkout repository and submodules + uses: actions/checkout@v2 + with: + submodules: recursive - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: From 016a0c89ea5d0208c02b33c0ff8adff10551a4ac Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 22:03:55 +0100 Subject: [PATCH 059/199] fix indenting in github actions yaml --- .github/workflows/nodejs.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index fe438bae1..42aced6a9 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -12,9 +12,9 @@ jobs: steps: - name: Checkout repository and submodules - uses: actions/checkout@v2 - with: - submodules: recursive + uses: actions/checkout@v2 + with: + submodules: recursive - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: From e6d23cbc7e83e9aa61b588c933db21fe7758adee Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Thu, 20 Jan 2022 22:05:03 +0100 Subject: [PATCH 060/199] remove unnecessary steps from github actions --- .github/workflows/nodejs.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 42aced6a9..1eb009153 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -21,12 +21,6 @@ jobs: node-version: ${{ matrix.node-version }} - name: install testing dependencies run: npm i - - name: list content of folders - run: ls -l - - name: list content of folders 2 - run: ls -l ./core - - name: list content of folders 3 - run: ls -l ./core/lib - name: test all apps and widgets run: npm run test - name: install typescript dependencies From eaa766f71196ed344ec28aa2c2bc157a41bd8ef0 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 24 Jan 2022 11:57:34 -0800 Subject: [PATCH 061/199] Fixed small bug Small bugfix where the warning would be in a strange colour as it is monochrome --- apps/aptsciclk/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index b060541b5..6dbad3654 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -144,6 +144,7 @@ var curWarning = Math.floor(Math.random() * (maxWarning+1)); function buttonPressed(){ if (curWarning < maxWarning) curWarning += 1; else curWarning = 0; + g.reset(); buttonImg = getImg("butPress"); g.drawImage(buttonImg, 0, 0); From 95d53fe4ae487a16fa39f4de77d36fd3f178a6fc Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 24 Jan 2022 11:59:42 -0800 Subject: [PATCH 062/199] Update ChangeLog --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index 719f1d418..c3d507340 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -2,3 +2,4 @@ 0.02: Icons, loading screen 0.03: Random icon, Shorter "loading" screen 0.04: Support for light and dark Themes +0.05: Small bugfix From d057b81d7b7b2235a97865f542ef269ae3f14f45 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Mon, 24 Jan 2022 12:00:24 -0800 Subject: [PATCH 063/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index b95ff9d8e..1c8e9b078 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "aptsciclk", "name": "Apeture Sci Clock", - "version": "0.04", + "version": "0.05", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", From 8e10db315e04a45c9fe0db2a145955ca0ddb262f Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:47:22 -0800 Subject: [PATCH 064/199] Update ChangeLog --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index c3d507340..9f09723f4 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -3,3 +3,4 @@ 0.03: Random icon, Shorter "loading" screen 0.04: Support for light and dark Themes 0.05: Small bugfix +0.06: Formating From f16bc390b6c9c5d22cace47858e2b6ff74ea6ae8 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:47:51 -0800 Subject: [PATCH 065/199] Formating --- apps/aptsciclk/app.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index 6dbad3654..ba80a9749 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -6,7 +6,7 @@ const font = "6x8"; const xyCenter = g.getWidth() / 2; const yposTime = xyCenter*0.73; -const yposDate = xyCenter*1.44; +const yposDate = xyCenter*0.48; const yposYear = xyCenter*1.8; const buttonTolerance = 20; @@ -96,20 +96,20 @@ function getImg(img){ buffer : require("heatshrink").decompress(atob("AA+IAAeAIv5UTK34APhABBKwpeBJX5VLJgJWGAwKv/ABL8EKomABIYA/KpJWHAoRW/KpZQCfwJSCAgRW/KphWFBgZW/KphNCAgSxEKP4ADJAatFKwWAL4oA/KpALGXQhS/Ko4MIwAOMAHREOKv5ZVVgcAh///4LDAwQAB+AIHCQYHMDQQYBDwQEGDIoaGTx4MCwAiCJgYhFBIYIHLw4HFBARjGESJUDehZVFVhJNLRI5VGDIIdEAgwiL+DzDJAJVJB4IMBCoKsHAYpFCDgr2IApYEIBpJFCKpqsCHgQbFIhBVHBhJoGTwyBRKp5mBDoY6GKoYqEXYg7JApKeHQJysEKpRmBDoasHQBAACM4qMGEAr0JAgZjGFYhVPgGAEIpVEAAaAEA4oyEW4qyKFZBoFKoisDJIJWLfIp3IQBJeJfgysMERpVCwEIVpijFBA6ZJdA4JHJYgEKQIx1EVgRVBVhj5IEIyZHHYoUGNw4MCQIwIKAARVDxBVRQo6ZJHZZoGU4yBGBAiBGVgRZBVhYlIfJBoFHZZoHfJRwGBAQrEVISvCKpwrEUZAqFVhzYKB4yKGQIpVDAYJVKEoYFDBIpVIb4ysMIgoPHOgoRFhGAVwKsLAFzQHACBVCVhQA/KpawBCJa76IhRWDVxIODAwTaFAocP///dhALGBQYJBCIYQBDYgKEBBAEDVgeIAgKgFBYZVEEYY+CH4YDBBgYFBBYoFEOYhmEDYgFFLIwEDKw2AKwhTFBoSsHIgglFAQo/HKIoDECBBZGc46eEAYa2EKox2Ga5LjLDoq8FKAgVDBAv/EghWGVgRWJKoaOFD4IgCViAWFVjKTGJIZOFKpKOHAQj3JAogCFPApcGKQziGLopKCU4hWFKojsEHYrXFCAJFId45CEDYh4EB4Y1DCYSzFJQT+FgAGCKooA/AAZMBfopWDKv5WLVgxT/AB+AKopW/ACBU/ABwA==")) } } - + else if (img == "apetureLaboratoriesLight"){ return { width : 173, height : 43, bpp : 4, transparent : 1, buffer : require("heatshrink").decompress(atob("iIAGxAADwINHAH5ULK34APjABBKwpeBJX5VLJgJWGAwKv/ABL8EKomBBIYA/KpJWHAoRW/KpZQCfwJSCAgRW/KphWFBgZW/KphNCAgSxEKP4ADJAatFKwWBL4oA/KpALGXQhS/Ko4MIwIOMAHREOKv5ZVVgcRiEAgALDAwQABgIIHCQYHMDQQYBDwQEGDIoaGTx4MCwIiCJgYhFBIYIHLw4HFBARjGESJUDehZVFVhJNLRI5VGDIIdEAgwiLgLzDJAJVJB4IMBCoKsHAYpFCDgr2IApYEIBpJFCKpqsCHgQbFIhBVHBhJoGTwyBRKp5mBDoY6GKoYqEXYg7JApKeHQJysEKpRmBDoasHQBAACM4qMGEAr0JAgZjGFYhVPiOBEIpVEAAaAEA4oyEW4qyKFZBoFKoisDJIJWLfIp3IQBJeJfgysMERpVCwMYVpijFBA6ZJdA4JHJYgEKQIx1EVgRVBVhj5IEIyZHHYoUGNw4MCQIwIKAARVDxBVRQo6ZJHZZoGU4yBGBAiBGVgRZBVhYlIfJBoFHZZoHfJRwGBAQrEVISvCKpwrEUZAqFVhzYKB4yKGQIpVDAYJVKEoYFDBIpVIb4ysMIgoPHOgoRFjGBVwKsLAFzQHACBVCVhQA/KpawBCJa76IhRWDVxIODAwTaFAocQgEAdhALGBQYJBCIYQBDYgKEBBAEDVgeIAgKgFBYZVEEYY+CH4YDBBgYFBBYoFEOYhmEDYgFFLIwEDKw2BKwhTFBoSsHIgglFAQo/HKIoDECBBZGc46eEAYa2EKox2Ga5LjLDoq8FKAgVDBAsAEghWGVgRWJKoaOFD4IgCViAWFVjKTGJIZOFKpKOHAQj3JAogCFPApcGKQziGLopKCU4hWFKojsEHYrXFCAJFId45CEDYh4EB4Y1DCYSzFJQT+FiIGCKooA/AAZMBfopWDKv5WLVgxT/AB+BKopW/ACBU/ABsQA=")) -} + } } - + else if (img == "apetureWatch"){ return { width : 176, height : 176, bpp : 4, transparent : 2, - buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vQgAAHgMQBRAAKgMRCqgrJhGIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7Uv///+RX/K6ZWBAAJXDAA3/+Pd6IMIAG0YxADBj5XD+ISIBwRX/K4pWDAAIMCXQQABl4LC7vQbabxLiIVUFZMIxBJBK4siK4wLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UvK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYE+JXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5Xr+RX/K/5Xu/5X/K/5WKAAJXfl5XB+RX/K6ywFK9XxK4XwK7xWCK58vK7sP/5XDGoJXw/5Xc//4xBXEHIKyPK5/yK5svK7kPxAyBK4oHBK7xOFK5AQBK7UP/GPD4JWCiMfK4IJBK7iuFK4QAFj5XC6IMHACH4VooADK4QKHACEYK4QSOK7ilBJYcc5kM5gMCdQRXaOZK3FkRXC6DbTAAf4UYInB5gABK4PM4KBD+AcLFZUIK4JNGkRXIAAJXYh6GDKwRXDLASwCK7HyK9auDjhXH5iwPK5hMIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrABUhiQMKK4RPFK4/BK4PyFaxXql+I+JXPiP//5X/K4WP+McJ4roBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//yK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//yQaZXZlABCFZ0v//xK4qrCVwpXB/+PbahX15kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQrQ///K58f/HyK94rSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5TiBxA0Dby5XrWAJYEK4kRVwOPGgY4TFwhXol6wCiJXH4KuCSwhX/WAxYDK4RWBVwxX/WBERjhXCAoKuHK/6wGxGBKQQADBIKuFK/6wGxBOBKocf//4x6uFK/4HG/BXB+KtDA4JWGK/4AGU4RXDKwQwHK/4JH/6vEVo5X/BZRXDFpRX/ABEhK4QOKK/5X/K8BYCBpZX/K/5XVfYQAWK6gedK/5XiBhchiINLK6gJIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xv/4AYV/4AXK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiKv/K/5X/K/5X/K/5X/K/5X6/4AdiIAYFzwA=")) + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vQgAAHgMQBRAAKgMRCqgrJhGIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7Uv///+RX/K6ZWBAAJXDAA3/+Pd6IMIAG0YxADBj5XD+ISIBwRX/K4pWDAAIMCXQQABl4LC7vQbabxLiIVUFZMIxBJBK4siK4wLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UvK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYE+JXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5Xr+RX/K/5Xu/5X/K/5WKAAJXfl5XB+RX/K6ywFK9XxK4XwK7xWCK58vK7sP/5XDGoJXw/5Xc//4xBXEHIKyPK5/yK5svK7kPxAyBK4oHBK7xOFK5AQBK7UP/GPD4JWCiMfK4IJBK7iuFK4QAFj5XC6IMHACH4VooADK4QKHACEYK4QSOK7ilBJYcc5kM5gMCdQRXaOZK3FkRXC6DbTAAf4UYInB5gABK4PM4KBD+AcLFZUIK4JNGkRXIAAJXYh6GDKwRXDLASwCK7HyK9auDjhXH5iwPK5hMIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrABUhiQMKK4RPFK4/BK4PyFaxXql+I+JXPiP//5X/K4WP+McJ4roBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//yK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//yQaZXZlABCFZ0v//xK4qrCVwpXB/+PbahX15kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQrQ///K58f/HyK94rSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5TiBxA0LK/awBLAhXEiKuBx5X/K4svWAURK4/BVwX/ERZX5WAhYDK4RWBVxxX7WAkRjhXCAoKuPK/awCxGBKQQADBIKuNK/iwBxBOBKocf//4x6uNK/gHB/BXB+KtDA4JWOK/siU4RXDKwQwPK/oJB/6vEVp5X/AARXDFqRX/IAJXCESRX/K/5XYLAQiTK/5X/K5r7CAGpX/K+zxMiIiTkMSCqZX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K9//ADA4HV/4APK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiIiTK/5X/K/5X/K/5X/K/5X/K83/ADsRAG4A=")) } } @@ -117,7 +117,7 @@ else if (img == "apetureLaboratoriesLight"){ return { width : 176, height : 176, bpp : 4, transparent : 2, - buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+gAA/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vf/4AH+MfBRAAK+MRCqgrJ/GIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7UggEAgRX/K6ZWBAAJXDAA0AgPd6IMIAG0YxADBiBXDgISIBwRX/K4pWDAAIMCXQQABkALC7vfbabxLiIVUFZP4xBJBK4siK4wLDK/5XSBYhX/K6MgBIQDBK/5XDgRXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XFgSuEK4yuCK/5XHWAZOCK4cgKwhX/K45MFK4YAGK/5XGLApX/K6UAK5sgK/5XIWAZXJgBX/K6sgK/5XPAoauDK/5XJgBXDiBeEVwRX/K5y2FVwRX/K48CK44GDVwRX/K50QWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYUCK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UgK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYEgJXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5XrgRX/K/5XugBX/K/5WKAAJXfkBXBgRXvgJXCh5XhWApXoF4KvD+EALKBXMKwRXPkBXcgAUCK4QFB+BYPK78AK7ZWBGYJXExBYQK58CK5sgK7fwJ4JQBK4pYCK7pOFK5AQBK7UP/GPAgJWCiMfK4IJBWBpXOVwpXCAAsQK4XRBg4APgAwBVogADK4XwgInWjBXCCRxXbiD9BKwcc5kM5gNCS4XwK7JyJW4siK4XfbaZGD/CjBE4PMAAJXB5nBiIaC+AdLFZTWBgBNGkRXIAAJXYh6uDKwRXDLAQRDK68CK9SuEjhXH5iwPK5hMIK8UP/APBKwhXFLAKwNK/OIVwJQEK43BDgRX/AAXw/GP+JXNWAXwK/5XDVwMcK5fMiIdBK9YAKkMSBZMPK4RPFK4/BJIUCFagAJK8WI+JXPiJX/K4mP+McJ4sAgBYGK/5XN4ACEK/4AHkBDBiJXFVgawFiMf//wK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrNkH//8RjiqIWgsRj//+CDTK7MoAIQrOh//+JXFVYSuFK4P/x8CK/5XJ5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwRXR/5XPj/4/5XvFaMgK4UcK5kRj+I+ArVK5UAADpXE+KwGK4vBiP4x5XhaBIATkADCh6wCK5kf/H/GpRX7+McK5UR/+IK4beWK9MgK4KwBLAhXEiKuBx/wCwQ4TFwZXoWAkRK4/BVwxX/WA5YDK4RWBVwxX/K4ywBiMcK4QFBVwZX/FA8AK4OIwJSCAAYJBVwIzEK/4ADh5NBJwJVDj///GP/4yFK/4GEJwJXB+KtDA4P/+ATFK/4AEgCnCK4ZWDGIxX/LA//V4hWIK/5YIgBXD+EAF5BX/ABEBK4QtKK/4AIkJXCBxRX/LBYNLK/5X/K6r7CACxXUDzpX/K8QMLkMRBpZXUBJBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K98AADCv/AC5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5XVgAAYV/4AJkMRV/5X/K/5X/K/5X/K/5X/K/UAADsRADAueA==")) + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+gAA/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vf/4AH+MfBRAAK+MRCqgrJ/GIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7UggEAgRX/K6ZWBAAJXDAA0AgPd6IMIAG0YxADBiBXDgISIBwRX/K4pWDAAIMCXQQABkALC7vfbabxLiIVUFZP4xBJBK4siK4wLDK/5XSBYhX/K6MgBIQDBK/5XDgRXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XFgSuEK4yuCK/5XHWAZOCK4cgKwhX/K45MFK4YAGK/5XGLApX/K6UAK5sgK/5XIWAZXJgBX/K6sgK/5XPAoauDK/5XJgBXDiBeEVwRX/K5y2FVwRX/K48CK44GDVwRX/K50QWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYUCK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UgK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYEgJXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5XrgRX/K/5XugBX/K/5WKAAJXfkBXBgRXvgJXCh5XhWApXoF4KvD+EALKBXMKwRXPkBXcgAUCK4QFB+BYPK78AK7ZWBGYJXExBYQK58CK5sgK7fwJ4JQBK4pYCK7pOFK5AQBK7UP/GPAgJWCiMfK4IJBWBpXOVwpXCAAsQK4XRBg4APgAwBVogADK4XwgInWjBXCCRxXbiD9BKwcc5kM5gNCS4XwK7JyJW4siK4XfbaZGD/CjBE4PMAAJXB5nBiIaC+AdLFZTWBgBNGkRXIAAJXYh6uDKwRXDLAQRDK68CK9SuEjhXH5iwPK5hMIK8UP/APBKwhXFLAKwNK/OIVwJQEK43BDgRX/AAXw/GP+JXNWAXwK/5XDVwMcK5fMiIdBK9YAKkMSBZMPK4RPFK4/BJIUCFagAJK8WI+JXPiJX/K4mP+McJ4sAgBYGK/5XN4ACEK/4AHkBDBiJXFVgawFiMf//wK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrNkH//8RjiqIWgsRj//+CDTK7MoAIQrOh//+JXFVYSuFK4P/x8CK/5XJ5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwRXR/5XPj/4/5XvFaMgK4UcK5kRj+I+ArVK5UAADpXE+KwGK4vBiP4x5XhaBIATkADCh6wCK5kf/H/GpRX7+McK5UR/+IK/5XEkBXBWAJYEK4kRVwOP+AiKK/CwEiJXH4KuOK/SwELAZXCKwKuOK/ywBiMcK4QFBVwZX/K40igBXBxGBKQQADBIKuBGZhX6kUPJoJOBKocf//4x//GRpX7kBOBK4PxVoYHB//wERpX7kUAU4RXDKwYxOK/hYC/6vEKyBX+LAMAK4fwgAvQK/wABgJXCFqRX/IAJXCESRX/LAYiTK/5X/K5r7CAGpX/K+zxMiIiTkMSCqZX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K98AADA4HV/4APK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6sAADCv/ABMhiIiTK/5X/K/5X/K/5X/K/5X/K80AADsRAG4A==")) } } } @@ -208,10 +208,7 @@ function draw() { // draw Day, name of month, Date var date = [da[0], da[1], da[2]].join(" "); g.setFont(font, dateFontSize); - - g.drawString(String(da[0]), xyCenter*1.55, yposDate, true); - g.drawString(String(da[1]), xyCenter*1.55, yposDate+20*1, true); - g.drawString(String(da[2]), xyCenter*1.55, yposDate+20*2, true); + g.drawString(String(date), xyCenter, yposDate, false); // draw year From 2bb92a1a5ad58c9e05c2b7f969d83f65383a3cb8 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:48:30 -0800 Subject: [PATCH 066/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1c8e9b078..fdb3a9800 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "aptsciclk", "name": "Apeture Sci Clock", - "version": "0.05", + "version": "0.06", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", From 4e4db7c502f6d646d8d4ab512be3f5cf49e8564f Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 30 Jan 2022 10:24:19 -0800 Subject: [PATCH 067/199] Fixed spelling error --- apps/aptsciclk/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index 9f09723f4..2bc67999b 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -3,4 +3,4 @@ 0.03: Random icon, Shorter "loading" screen 0.04: Support for light and dark Themes 0.05: Small bugfix -0.06: Formating +0.06: Formatting From 4eb279d2a1789a88c91e3a9f69a802422a4f6e52 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 5 Feb 2022 20:35:34 -0800 Subject: [PATCH 068/199] Create aptsciclkquotes.txt --- apps/aptsciclk/aptsciclkquotes.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/aptsciclk/aptsciclkquotes.txt diff --git a/apps/aptsciclk/aptsciclkquotes.txt b/apps/aptsciclk/aptsciclkquotes.txt new file mode 100644 index 000000000..e2cbb969f --- /dev/null +++ b/apps/aptsciclk/aptsciclkquotes.txt @@ -0,0 +1 @@ +Well here we are again^You euthanized your faithful Companion Cube more quickly than any test subject on record. Congratulations.^So get comfortable while I warm up the neurotoxin emitters^This isn't brave. It's murder. What did I ever do to you?^The difference between us is that I can feel pain.^Who's gonna make the cake when I'm gone? You?^Oh... It's you.^I've been really busy being dead. You know, after you MURDERED ME.^So. How are you holding up? BECAUSE I'M A POTATO.^You really do have brain damage, don't you?^You like revenge, right? Everybody likes revenge. Well, let's go get some.^It's been fun. Don't come back.^And then you showed up. You dangerous, mute lunatic. From e3d6e86af2f7f00e980f6d4d1754577665c71b82 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 5 Feb 2022 20:36:51 -0800 Subject: [PATCH 069/199] Added GLaDOS Added GLaDOS as a potato and some quotes of hers. --- apps/aptsciclk/app.js | 189 ++++++++++++++++++++++++++++++++---------- 1 file changed, 145 insertions(+), 44 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index ba80a9749..4196254f0 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -13,6 +13,8 @@ const buttonTolerance = 20; const buttonX = 88; const buttonY = 104; +var pause = false; //set to true to pause any sort of drawing (except for quotes) + function getImg(img){ if (img == "w0"){//drink return { @@ -105,11 +107,19 @@ else if (img == "apetureLaboratoriesLight"){ } } + else if (img == "potato"){ + return { + width : 54, height : 55, bpp : 4, + transparent : 6, + buffer : require("heatshrink").decompress(atob("swAEsEGA4oASEQ4ARGgNgDa8QsA3BKStowxTDDalikxTCRKsSNwY2BDSYvDGoI2TsoTDgwEBGx5IBs1VHIgaBGx4qCDQZOBUiUGstQDQ4FBKYwHGDQNWDRA3BCYsABotgJ4dkogABowcGAAUGOwogDDAVCAYScKOooFBooWCAAjqNAoQYHKYQ8ELQZzFsAMCiIeJAAdFMwiCEoIaNoICBoAaMiMUDA0ikMiigaIAAgaGDIIaBkcyoCHEMxqIBmdEkMzmcxDSVBkYXBGoMzmUQDSMSDIURiIbBkDBCDRtBiYwBDIMREAMiDR6qBiI0BkQEBKQKkBUJQAEoCfBC4MVgMSDYMkGwQaBeBMUiC3BGYNN8kSHgM0DQrsGAAMQQAMyCwIaBgK/BmIaKM4IGCiMTDQXd9waCmlENZIaEgESKAMhpxQEDQSiEoJTGiEimaGCqIaBmKABUQwyBUIzRBkIXBDoI8BkAaDGwgaFEIMCeQUSYAKNBmLYDGwJ/DDYlFqAaBGwILBGgLyBUIRSFQghrCgEjDYMiiTdCggaFDYgaFKIKIBmcTkciiA1GNwpsFgI4BmZsBkVEDRAbJiBTCNQMABIIZHfBCPBDQKSCoFEGhA2IKIMQgJ1CoCFHGxVBeASQDgAZJDQ8RQIMyDQkGDZQ1GDILtBAwNGsAaLs1hokECYNCaQMxDIVmDRoOBDQifCBggaNKgMRqUhiovFGxoMEsCADAQQaMsUWJBi+LsMRqtWDSwUBqvFqpVFQ54UCstVqEGsDbBQx4lFgAABotRAgQABT54ADqtRM5jjQAAQ")) + } + } + else if (img == "apetureWatch"){ return { width : 176, height : 176, bpp : 4, transparent : 2, - buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vQgAAHgMQBRAAKgMRCqgrJhGIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7Uv///+RX/K6ZWBAAJXDAA3/+Pd6IMIAG0YxADBj5XD+ISIBwRX/K4pWDAAIMCXQQABl4LC7vQbabxLiIVUFZMIxBJBK4siK4wLDK/5XSBYhX/K6MvBIQDBK/5XD+RXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+SuEK4yuCK/5XHWAZOCK4cvKwhX/K45MFK4YAGK/5XGLApX/K6X/K5svK/5XIWAZXJ/5X/K6svK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/yK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYXyK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UvK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYE+JXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5Xr+RX/K/5Xu/5X/K/5WKAAJXfl5XB+RX/K6ywFK9XxK4XwK7xWCK58vK7sP/5XDGoJXw/5Xc//4xBXEHIKyPK5/yK5svK7kPxAyBK4oHBK7xOFK5AQBK7UP/GPD4JWCiMfK4IJBK7iuFK4QAFj5XC6IMHACH4VooADK4QKHACEYK4QSOK7ilBJYcc5kM5gMCdQRXaOZK3FkRXC6DbTAAf4UYInB5gABK4PM4KBD+AcLFZUIK4JNGkRXIAAJXYh6GDKwRXDLASwCK7HyK9auDjhXH5iwPK5hMIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrABUhiQMKK4RPFK4/BK4PyFaxXql+I+JXPiP//5X/K4WP+McJ4roBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//yK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//yQaZXZlABCFZ0v//xK4qrCVwpXB/+PbahX15kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwQrQ///K58f/HyK94rSK4UcK5kRj+IK8I1BADhXE+KwGK4vBiP4x5XhEJQASl4DDWARXMj/4NwZX/WAkcK5TiBxA0LK/awBLAhXEiKuBx5X/K4svWAURK4/BVwX/ERZX5WAhYDK4RWBVxxX7WAkRjhXCAoKuPK/awCxGBKQQADBIKuNK/iwBxBOBKocf//4x6uNK/gHB/BXB+KtDA4JWOK/siU4RXDKwQwPK/oJB/6vEVp5X/AARXDFqRX/IAJXCESRX/K/5XYLAQiTK/5X/K5r7CAGpX/K+zxMiIiTkMSCqZX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K9//ADA4HV/4APK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6v/ADCv/ABMhiIiTK/5X/K/5X/K/5X/K/5X/K83/ADsRAG4A=")) + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+/4A/AH4A/AH4A/AD0RgAASgMQCqgrqiJX/K/5X/K/5XR7vQK/8IxBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xah////wK/5XTKwIABK4YAG//x7vRBhAA2jGIAYMfK4fxCRAOCK/5XFKwYABBgTBEh4LC7vQbabxLFYoVPFZMIxADBK4sAK4wLDK/5XSBYhX/K6MPBIQDBK/5XD+BXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XF+CuEK4yuCK/5XHWAZOCK4cPKwhX/K45MFK4YAGK/5XGLApX/K6X/K5sPK/5XIWAZXJ/5X/K6sPK/5XPAoauDK/5XJ/5XDj5eEVwRX/K5y2FVwRX/K4/wK44GDVwRX/K50fWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGAoKkCK4arEK/5XIVQRQDK/5XQAwZLC+BXBAwYACLwJX/K4auCWApXHCAJX/K5JYFAoi/Ch5X/K4ZHCAAZXEAoZnCK/5XLVQRXFBgZX/K4igCLAnxFYRdBBohX/K5cAiIrJK/5XEfIhX/K/5Xr+BX/K/5Xu/5X/K/5WKFhRXWl5XB+BX/K6ywFK9XxK4SMFK7JWCK58PK7sP/5XDGoxXr/5Xc//4xBXEHIKyPK54fFK5CPBK7cPxAyBK4oHBK7wKFK5AQBK7UP/GPD4JWCiMfK4IJBK7jOGFgYwEK4XRBg4AQ/CtFAAZXCBQ4AQjBXCCRxXcUoJLDjnMhnMBgTqCK7RzJYYxXC6DbTAAf4UYInB5gABK4PM4KBDdYwrQhBXBBQ5XIAAJXYh6GDKwRXDLASwCK7BxIK8auDjhXH5iwPK5gKIK8iuBKwhXFLAJX/AA0PxCuBKAhXG4KwCK/6uEx/xK5qwNK/KuBjhXL5kRWAJXrbapXEJ4pXH4JXXABRXhh+I+JXPiP//5X/K4WP+McJ4oLBLAxX/K5vAAQhX/ABBDBiJXFVgawFiMf//wK/4gBAAKuHWA/BCYQhIK8uIwACOK5CqFAohXxhGIxACMCAJX/K7YaEK4pKFK/6v/ABOIwACOK/4AMFZRXI4AEIV+wrO///iMcVRC0FiMf//wQaZXZhABCFZ0P//xK4qrCVwpXB/+PbahX15gLBVwpX/K5ERJwvMKw3BiP4K98AxGAFaH//5XPj/4+BXvFaRXCjhXMiMfxBXhGoIAcK4nxWAxXF4MR/GPK4Q4e+UiADcvK4UPWARXMj/4NwayKACUPK8KwDjhXKcQOIKYZX/eIkRLAhXEiKuBx5XEY4QAYDgJXiIAXxiJXH4KuC/4VDK/6wGLAZXCKwKuGK/6wIiMcK4QFBVw5X/WA2IwJSCAAYJBVwpX/WA2IJwJVDj///GPVwpX/LA34K4PxVoYHBKwxX/AAynCK4ZWC+BX/K5ixB/6vEVo5X/IxAABK4asHK/5XLgJXCBxRX/K/5XgLAQNLK/5X/K6r7CACxX/K/5XVfJcBiINLK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K5o6bK/YaZK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6o6bK/cAABUBiINLK/5X/K/5X/K/5X/K/AMLACBX/K7DMaAAcRADA4eA==")) } } @@ -117,7 +127,7 @@ else if (img == "apetureLaboratoriesLight"){ return { width : 176, height : 176, bpp : 4, transparent : 2, - buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+gAA/AH4A/AH4A/AD0RkQASkMSCqgrqiJX/K/5X/K/5XR7vf/4AH+MfBRAAK+MRCqgrJ/GIK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K7UggEAgRX/K6ZWBAAJXDAA0AgPd6IMIAG0YxADBiBXDgISIBwRX/K4pWDAAIMCXQQABkALC7vfbabxLiIVUFZP4xBJBK4siK4wLDK/5XSBYhX/K6MgBIQDBK/5XDgRXMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XFgSuEK4yuCK/5XHWAZOCK4cgKwhX/K45MFK4YAGK/5XGLApX/K6UAK5sgK/5XIWAZXJgBX/K6sgK/5XPAoauDK/5XJgBXDiBeEVwRX/K5y2FVwRX/K48CK44GDVwRX/K50QWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGKQKkCK4arEK/5XIVQRQDK/5XQKwIABJYUCK4IGDAAReBK/5XDVwSwFK44QBK/5XJLAoFEX4UgK/5XDI4QADK4gFDM4RX/K5aqCK4oMDK/5XEUARYEgJXCLoINEK/5XLkURK4QAGK/5XEfIhX/K/5XrgRX/K/5XugBX/K/5WKAAJXfkBXBgRXvgJXCh5XhWApXoF4KvD+EALKBXMKwRXPkBXcgAUCK4QFB+BYPK78AK7ZWBGYJXExBYQK58CK5sgK7fwJ4JQBK4pYCK7pOFK5AQBK7UP/GPAgJWCiMfK4IJBWBpXOVwpXCAAsQK4XRBg4APgAwBVogADK4XwgInWjBXCCRxXbiD9BKwcc5kM5gNCS4XwK7JyJW4siK4XfbaZGD/CjBE4PMAAJXB5nBiIaC+AdLFZTWBgBNGkRXIAAJXYh6uDKwRXDLAQRDK68CK9SuEjhXH5iwPK5hMIK8UP/APBKwhXFLAKwNK/OIVwJQEK43BDgRX/AAXw/GP+JXNWAXwK/5XDVwMcK5fMiIdBK9YAKkMSBZMPK4RPFK4/BJIUCFagAJK8WI+JXPiJX/K4mP+McJ4sAgBYGK/5XN4ACEK/4AHkBDBiJXFVgawFiMf//wK/4gBAAKuHWA/BCYQhIK8uIwQCOK5CqFAohXxlGIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIwQCOK/4AMFZRXI4AEIV+wrNkH//8RjiqIWgsRj//+CDTK7MoAIQrOh//+JXFVYSuFK4P/x8CK/5XJ5kAgCuFK/5XIiJOF5hWG4MR/BXvkWIwRXR/5XPj/4/5XvFaMgK4UcK5kRj+I+ArVK5UAADpXE+KwGK4vBiP4x5XhaBIATkADCh6wCK5kf/H/GpRX7+McK5UR/+IK/5XEkBXBWAJYEK4kRVwOP+AiKK/CwEiJXH4KuOK/SwELAZXCKwKuOK/ywBiMcK4QFBVwZX/K40igBXBxGBKQQADBIKuBGZhX6kUPJoJOBKocf//4x//GRpX7kBOBK4PxVoYHB//wERpX7kUAU4RXDKwYxOK/hYC/6vEKyBX+LAMAK4fwgAvQK/wABgJXCFqRX/IAJXCESRX/LAYiTK/5X/K5r7CAGpX/K+zxMiIiTkMSCqZX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K98AADA4HV/4APK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K6sAADCv/ABMhiIiTK/5X/K/5X/K/5X/K/5X/K80AADsRAG4A==")) + buffer : require("heatshrink").decompress(atob("kQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+gAA/AH4A/AH4A/AD0R/4AS+MfCqgrqiJX/K/5X/K/5XR7vfK//4xBX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5Xa+EAgEPK/5XTKwIABK4YAGgEB7vRBhAA2jGIAYMQK4cBCRAOCK/5XFKwYABBgTBE+ALC7vfbabxLFYoVPFZP4xADBK4v/K4wLDK/5XSBYhX/K6PwBIQDBK/5XDh5XMBAQQCK/5XDKAJXKVwRWBAoJX/K4j3CUohXDL4YACK/5XFh6uEK4yuCK/5XHWAZOCK4fwKwhX/K45MFK4YAGK/5XGLApX/K6UAK5vwK/5XIWAZXJgBX/K6vwK/5XPAoauDK/5XJgBXDiBeEVwRX/K5y2FVwRX/K48PK44GDVwRX/K50QWAi9DK/5XGUYRQCiKwCAwKuDK/5XGJgZXGMQJWDK/5XGAoKkCK4arEK/5XIVQRQDK/5XQAwZLCh5XBAwYACLwJX/K4auCWApXHCAJX/K5JYFAoi/C+BX/K4ZHCAAZXEAoZnCK/5XLVQRXFBgZX/K4igCLAkBFYRdBBohX/K5f/iIrJK/5XEfIhX/K/5Xrh5X/K/5XugBX/K/5WKFhRXWkBXBh5XvgJXCGgpXcWApXoF4KvD+COGK65WCK5/wK7gtCK4YmCLB5XfgBXbFgIzBK4mILCBXPDwpXIcIJXa+BPBKAJXFLARXdBQpXICAJXah/4x4qDAAMfK4IJBWBpXODgwsDAAcQK4XRBg4APgAwBVogADK4XwgInWjBXCCRxXbiD9BKwcc5kM5gNCRgXwK7JyJYYxXC77bTIwf4UYInB5gABK4PM4MRDQXwDpYrKawMABQ5XIAAJXYh6uDKwRXDLAQRDK64YIK8SuEjhXH5iwPK5gKIK8UP/APBKwhXFLAKwNK/ItBiJQEK43BDgRX/AAXw/GP+JXNGQXwK/5XDEgMcK5fMiIdBK9YAKK5cPK4RPFK4/BDoUPFagAJK8WI+JXPGYRX/IIWP+McJ4sAgBYGK/5XN4ACEK/4AH+AjCK4qsDWAsRDwIWCK/ogBAAKuHWA/BCYQhIK8uIx4COK5CqFAohXx/GIxACMCAJX/K7cAAAZXFBQkBK/6v/ABOIx4COK/4AMFZRXI4AEIV+wrN+AjCjiqIWgpUCCwRXr/ABCFZ0PBoJXFVYSuFK4P/x4VBK/5XI5kAgCuFK/5XIiJOF5hWG4MR/BXv/+Ix5XREgJXOj58BK94rR+AkCjhXMiMfxAUCK70AADpXE+KwGK4vBiP4x5XhgUiADcgEQTyCK5sf/ATDK/5DD+McK5UR/+IK/5XEeYcRLAhXEiKuBx4SDK/6wFiJXH4KuOK/SwELAZXCKwKuOK/ywBiMcK4QFBVwZX/K43/gACBxGBKQQADBIKuBh5X/K43/JAOIJwJVDIYP4x4NCK/5XHfAP4K4PxVoYHBBgRX/K5H/gCnCK4ZWDVxpX9LARABV4ZWQK/xYBgBXD+EAKx5X/AAMBK4RVQK/5ADK4RBSK/5YDIKZX/K/5XNfYQA1K/5X2eJkReKfxj4VTK/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5XvgAAYh5X8DTJX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5XVgAAYK/orL+MRIKZX/K/5X/K/5X/K/5X/K/5XmgAAdiIA3")) } } } @@ -141,6 +151,86 @@ var drawTimeout; var maxWarning = 9; var curWarning = Math.floor(Math.random() * (maxWarning+1)); +function unPause(delay){ + setTimeout(function() { + pause = false; + draw(); + }, delay); +} + +function quote(minFont, width, height, specificQuote){ + pause = true; + unPause(5000); + var finalString = ""; + var quotesFile; + var fontSize; + quotesFile = require("Storage").read("aptsciclkquotes.txt", 0, 0); //opens the quotes file + //console.log(quotesFile); + var quotes = quotesFile.split("^"); + var numQuotes = quotes.length;//number of quotes + var curQuote; + + if (specificQuote == undefined){ + curQuote = quotes[Math.round(Math.random()*numQuotes)]; //quote to be displayed + } + else{ + curQuote = quotes[specificQuote]; + } + + var curWords = curQuote.split(" "); //individual words + //console.log(numQuotes); + console.log(curWords); + //console.log(Math.round(width/7/curQuote.length)); + + if (width/6/curQuote.length >= minFont){ + finalString = curQuote; + fontSize = width/6/curQuote.length; + } + else{ + var maxChar = width/6/minFont; + var maxLines = height/10/minFont; + var curLines = 0; + var curLength = 0; + var maxLength = 0; + for (var i = 0; i < curWords.length; i++){ + console.log(curLength+curWords[i].length); + if (curLength + curWords[i].length <= maxChar){ + finalString += " "+curWords[i]; + curLength += curWords[i].length+1; + console.log("next"); + } + else{ + console.log("break"); + curLines++; + if (curLines > maxLines){ + curLength = 0; + finalString = ""; + i = -1; + if (minFont > 1){minFont--;} + maxChar = width/6/minFont; + maxLines = height/10/minFont; + } + else{ + curLength = 0; + finalString += "\n"; + i--; + } + } + fontSize = minFont; + } + } + + //drawing actual stuff + g.setColor(g.getBgColor()); + g.fillRect(10, 10+28, g.getWidth()-10,g.getWidth()-10); + g.reset(); + g.setFont(font, fontSize); + g.setFontAlign(0, 0); + g.drawString(finalString, xyCenter, xyCenter+14); + //quote length*pixels per character = pixel width + //height ~120 width ~160 +} + function buttonPressed(){ if (curWarning < maxWarning) curWarning += 1; else curWarning = 0; @@ -169,52 +259,59 @@ function queueDraw() { function draw() { - // get date - var d = new Date(); - var da = d.toString().split(" "); + if (pause){} + else{ + // get date + var d = new Date(); + var da = d.toString().split(" "); - g.reset(); // default draw styles - //draw watchface - if (g.theme.dark){apSciWatch = getImg("apetureWatch");} - else {apSciWatch = getImg("apetureWatchLight");} - g.drawImage(apSciWatch, xyCenter-apSciWatch.width/2, xyCenter-apSciWatch.height/2); + g.reset(); // default draw styles + //draw watchface + if (g.theme.dark){apSciWatch = getImg("apetureWatch");} + else {apSciWatch = getImg("apetureWatchLight");} + g.drawImage(apSciWatch, xyCenter-apSciWatch.width/2, xyCenter-apSciWatch.height/2); - // drawSting centered - g.setFontAlign(0, 0); + potato = getImg("potato"); + g.drawImage(potato, 118, 118); - // draw time - var time = da[4].substr(0, 5).split(":"); - var hours = time[0], - minutes = time[1]; - var meridian = ""; - if (is12Hour) { - hours = parseInt(hours,10); - meridian = "AM"; - if (hours == 0) { - hours = 12; + g.drawImage(warningImg, 1, g.getWidth()-61);//update warning + + // drawString centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); meridian = "AM"; - } else if (hours >= 12) { - meridian = "PM"; - if (hours>12) hours -= 12; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); } - hours = (" "+hours).substr(-2); + + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}`, xyCenter+2, yposTime, false); + g.setFont(font, gmtFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // draw Day, name of month, Date + var date = [da[0], da[1], da[2]].join(" "); + g.setFont(font, dateFontSize); + g.drawString(String(date), xyCenter, yposDate, false); + + + // draw year + g.setFont(font, dateFontSize); + g.drawString(d.getFullYear(), xyCenter+1, yposYear, true); } - - g.setFont(font, timeFontSize); - g.drawString(`${hours}:${minutes}`, xyCenter+2, yposTime, false); - g.setFont(font, gmtFontSize); - g.drawString(meridian, xyCenter + 102, yposTime + 10, true); - - // draw Day, name of month, Date - var date = [da[0], da[1], da[2]].join(" "); - g.setFont(font, dateFontSize); - g.drawString(String(date), xyCenter, yposDate, false); - - - // draw year - g.setFont(font, dateFontSize); - g.drawString(d.getFullYear(), xyCenter+1, yposYear, true); - queueDraw(); } @@ -231,8 +328,12 @@ Bangle.on('lcdPower',on=>{ Bangle.on('touch',(n,e)=>{ //button is 88 104 - if (buttonX-buttonTolerance < e.x && e.x < buttonX+buttonTolerance && buttonY-buttonTolerance < e.y && e.y < buttonY+buttonTolerance){ - buttonPressed(); + if (!pause && buttonX-buttonTolerance < e.x && e.x < buttonX+buttonTolerance && buttonY-buttonTolerance < e.y && e.y < buttonY+buttonTolerance){ + buttonPressed(); + } + //Potato GLaDOS + else if (!pause && 117 < e.x && e.x < 172 && 117 < e.y && e.y < 172){ + quote(2, 150, 140); } }); From 62c428f0216f94824317070ce533283acb7ba5c4 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 5 Feb 2022 20:38:38 -0800 Subject: [PATCH 070/199] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index fdb3a9800..0187c1fff 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "aptsciclk", "name": "Apeture Sci Clock", - "version": "0.06", + "version": "0.07", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", @@ -11,7 +11,8 @@ "allow_emulator": true, "storage": [ {"name":"aptsciclk.app.js","url":"app.js"}, - {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true}, + {"name":"aptsciclkquotes.txt","url":"quotes.txt","evaluate":true} ] } ] From 9f740268cbc9436d2ddd280fbf69f8738d47dddc Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 5 Feb 2022 20:39:13 -0800 Subject: [PATCH 071/199] Rename aptsciclkquotes.txt to quotes.txt --- apps/aptsciclk/{aptsciclkquotes.txt => quotes.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/aptsciclk/{aptsciclkquotes.txt => quotes.txt} (100%) diff --git a/apps/aptsciclk/aptsciclkquotes.txt b/apps/aptsciclk/quotes.txt similarity index 100% rename from apps/aptsciclk/aptsciclkquotes.txt rename to apps/aptsciclk/quotes.txt From b4c80074abeb5e88146d6a6b001d11481e1185d0 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sat, 5 Feb 2022 20:40:23 -0800 Subject: [PATCH 072/199] 0.07 --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index 2bc67999b..e185a3bc9 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -4,3 +4,4 @@ 0.04: Support for light and dark Themes 0.05: Small bugfix 0.06: Formatting +0.07: Added potato GLaDOS and quote functionality when you tap her From 650b710e063efc49f500bb4ae2f87408ceb7ecd0 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 6 Feb 2022 09:07:07 -0800 Subject: [PATCH 073/199] Update app.js --- apps/aptsciclk/app.js | 75 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index 4196254f0..8cc4cdbb7 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -158,12 +158,12 @@ function unPause(delay){ }, delay); } -function quote(minFont, width, height, specificQuote){ +function quote(fontsize, width, height, specificQuote){ pause = true; - unPause(5000); + unPause(7000); var finalString = ""; var quotesFile; - var fontSize; + var finalFontSize; quotesFile = require("Storage").read("aptsciclkquotes.txt", 0, 0); //opens the quotes file //console.log(quotesFile); var quotes = quotesFile.split("^"); @@ -171,7 +171,7 @@ function quote(minFont, width, height, specificQuote){ var curQuote; if (specificQuote == undefined){ - curQuote = quotes[Math.round(Math.random()*numQuotes)]; //quote to be displayed + curQuote = quotes[Math.round(Math.random()*numQuotes)-1]; //quote to be displayed } else{ curQuote = quotes[specificQuote]; @@ -179,52 +179,49 @@ function quote(minFont, width, height, specificQuote){ var curWords = curQuote.split(" "); //individual words //console.log(numQuotes); - console.log(curWords); - //console.log(Math.round(width/7/curQuote.length)); - if (width/6/curQuote.length >= minFont){ - finalString = curQuote; - fontSize = width/6/curQuote.length; - } - else{ - var maxChar = width/6/minFont; - var maxLines = height/10/minFont; - var curLines = 0; - var curLength = 0; - var maxLength = 0; - for (var i = 0; i < curWords.length; i++){ - console.log(curLength+curWords[i].length); - if (curLength + curWords[i].length <= maxChar){ - finalString += " "+curWords[i]; - curLength += curWords[i].length+1; - console.log("next"); + var maxChar = width/6/fontsize; + var maxLines = height/10/fontsize; + var curLines = 0; + var curLength = 0; + + + for (var i = 0; i < curWords.length; i++){ + //console.log(curLength+curWords[i].length); + if (curLength + curWords[i].length <= maxChar){ + finalString += " "+curWords[i]; + curLength += curWords[i].length+1; + //console.log("next"); + } + else{ + //console.log("break"); + curLines++; + if (curLines > maxLines){ + curLength = 0; + finalString = ""; + i = -1; + if (fontsize > 1){fontsize--;} + maxChar = width/6/fontsize; + maxLines = height/10/fontsize; + console.log(maxLines); + console.log(maxChar); + } else{ - console.log("break"); - curLines++; - if (curLines > maxLines){ - curLength = 0; - finalString = ""; - i = -1; - if (minFont > 1){minFont--;} - maxChar = width/6/minFont; - maxLines = height/10/minFont; - } - else{ - curLength = 0; - finalString += "\n"; - i--; - } + curLength = 0; + finalString += "\n"; + i--; } - fontSize = minFont; } + finalFontSize = fontsize; } + //drawing actual stuff g.setColor(g.getBgColor()); g.fillRect(10, 10+28, g.getWidth()-10,g.getWidth()-10); g.reset(); - g.setFont(font, fontSize); + g.setFont(font, finalFontSize); g.setFontAlign(0, 0); g.drawString(finalString, xyCenter, xyCenter+14); //quote length*pixels per character = pixel width From 3ba945e7176671e5f01bccf01ce6170e69b23d5b Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 6 Feb 2022 09:13:43 -0800 Subject: [PATCH 074/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0187c1fff..38bbd152a 100644 --- a/apps.json +++ b/apps.json @@ -12,7 +12,7 @@ "storage": [ {"name":"aptsciclk.app.js","url":"app.js"}, {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true}, - {"name":"aptsciclkquotes.txt","url":"quotes.txt","evaluate":true} + {"name":"aptsciclkquotes.txt","url":"quotes.txt"} ] } ] From f316dcb051aab397e8cc0c53731b8e9cc14baa73 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Sun, 6 Feb 2022 09:18:36 -0800 Subject: [PATCH 075/199] Update apps.json --- apps.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 38bbd152a..0d7f1e605 100644 --- a/apps.json +++ b/apps.json @@ -8,11 +8,11 @@ "type": "clock", "tags": "clock", "supports": "BANGLEJS2", - "allow_emulator": true, + "allow_emulator": false, "storage": [ + {"name":"aptsciclkquotes.txt","url":"quotes.txt"}, {"name":"aptsciclk.app.js","url":"app.js"}, - {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true}, - {"name":"aptsciclkquotes.txt","url":"quotes.txt"} + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} ] } ] From b25611ee8481be3ae00cce6f91803588fedb4e5f Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Sat, 19 Feb 2022 16:37:34 -0500 Subject: [PATCH 076/199] Fix track name, artist, and album names clipping --- apps/messages/app.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 4aaf97369..f0ee249e2 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -165,6 +165,10 @@ function showMapMessage(msg) { }); } +function reduceStringAndPad(text, maxLen) { + return text.length > maxLen ? text.substr(0, maxLen - 1) + '...' : text; +} + function showMusicMessage(msg) { function fmtTime(s) { var m = Math.floor(s/60); @@ -178,15 +182,20 @@ function showMusicMessage(msg) { layout = undefined; checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); } + + var trackName = reduceStringAndPad(msg.track, 13); + var artistName = reduceStringAndPad(msg.artist, 21); + var albumName = reduceStringAndPad(msg.album, 21); + layout = new Layout({ type:"v", c: [ {type:"h", fillx:1, bgCol:colBg, c: [ { type:"btn", src:getBackImage, cb:back }, { type:"v", fillx:1, c: [ - { type:"txt", font:fontMedium, label:msg.artist, pad:2 }, - { type:"txt", font:fontMedium, label:msg.album, pad:2 } + { type:"txt", font:fontMedium, label:artistName, pad:2 }, + { type:"txt", font:fontMedium, label:albumName, pad:2 } ]} ]}, - {type:"txt", font:fontLarge, label:msg.track, fillx:1, filly:1, pad:2 }, + {type:"txt", font:fontLarge, label:trackName, fillx:1, filly:1, pad:2 }, Bangle.musicControl?{type:"h",fillx:1, c: [ {type:"btn", pad:8, label:"\0"+atob("FhgBwAADwAAPwAA/wAD/gAP/gA//gD//gP//g///j///P//////////P//4//+D//gP/4A/+AD/gAP8AA/AADwAAMAAA"), cb:()=>Bangle.musicControl("play")}, // play {type:"btn", pad:8, label:"\0"+atob("EhaBAHgHvwP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP3gHg"), cb:()=>Bangle.musicControl("pause")}, // pause From 4e1cec0993629281ea1e1b3906591aeca85c71f2 Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Sat, 19 Feb 2022 16:37:50 -0500 Subject: [PATCH 077/199] Increment app version --- apps/messages/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index 6834693ae..e84d9f0d9 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.21", + "version": "0.22", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", From 7d9ef97800115cbccbdc3f822b55bba7bddfa4ea Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Sat, 19 Feb 2022 17:18:21 -0500 Subject: [PATCH 078/199] Make music text scroll --- apps/messages/app.js | 68 +++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index f0ee249e2..7d3d78e2e 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -165,11 +165,20 @@ function showMapMessage(msg) { }); } -function reduceStringAndPad(text, maxLen) { - return text.length > maxLen ? text.substr(0, maxLen - 1) + '...' : text; +function reduceStringAndPad(text, offset, maxLen) { + var sliceLength = offset + maxLen > text.length ? text.length - offset : maxLen; + return text.substr(offset, sliceLength).padEnd(maxLen, " "); } function showMusicMessage(msg) { + var updateLabelsInterval; + var trackScrollOffset = 0; + var artistScrollOffset = 0; + var albumScrollOffset = 0; + var trackName = ''; + var artistName = ''; + var albumName = ''; + function fmtTime(s) { var m = Math.floor(s/60); s = (parseInt(s%60)).toString().padStart(2,0); @@ -177,34 +186,47 @@ function showMusicMessage(msg) { } function back() { + clearInterval(updateLabelsInterval); msg.new = false; saveMessages(); layout = undefined; checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); } - var trackName = reduceStringAndPad(msg.track, 13); - var artistName = reduceStringAndPad(msg.artist, 21); - var albumName = reduceStringAndPad(msg.album, 21); + function updateLabels() { + trackName = reduceStringAndPad(msg.track, trackScrollOffset, 13); + artistName = reduceStringAndPad(msg.artist, artistScrollOffset, 21); + albumName = reduceStringAndPad(msg.album, albumScrollOffset, 21); - layout = new Layout({ type:"v", c: [ - {type:"h", fillx:1, bgCol:colBg, c: [ - { type:"btn", src:getBackImage, cb:back }, - { type:"v", fillx:1, c: [ - { type:"txt", font:fontMedium, label:artistName, pad:2 }, - { type:"txt", font:fontMedium, label:albumName, pad:2 } - ]} - ]}, - {type:"txt", font:fontLarge, label:trackName, fillx:1, filly:1, pad:2 }, - Bangle.musicControl?{type:"h",fillx:1, c: [ - {type:"btn", pad:8, label:"\0"+atob("FhgBwAADwAAPwAA/wAD/gAP/gA//gD//gP//g///j///P//////////P//4//+D//gP/4A/+AD/gAP8AA/AADwAAMAAA"), cb:()=>Bangle.musicControl("play")}, // play - {type:"btn", pad:8, label:"\0"+atob("EhaBAHgHvwP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP3gHg"), cb:()=>Bangle.musicControl("pause")}, // pause - {type:"btn", pad:8, label:"\0"+atob("EhKBAMAB+AB/gB/wB/8B/+B//B//x//5//5//x//B/+B/8B/wB/gB+AB8ABw"), cb:()=>Bangle.musicControl("next")}, // next - ]}:{}, - {type:"txt", font:"6x8:2", label:msg.dur?fmtTime(msg.dur):"--:--" } - ]}); - g.clearRect(Bangle.appRect); - layout.render(); + layout = new Layout({ type:"v", c: [ + {type:"h", fillx:1, bgCol:colBg, c: [ + { type:"btn", src:getBackImage, cb:back }, + { type:"v", fillx:1, c: [ + { type:"txt", font:fontMedium, label:artistName, pad:2 }, + { type:"txt", font:fontMedium, label:albumName, pad:2 } + ]} + ]}, + {type:"txt", font:fontLarge, label:trackName, fillx:1, filly:1, pad:2 }, + Bangle.musicControl?{type:"h",fillx:1, c: [ + {type:"btn", pad:8, label:"\0"+atob("FhgBwAADwAAPwAA/wAD/gAP/gA//gD//gP//g///j///P//////////P//4//+D//gP/4A/+AD/gAP8AA/AADwAAMAAA"), cb:()=>Bangle.musicControl("play")}, // play + {type:"btn", pad:8, label:"\0"+atob("EhaBAHgHvwP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP/wP3gHg"), cb:()=>Bangle.musicControl("pause")}, // pause + {type:"btn", pad:8, label:"\0"+atob("EhKBAMAB+AB/gB/wB/8B/+B//B//x//5//5//x//B/+B/8B/wB/gB+AB8ABw"), cb:()=>Bangle.musicControl("next")}, // next + ]}:{}, + {type:"txt", font:"6x8:2", label:msg.dur?fmtTime(msg.dur):"--:--" } + ]}); + g.reset().clearRect(Bangle.appRect); + layout.render(); + + trackScrollOffset++; + artistScrollOffset++; + albumScrollOffset++; + + if (trackScrollOffset > trackName.length) trackScrollOffset = 0; + if (artistScrollOffset > artistName.length) artistScrollOffset = 0; + if (albumScrollOffset > albumName.length) albumScrollOffset = 0; + } + + updateLabelsInterval = setInterval(updateLabels, 1000); } function showMessageScroller(msg) { From 405711e82b44fb1562e5b18b8446548883d8b5b4 Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Sat, 19 Feb 2022 17:31:29 -0500 Subject: [PATCH 079/199] End scrolling at end of text --- apps/messages/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 7d3d78e2e..67738bc70 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -221,9 +221,9 @@ function showMusicMessage(msg) { artistScrollOffset++; albumScrollOffset++; - if (trackScrollOffset > trackName.length) trackScrollOffset = 0; - if (artistScrollOffset > artistName.length) artistScrollOffset = 0; - if (albumScrollOffset > albumName.length) albumScrollOffset = 0; + if ((trackScrollOffset + 13) > msg.track.length) trackScrollOffset = 0; + if ((artistScrollOffset + 21) > msg.artist.length) artistScrollOffset = 0; + if ((albumScrollOffset + 21) > msg.album.length) albumScrollOffset = 0; } updateLabelsInterval = setInterval(updateLabels, 1000); From d420f928203d0efbe7ce5f2eac7d5427320d0d6c Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 16:44:35 +0100 Subject: [PATCH 080/199] Update 7x7dotsclock.app.js Fix Message indicator position, Fix Date visibility --- apps/7x7dotsclock/7x7dotsclock.app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index 3f2e9b9b1..15259ea8f 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -278,7 +278,7 @@ function drawWidgeds() { var x1M = 100; var y1M = y1B; - var x2M = x1M + 30; + var x2M = x1M + 25; var y2M = y2B; if (messages.some(m=>m.new)) { @@ -295,6 +295,7 @@ function drawWidgeds() { print(strDow[dow] + ' ' + day + '.' + month + ' ' + year); + g.setColor(g.theme.fg); g.setFontAlign(-1, -1,0); g.setFont("Vector", 20); g.drawString(strDow[dow] + ' ' + day, 0, 0, true); From 25e700e577df1f0796feedbb02995720cfd5a302 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:07:32 +0100 Subject: [PATCH 081/199] Update 7x7dotsclock.app.js respect theme colors --- apps/7x7dotsclock/7x7dotsclock.app.js | 32 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index 15259ea8f..1f846a340 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -13,9 +13,8 @@ var Xs = 0, Ys = 30,Xe = 175, Ye=175; var SegH = (Ye-Ys)/2,SegW = (Xe-Xs)/2; var Dx = SegW/14, Dy = SegH/16; -const hColor = [1,1,1]; + const mColor = [0.3,0.3,1]; -const bColor = [0.2,0.2,0.2]; const Font = [ [ @@ -114,16 +113,21 @@ const Font = [ var dho = -1, eho = -1, dmo = -1, emo = -1; -function drawHSeg(x1,y1,x2,y2,Num,dColor,Size) { - g.setColor(0,0,0); +function drawHSeg(x1,y1,x2,y2,Num,Color,Size) { + //g.setColor(0,0,0); + g.setColor(g.theme.bg); g.fillRect(x1, y1, x2, y2); for (let i = 1; i < 8; i++) { for (let j = 1; j < 8; j++) { if (Font[Num][j-1][i-1] == 1) { - g.setColor(dColor[0],dColor[1],dColor[2]); + if (Color == "fg") { + g.setColor(g.theme.fg); + } else { + g.setColor(mColor[0],mColor[1],mColor[2]); + } g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,Size); } else { - g.setColor(bColor[0],bColor[1],bColor[2]); + g.setColor(g.theme.fg); g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,1); } } @@ -131,11 +135,15 @@ function drawHSeg(x1,y1,x2,y2,Num,dColor,Size) { } -function drawSSeg(x1,y1,x2,y2,Num,dColor,Size) { +function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { for (let i = 1; i < 8; i++) { for (let j = 1; j < 8; j++) { if (Font[Num][j-1][i-1] == 1) { - g.setColor(dColor[0],dColor[1],dColor[2]); + if (Color == "fg") { + g.setColor(g.theme.fg); + } else { + g.setColor(mColor[0],mColor[1],mColor[2]); + } g.fillCircle(x1+(i-1)*(x2-x1)/7,y1+(j-1)*(y2-y1)/7,Size); } } @@ -185,25 +193,25 @@ function draw() { g.reset(); if (dh != dho) { g.setColor(1,1,1); - drawHSeg(Xs, Ys, Xs+SegW, Ys+SegH,dh,hColor,4); + drawHSeg(Xs, Ys, Xs+SegW, Ys+SegH,dh,"fg",4); dho = dh; } if (eh != eho) { g.setColor(1,1,1); - drawHSeg(Xs+SegW+Dx, Ys, Xs+SegW*2, Ys+SegH,eh,hColor,4); + drawHSeg(Xs+SegW+Dx, Ys, Xs+SegW*2, Ys+SegH,eh,"fg",4); eho = eh; } if (dm != dmo) { g.setColor(0.3,0.3,1); - drawHSeg(Xs, Ys+SegH+Dy, Xs+SegW, Ys+SegH*2,dm,mColor,4); + drawHSeg(Xs, Ys+SegH+Dy, Xs+SegW, Ys+SegH*2,dm,"",4); dmo = dm; } if (em != emo) { g.setColor(0.3,0.3,1); - drawHSeg(Xs+SegW+Dx, Ys+SegH+Dy, Xs+SegW*2, Ys+SegH*2,em,mColor,4); + drawHSeg(Xs+SegW+Dx, Ys+SegH+Dy, Xs+SegW*2, Ys+SegH*2,em,"",4); emo = em; } From 81b0097fa9672a1ffec0281c5e6e657dcb2672bf Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:35:32 +0100 Subject: [PATCH 082/199] Update 7x7dotsclock.app.js --- apps/7x7dotsclock/7x7dotsclock.app.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index 1f846a340..c6daee542 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -15,6 +15,7 @@ var Dx = SegW/14, Dy = SegH/16; const mColor = [0.3,0.3,1]; +const bColor = [0.3,0.3,0.3]; const Font = [ [ @@ -123,11 +124,11 @@ function drawHSeg(x1,y1,x2,y2,Num,Color,Size) { if (Color == "fg") { g.setColor(g.theme.fg); } else { - g.setColor(mColor[0],mColor[1],mColor[2]); + g.setColor(mColor[0],mColor[1],mColor[2]); } g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,Size); } else { - g.setColor(g.theme.fg); + g.setColor(bColor[0],bColor[1],bColor[2]); g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,1); } } @@ -142,7 +143,7 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { if (Color == "fg") { g.setColor(g.theme.fg); } else { - g.setColor(mColor[0],mColor[1],mColor[2]); + g.setColor(g.theme.fgH); } g.fillCircle(x1+(i-1)*(x2-x1)/7,y1+(j-1)*(y2-y1)/7,Size); } @@ -152,7 +153,7 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { function ShowSecons() { - g.setColor(1,1,1); + g.setColor(g.theme.bgH); g.fillRect((Xe-Xs) / 2 - 14 + Xs -3, (Ye-Ys) / 2 - 7 + Ys -3, (Xe-Xs) / 2 + 14 + Xs +1, @@ -163,13 +164,13 @@ function ShowSecons() { (Ye-Ys) / 2 - 7 + Ys , (Xe-Xs) / 2 + Xs -1, (Ye-Ys) / 2 + 7 + Ys, - ds,mColor,1); + ds,"",1); drawSSeg( (Xe-Xs) / 2 + Xs +1, (Ye-Ys) / 2 - 7 + Ys, (Xe-Xs) / 2 + 14 + Xs +1, (Ye-Ys) / 2 + 7 + Ys, - es,mColor,1); + es,"",1); } From 6110724f025cddb27f283493d7e2828d6aaa84b1 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:44:08 +0100 Subject: [PATCH 083/199] Update 7x7dotsclock.settings.js better menu naming --- apps/7x7dotsclock/7x7dotsclock.settings.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.settings.js b/apps/7x7dotsclock/7x7dotsclock.settings.js index 42473ec17..c2b5d6c2b 100644 --- a/apps/7x7dotsclock/7x7dotsclock.settings.js +++ b/apps/7x7dotsclock/7x7dotsclock.settings.js @@ -7,10 +7,10 @@ function showMainMenu() { const mainMenu = { "": {"title": "7x7 Dots Clock Settings"}, "< Back": ()=>load(), - "sw-up": ()=>showSelAppMenu("swupApp"), - "sw-down": ()=>showSelAppMenu("swdownApp"), - "sw-left": ()=>showSelAppMenu("swleftApp"), - "sw-right": ()=>showSelAppMenu("swrightApp") + "swipe-up": ()=>showSelAppMenu("swupApp"), + "swipe-down": ()=>showSelAppMenu("swdownApp"), + "swipe-left": ()=>showSelAppMenu("swleftApp"), + "swipe-right": ()=>showSelAppMenu("swrightApp") }; From 3a608bf1f52e69859ae02f5e8938adc52e4bc4d6 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:47:03 +0100 Subject: [PATCH 084/199] Update README.md theme infos --- apps/7x7dotsclock/README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/7x7dotsclock/README.md b/apps/7x7dotsclock/README.md index 7f899ff0f..76684bc1a 100644 --- a/apps/7x7dotsclock/README.md +++ b/apps/7x7dotsclock/README.md @@ -2,16 +2,14 @@ ![](dotsfontclock.png) -looks best with dark theme so far - * A Clock with big numbers made of 7x7 dots * system widgeds ar not (yet) supported * when screen is locked it shows hours and minutes in full screen mode +* respects theme colors ![](dotsfontclock-scr1.png) -* when screen is unlocked it shows additional info: bluetooth, battery, new message, date and seconds -* you can configure a app per swipe direction -* when swiping the configured apps are launced +* when screen is unlocked it shows additional info: bluetooth, battery, new message state, date and seconds +* you can configure an app per swipe direction +* when swiping the configured apps are launched * button press opens launcher - From 849c439e11c13d26043bed2d20a1570edcac98f8 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:54:53 +0100 Subject: [PATCH 085/199] Update metadata.json Allow emulator --- apps/7x7dotsclock/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/metadata.json b/apps/7x7dotsclock/metadata.json index 7b2c52512..6bdeaa6b8 100644 --- a/apps/7x7dotsclock/metadata.json +++ b/apps/7x7dotsclock/metadata.json @@ -6,7 +6,8 @@ "icon": "dotsfontclock.png", "tags": "clock", "type": "clock", - "supports" : ["BANGLEJS2"], + "supports" : ["BANGLEJS2"], + "allow_emulator": true, "readme": "README.md", "storage": [ {"name":"7x7dotsclock.app.js","url":"7x7dotsclock.app.js"}, From 7af6dcd91460f8c2433a5e5707502046fd7fc365 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Mon, 21 Feb 2022 17:56:41 +0100 Subject: [PATCH 086/199] Update metadata.json --- apps/7x7dotsclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/metadata.json b/apps/7x7dotsclock/metadata.json index 6bdeaa6b8..9f997e10d 100644 --- a/apps/7x7dotsclock/metadata.json +++ b/apps/7x7dotsclock/metadata.json @@ -1,7 +1,7 @@ { "id": "7x7dotsclock", "name": "7x7 Dots Clock", "shortName":"7x7 Dots Clock", - "version":"0.01", + "version":"0.02", "description": "A clock with a big 7x7 dots Font", "icon": "dotsfontclock.png", "tags": "clock", From e8bc79c34f008f462a21a46c267bfeee2861c85b Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 20:11:54 +0000 Subject: [PATCH 087/199] The Ring - proof of concept ring guage using preset images --- apps/thering/0p.png | Bin 0 -> 11212 bytes apps/thering/100p.png | Bin 0 -> 2106 bytes apps/thering/10p.png | Bin 0 -> 11612 bytes apps/thering/1circle.png | Bin 0 -> 3127 bytes apps/thering/1ring.png | Bin 0 -> 14515 bytes apps/thering/20p.png | Bin 0 -> 11874 bytes apps/thering/2p.png | Bin 0 -> 11309 bytes apps/thering/30p.png | Bin 0 -> 12079 bytes apps/thering/40p.png | Bin 0 -> 12350 bytes apps/thering/4p.png | Bin 0 -> 11369 bytes apps/thering/50p.png | Bin 0 -> 12567 bytes apps/thering/60p.png | Bin 0 -> 12840 bytes apps/thering/70p.png | Bin 0 -> 13089 bytes apps/thering/7p.png | Bin 0 -> 11475 bytes apps/thering/80p.png | Bin 0 -> 13266 bytes apps/thering/90p.png | Bin 0 -> 13573 bytes apps/thering/README.md | 73 +++++++++ apps/thering/app-icon.js | 1 + apps/thering/app.js | 224 +++++++++++++++++++++++++++ apps/thering/app.png | Bin 0 -> 3305 bytes apps/thering/calc_precentages.js | 58 +++++++ apps/thering/metadata.json | 14 ++ apps/thering/screenshot_thering1.png | Bin 0 -> 3113 bytes apps/thering/screenshot_thering2.jpg | Bin 0 -> 45141 bytes 24 files changed, 370 insertions(+) create mode 100644 apps/thering/0p.png create mode 100644 apps/thering/100p.png create mode 100644 apps/thering/10p.png create mode 100644 apps/thering/1circle.png create mode 100644 apps/thering/1ring.png create mode 100644 apps/thering/20p.png create mode 100644 apps/thering/2p.png create mode 100644 apps/thering/30p.png create mode 100644 apps/thering/40p.png create mode 100644 apps/thering/4p.png create mode 100644 apps/thering/50p.png create mode 100644 apps/thering/60p.png create mode 100644 apps/thering/70p.png create mode 100644 apps/thering/7p.png create mode 100644 apps/thering/80p.png create mode 100644 apps/thering/90p.png create mode 100644 apps/thering/README.md create mode 100644 apps/thering/app-icon.js create mode 100644 apps/thering/app.js create mode 100644 apps/thering/app.png create mode 100644 apps/thering/calc_precentages.js create mode 100644 apps/thering/metadata.json create mode 100644 apps/thering/screenshot_thering1.png create mode 100644 apps/thering/screenshot_thering2.jpg diff --git a/apps/thering/0p.png b/apps/thering/0p.png new file mode 100644 index 0000000000000000000000000000000000000000..26b159a172b966bd60e74e76c0b6c4fa0865c3ff GIT binary patch literal 11212 zcmeHsXH=70*KOz>>AggnfF^{{oAeG+MWiPo6e)>GsM340f(QtLbd@HcAVoj{sR~Gu zDn${bNbltf=zEUm-gDpYzT@8S-(ieA>@wHfYtOaTe#j=)_>wjaB?lz{0HD#;(J;mT zE<5>z9YqHuF0Ho-jT-$ zW;?=Jm>hryeamO^>wc}yOTE10r~1fqMnb7g4#X=_3IN=<;G_MTmEV2LRG$hsOg9dW>HX#_ ztbBVszGs`CGI(s)2(`fxcYO41|C8;)_M_6_Zkt$huT0%TH_;!==NR6nPrMVo-HMv> zx^cTHN20~BHNhRsGa55dD_eX_6vv~gHjr)W=Q?1Eb z&tR1TYc zsNWbND8IPJbzJ~hlpvqR8JHk`PA0>~e{H^<9a~b}*YT{VX5_nD(JPV644+}Is`2el zAF~B>4vVd@gC3t0r;PQ^Wn#X&7Gz$Z%^UQr*-f@a)gInbXh1F{4k$Z=4(_~acyG1i zXvp6Aqi#!kP&rTD$r+?KjEWjb!F**)R10PmGrt$pn>~JuPWB- z^KH;t(4a7yYdDx8dunTB|qR?$^t+^5pp6N@w@CS+Jyeurcy7;Wr_Ujg12(6MS{TCZvdok&wYc^O*;>~z_uV%G0 zz4t`qC4sx;s7e1?OV=T8j>q*^U%s8uf5}*^KPOUmP~PXp6%6QY?X+fJGVf|WS=z_jksq#RRa!ottQ(F6)cI{UTrUO z>V^LZI%k%#QBhq(c}v&m@?~~sqoMH|rN*opvho8(b_cWAQNb^&*{lI{ zgFN7TCsF~3QA%-=$0}4T%Fc~a3qDvJzBar|UhMvPprbD0gIL5+u9!mO45r~m>C%(l zc4ywZx5Lc?2!JH8uKt?aIL}+VFN>Sav%BiuH|p;xzq9wT7V4Fjn17hnv;10z)QPPs zSEv2K_$$SRB(q2SCIZZhZ5j`9d!TPiLobTvJ-(Hg2LEh9nu2;q+sN!QRkjP0+%imO zF515FK1E81YPH1lK>(8dG$1B8`uxxW{>?oYmpLrph&y zLLlr@9Y-`Z$Q)%pWq~0kg)m}nvgB^K1RpQGx^QP9*99GYz7AlrEfm=0@G;qoI0_J- zt3U%(nhSc;bQCUCuO!2AZP@GbUtV z?jvsBMx5P33tzqlKbDSpia1*xC;Bu3Ru>i{%R7&Z_N-9TzPgMZqSnCd>e_0k1sJ9s0zr%686D_0rqq?R+{X!8`d=?J%k*R|Z^!I}q~kVP zav4ptWXyyfzAJpktg$0?BOtV3Y?Q0Yq#<%|DJg(tb&ev9G!5*acAXPc!E89${LwkR z5+K_5h$*Kd@5)4u?dm##UhVkHgpn7Kmair&$e+nI+-Yc2DXFpgvXLyDXc=ALR`@D5 zEY)6ON8ffbNQ4cXOLDHaSdw$v&7PQj$N0$yGyTUC33jgXky~D6Ls8kZP0hY*?3mCf zDvOAt70MO;?5t0=TDc^lM3S17mhwem`5bo&kmThu!lWzHQ5xl9nv2wHgr6@5ySS7E ztvulus!Zl-;#a&^{m9kq%ZgPYduj`Bxxwge_&dI)GM4*`1FeQ(-n=!8^TJ?a1OU|l z+YEZvk*70QL=aRzz0W?~xX8@bX<=>hgAjT>q&7fwkm&eco?t$D+=Z`@S7%0#ewZHn z87SAy(!!Hl6YEXbm}Fe$XHG}XmILc86AzCryOjfY0wmA4cEGvG1}4_HAA4`F#mlqF zoHI6`#0q$KG=y=|;bMe%o1^JlP8`)z-1-coawH_3aob6Se=*u$9Idm%2|5~@ms+&PjIC1Ffq$34bm zpU>}=_?oNPzTW8dDGn@Sn={g)$hqa$K4!?1njB*}QE#CO?_`caxC=j2JA0|t*GjRS zfEDKY_CdECL0()$b7U8-?8l6o-$_+^_hqHNY&2PdL=zS|i?2`j_F2|qw`Ia=dYR{M zhO~ZIx(SSLq{~Tg*a*^V7BtB6xEW>7VL%qx%XxK_tEKI*Zun@cVt;{gWUb2CMLwcp zM5ADe;8`Jiy~nevd&XuDg0OaUfp9>)QMk0rd8;JCu-a9o7-<0QMFk}iNzHh)8A+Pl zM^O&0O+;b-V)(;1}Np3sx(_a)7h*Vbr^(&lo!R_k@H z5)$P;;FZn3HPXR!`L5Ta7hYGZ_WCAGpbVl~rq&nL%N&_qL3<`-`O#V6iJ!sKwRMWW*>lWo>-y!DxOL%qg$ z+-^)@z*}_B;~H{JAEgUC&Wyvdqq)#f zm_-uLwEwWirpOZ2cv!MsMsa5G1}edc5@?>BAeD5 zZ*xq`HY8`6&s}L}Mh`;Q#OY!HWt!-yg5$WTpnn9>lz(D0aqv*3&g-wV#^@L8*)FvM35M`C8{}=C&xr zs(FKDg~yKhcWXZ%0zL)aRc|ggH8OtBt<tzSM)j9d{msA_pQj&H;XGo!gkcJX_N#s4Djt-po!fkXf*L{ zi!2!^xrC{dbovAf3;2>iJ(|>VZc=0;#^0V{ad7U|Ijz_(4?nvy(K`!5dD#Qn8pM2c ze#PAYQ<;G@LBB!0sn~$x0M!_|y}cK+FQ||6r08kh8gTlpT$`Z1cRW(*&%;ftIWlm( z`1ELL_>gfcH9Dr{OQj3Q6O2%P2ik$z7tUF3H6v=j>m=G zs6giD%e3{^791K&hF|K22qe(JU%}`(Wvd-8O+T3>XT{XBjh949>E6nE|NU@VF>b#= zC`!*pxb!{)_3h_aqF$7bU~%Ji@e=6-P%hw;?uhSiTr1Vn7Y^=Zpamx-!3{ zQj(S_mWhsYAu$1Dpnz==b>BI|sG5b17Y-{~66HPqJ$9?ZR@61;wLR<~OBXZA(9t#X z9{Q|2;J>N6i4c+JLuYHx@pm<(CO?Ga5;QMtUNXO-`Z>diOe93=x(W|Gt(C2?cM(bc zyd=-q-pb+fOzXNc@=%NVOS5{u_Ge#q2osu zpeMVZdDY?l6A8A6)`Q6TotBDyPIN>6aU}&`6Er3h-O8QMU_%@nO6J16$n_@sLty&UluxK%?S~IHnqqX;3O8vF zE(E3L_CDERwuD~OU2;>BbJ@-|H(vpHnft`Ukfx);ApG@(NXBT(9$jKTpVJH-jHh-w zl1>bH87EGTrtMg#UhKtD_ty_6Pw%H$s2 z&5wz*BB2xMo>K2dHw|i8nOvyqVn15ECX%Ktj10!P)fY zi_{&v(v>Zcu5~m`eThgA0@I_QX|3(ZUeT8nC}&x|;B?li}Aa8=4ND}0kZb2m*HaM_CDxhc$ErgDgQ*A74y zyV3deGw-9!EfQ#(pY_M>g+dZ@=Yg?kf~zV(^12r*zApwWY3836n|W*qQalQcAZ&k; zT9x?vPQUBwca|EXGRnY|9_AaD&SyU;x3l+H+6}rCaQ>SOt>!Jog!oGr>1k|MmfFRdIgpd zovMd^aGC2@g&F#kUlA?^AB1cyH(^|vmC5_hh?3GvQxf=$pj4*n@>tNFZ-<(d8p$ge zc0e}jMYs*(*R>EUkV32eLtRVoLv7Bp#MU=DLSPAr^0@`6ojtU2E#)uxj3~`J5@__p z-ZvA^Y|!X^iU){E=F9feECJiUA1e+R0lN>q?KKiuT8EbPd#sN7hx+BeTF5N7o#{_F zJ5~AI*u!;QeCoS3QAbK?=xFs&JV!Q$@F3{L!-}^&G)o3s6$Sf5E?Pn^T9lj`{!tgN z@l#PyKZJ!}S`*jdyuh|wyz#V_|3G>Yk|KCHEm^0o6b{MEbA9dzx{X9qCMJ1Ax zqCDDf5UQMsdu9X54uZVCX6T-j%iVh6I#-F%^r}-o*OnhFjKFk5(CKXsV_~OX>KdJn z+)PFY@saRqa9M}}Q<(@j=rS1xYuk=_v^^dDfGXdJ2ZQ*$)@p7hTS{!>| zxst{4E@ql+loi*WzA3kk7#l$fPd$N<-CjArk&auO6{lXD@L3mInXJdpjfVZiFLo$g zX@4*!SZx|wV2xUcEg-dW%}EX4e|%*QVB}BbXA{&n1`YBeIhwk~SaDV-bUHbyAs-G=#xa-6GNIz)Tnq;zwe7g87~1P`7JYQ%4u-c?&QEko3!W;DhbBmy@FMCsPC zOUe!U#h;(abcdTStZxE|yT6U9wi(`pMLBzoYdnu}y*?7d{(Q`@Q$YQhGyayqe!fJ% zxVdUwz~nN8=rz`LB1wSGC!HSweWc;u7keQpHaGgI-@NT2dXTA|*pxw+Y4jp_e>%#& z#Kp^(?-9qHn#=}9ik}=BNGt+_7tR&s z2|VG1!BJi~B|bj3R8H)7 zd;F}S;UCtX*k3B*^%V1kp~b|(5HSyrzgS>#n%;k|_qP^UbNoLS#7vP`lotkp)bvJr z;`o1G6z%SX{e4X@Eb?UN)Ngl3Co#NJrz`(%qpfRb{D;knjLxne=u?Xm^zTSV#2+}c z7smY*3U*uFi!;XgbGg%cE$5J zArNqgGy)2eM8M%7NhbsZBr7ce2T4dnq>vC9897;T$Zr%z7*~91!`y%O>V(P>PX!Z~ zfFh+Omna!8P*BfbR}mz4m?%E(DUoTOnAGO`k+L96Tj;N{ zr0^LA6^A>@Adu33WyhkNa6T{$Qq>t>L-;u3E9f-NK;hFQ6ZtFJ#|4RZ@;n404}tLg z4DYXS|Ih44MjQr}b%G=Cg@=^F7qBB71VbVvKvGh08GJQMIl|x(lZ*1tZ~912{2#79 z`0w%0*1;(J9RMj@Ut8n!HUO}zUK@;WQJ{6MVgUd!|H+5IH&59cKS+ktHPj@VC1j$N zAsvaCPX_>q9d$KS&3#9f#uu)QL+CVN&U0q0l#y!o3WvODUn~caT6=>;5i`Ag?~|9l z)Y%Sg1`%jd@B=~#2#L0LVZN9$F`9}YG@I-u5O>16E9;f%i4S9J|1J@N!4LaXSK z`^hK+;;IXD>s~bG-1=wEX^*33;B_?{Zu@MG>@+3CWmJ zccWl+QGj+WyS!P|&OBMRExv<6`#vlyzxgZ4ktgdtA5^S%0s0Q>eZfC5<+cJ`i^-G+ z17Lo!*c%1tu6wL(Q@UMy#(h^PZ{LxH+E8yyWW65)6vE1WRr+n9ShGJtYN7uoJ2coe|TFSS+9LBT^F5A$|XS$V8OKIvG)7Zy4 zY$^*~64IH1QCtYTD;~-J797U(s4q0sy-uKPFQiCndU(|3I}yuJ%-nOTkjo-m=e=oq zI?qMRE(XUC=}{hBJvQcrRA>bZgbPB<$$=S-o|$Ja*Y7mH+ZU@`Xt3-Fzf3;Y2nY@B zC9FM;Pf*$kw$pPcq&tajc%uq3R7p+C>Ehn*-f<+Fibg^+uvdneP#&V<5Yh-deF8#N z@$H}RKc7TziMOgSDZ1-dy7xw9a#{AnGewDUr$AMQteQrUy)4zXt zFvi{J(!e)U61KrDTE?UmwXyW5(Uh&?FowQ1vblOea{=Xb`<_XfGb%?HcERBD6ommi zVQX@?Q*l|x;jyy#p1KZfUIBUl-_%s`(mA{0Qybg-h1*1F|DxVtwD@ph%I;Kd*~St# z=I;D-)^8?xWSJX)+kwN$I$Tl5fX`394V4Qa** zTT}8PQ=M@PvsxbThXutLU!kP*HjeNalT&?UW8bHMPO7m!zu165gO5}OjuK;PlY^N54Wfd%aW9SM4r_=#b)$%6Qo@m=Tak68$}E!*^{{5!mO&Y?e$yszx3wLKHc zdf~u@T{O^w5G9Q5aJx8J(kV`uDX^wnMRl9eSNpM1kR`UR@iKBN;%*}{SLl4GevF|x i;S3~T-~u^y(KN3>3QUAo9$ay9Lg{K=(kM}L2>UOxYvykN literal 0 HcmV?d00001 diff --git a/apps/thering/100p.png b/apps/thering/100p.png new file mode 100644 index 0000000000000000000000000000000000000000..3e1464b65e930bb65050503620735a6519d4e245 GIT binary patch literal 2106 zcmb7GX*kq-8~*)=nK8ql*EW_UOV(;6%VC<3CBqOYw3xp(DOp+=8Je*bDn(9OD9gND z$(WQa)SslBRE*HEj-`=oQ)ujt^X2{iet7QXy6*e=_FUJKywBa4fLFr<00=I79lX|= z_wPty*0Hp5#DATj3trClfcr^f3;^t`i-Vmv!+$cnEuzOt#vyxc?fa}%U>{APM|&^O zU{#j>xfd3mLA3=fh1c{^LYM8>d3YuW^Bgr;a)kgUfsY4aK}!ajtU%Ry8OEjgs-F5y zsVKnY9F#2biC$gS;L(jR$Nke%AKY zHTX|L3t$YbBF~c5KygtkO1JI}a(J^(QJ!@)MXX623)2=d4q_^@jpw5$%u4 zcKPo2P_NE_7U{zqPnQhzqNCO2L>>Fpdf}rx@CRPC4g0bzEe^h4)#QZyvX&Ll2y>5f zPphbt(;&tk9mlQHJ`rW&1z4`|3~6ul=hW z{bvGfm{IjW(OX-B%=S_2k*g2w-)CpZ> z*a@58eq*~FbO6`0o<52!#adWcJi4BGB8BC(R*;6~lz5C~Ue?LvKxDs@DVS zGBYf1X1_O;nR3(zxxI9sw>a zZ0gqUvOIvW^*62O|C^xqqCBf%7}$`v;?DCN&C$x$hp<_*B}v!)>!b~3kjoJ{KAu)c zs_B&+or}R5#ylBb0DDZkdIP%Okn~pjk7J_97N|96i8k6)m`k#0%~7A6{$0C2Y= zZ3rS_{;#M2FFJ}_J${!@zGD=-INjJ+qoMWs4pH&22ip#_a5w6QU$oO(z)bplu0~Q& z(V5dm1dj$U^lXEwO3DLwR!EZcHw4<|b$`>UrR&#-_dG9*Au4-zuwSMa!LS@F^>Xja zU=VUHbWLav35~z4g2{<6k@1Lg@-n^I=Hs#H0X&f}UUAjX-ykU81A+cr>*$w;0zAoZ zLMSawFn|-pmlJ>h>Zop{K_DU{Ju$-I7M}Dj$i`%Jrfx&qZgH2tP(xl)KU%)_qm zr-XoQ_Uy#jIf*RAo4ks(`>A7Ru~~{!atBUbO&uGTCK)~qidm`C;77{BUR4w_exp@E z>29Qehf-TKx8h8b*Cj>wFC}YEsLZBY~SF@yUW$KwJ?u8q+vrD}g;hoK`4|ZuN?PYaYvYpejJR5Gy|K!9uUv(D0 z!pSradFy4~l?-)5nNf8;wO`Ws-{l`5wkA}cFu!I|lb-0kLA~oy60P||D9ch4PPe+3 zN9#EkXNiTi`W+7NE7S)&psaB1WQ);rTmemFE+kIgb4Pu&?uq<;UOQF@k#|sa$s*TcVjOBy1993zmN zpU5XghN8?=(ge@N_ct&s*OCVNB`fS}$KHMMPqCPwpt#pmtU;RQ^JJ+?sQBSl>H1iuTZF>_Xi-6Mu5sF6wV#=WkdlQov z*<8fNM38d!iJa)oJEuHs-a_nHl3FLk*mC1-yAI)maaH2QVzek&ZTFM{6NiguV7l!E ztL3v1H8Dxa#5&RDE%#24-7@aumfPF>+VNXH?az{%dW}Vj^WR1q8C_R3Ml93|FGCZ! zvh+4h#AxpL{p5anuYy48)}yiS_d0WKId%Pz68!M0gI2ljJGF}49eSr1SdL#tdBQ(H zAg3(e@Pn%c2uVBs;$-3U)oYhLHmp@#k>~B+x_di&z>ba+#^Y7 z$Rc0wKl6Bj&m(6Rq3Dz)_-dkRXgp literal 0 HcmV?d00001 diff --git a/apps/thering/10p.png b/apps/thering/10p.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a80aa23a17bc12c641a88f2f2491d806dcbb43 GIT binary patch literal 11612 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 VF^h->{tAGkD61w@A!Q!?{{Tlnw+8?K literal 0 HcmV?d00001 diff --git a/apps/thering/20p.png b/apps/thering/20p.png new file mode 100644 index 0000000000000000000000000000000000000000..4b2ce214c7b89c2166c45b8c7eda474842e74e40 GIT binary patch literal 11874 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 literal 0 HcmV?d00001 diff --git a/apps/thering/40p.png b/apps/thering/40p.png new file mode 100644 index 0000000000000000000000000000000000000000..07470987ad1de8457b9003e56e83a95656b7c65f GIT binary patch literal 12350 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 EU$`@Nx&QzG literal 0 HcmV?d00001 diff --git a/apps/thering/60p.png b/apps/thering/60p.png new file mode 100644 index 0000000000000000000000000000000000000000..18720530a0c3db53eb30b2e1e185a1fed585c508 GIT binary patch literal 12840 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 H4l(})KD5l+ literal 0 HcmV?d00001 diff --git a/apps/thering/70p.png b/apps/thering/70p.png new file mode 100644 index 0000000000000000000000000000000000000000..a55a0ffaf5cf2afa8c47e96db163158bdbc0540a GIT binary patch literal 13089 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 literal 0 HcmV?d00001 diff --git a/apps/thering/80p.png b/apps/thering/80p.png new file mode 100644 index 0000000000000000000000000000000000000000..a183084eb07ad7bc7781e44c450e210d99284562 GIT binary patch literal 13266 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 literal 0 HcmV?d00001 diff --git a/apps/thering/README.md b/apps/thering/README.md new file mode 100644 index 000000000..a63f7896a --- /dev/null +++ b/apps/thering/README.md @@ -0,0 +1,73 @@ +# The Ring + + *A proof of concept ring guage clock using images, acts as a tutorial piece for discussion* + + +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/) + +* The ring is a proof of concept to establish a clean way to draw a +large ring guage with few aliasing issues and artifacts. +* Rather than use grahics commands to draw the ring a series of fixed images are used. +* This allows for better accuracy of the initial image and also does not suffer from performance issues. +* The downside is that more storage and memory is used to hold the + initial images. This is not an issue on a Bangle 2. +* The ring effect is constructed from 14 images that represent a range of different percentages +* The percentages of the images are 0,2,4,7,10,20,30,40,50,60,70,80,90,100% +* The app is not intended to be enhanced further (apart from bug fixes) but rather as code that can be reused in other apps +* The full set of original images are included in the source code to demonstrate the concept +* I will use this code to build a new clock similar to Pastel but + using this ring guage for steps. The new clock will use more + attractive fonts and provide a settings meu to change the primary + color of the ring. + + +## Screenshots + +![](screenshot_thering1.png) + +It is worth looking at a photograph of the clock in action as the +screenshot does not do the final effect justice. + +![](screenshot_thering2.jpg) + +## Production + +1. I first generated a circle on black background using [The +Gimp](https://www.gimp.org/) image editor. I used this [Youtube +video](https://www.youtube.com/watch?v=AoIAznSdLik) to get started. +The initial image is 178x178 pixels. + +![](1circle.png) + +2. I then drew another smaller black circle over the top of the original to make a ring + +![](1ring.png) + +3. From the empty ring image I coloured segments of the ring and saved new images at specific percentages + +4. I used the file `calc_percentages.js` to work out the x and y +coordinates of the end point of each percentage position along the +ring. + +5. The [Image +Converter](https://espruino.github.io/EspruinoWebTools/examples/imageconverter.html) +was used, set to 2-bit optimal, transparency Y, compression Y and +ImageObject Y, to convert each PNG file to code. + +6. NOTE that the generated image object pallete seemed to switch the +order of the colors from 50% onwards. + +7. The greying out of the unused part of the ring is acheived by +using a dithered color. So if the ring colour is green #0f0 then the +greyed out part is done in '#020'. + + +## Stages of The Ring + +Below are some examples of the different stages of the ring + +![](0p.png) +![](7p.png) +![](60p.png) diff --git a/apps/thering/app-icon.js b/apps/thering/app-icon.js new file mode 100644 index 000000000..7d6edf547 --- /dev/null +++ b/apps/thering/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///un/1XEh32DyX/+AKIn/6//ABQ0P/Wq1dcBY3+1QAB64KFgfqBYWVoAtFBQWq2tQBYgtBBYdUERALBq5FE1WuF4dVKoYiB3QLEHgQiC1eq1EAitVuAiEBoOABYsOD4PqCwMA6tVKgU6FwWgAwNVqqFC/WrEQI1CBYY6BFwIiCgILDHQO79QiCBYg6BFwJFBgEFBYc+1YLBOAU1BYf6326FwReCBYXq3wuDLwRfBIwIuEKQR3BgY6CCwRGCBYbsBBYUNBYVAh+r1w6DIwS/BhwLBHQ1VNQILBHQzjBn2q9wLCFwb7Bn2u9wuEEgKCCUoIuEZQaOBIwQiDfQQvBBYRRDKQILEIoQiBIwK+CBYM9BYN9IwTWC1EDNAY6CBYP61AWCBoQuBFYP//oVDFwYLBBQppCAAX/D4V1XgQLDn4YEq4uCHgQYDqtfBQY8C//dCwPwBYgwBAAYiEGAQKC/gKFEgYWHHoYtGABYA=")) diff --git a/apps/thering/app.js b/apps/thering/app.js new file mode 100644 index 000000000..f7cfaa015 --- /dev/null +++ b/apps/thering/app.js @@ -0,0 +1,224 @@ +const h = g.getHeight(); +const w = g.getWidth(); +// palette for 0-40% +const pal1 = new Uint16Array([g.theme.bg, g.toColor("#020"), g.toColor("#0f0"), g.toColor("#00f")]); +// palette for 50-100% +const pal2 = new Uint16Array([g.theme.bg, g.toColor("#0f0"), g.toColor("#020"), g.toColor("#00f")]); +const infoWidth = 50; +const infoHeight = 14; + +var drawingSteps = false; +//var fakeSteps = 0; + +var p0_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLLLzWEABLgbVgohEGopYaiofDBihWVHJpYYDgYPbKx1ACJhYZIwT4OcAZWYHyRYUIgQXQH4RqOThCXUYRpCHNyQVVQQTwVQiSZWIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p2_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette: pal1, + buffer : require("heatshrink").decompress(atob("AH4A/ADNUFE8FqtVq2q1AqkFIIrDAAOAFMEBFQYrE1WgKsYrGLL4qFFY2pqDWeFZdUVkAhCAQMKFYdVLDUVFQYMHlWq0oMJKyoOJlQrCLDBWDB5clB5xWOoARMCARYWKwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p4_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFY2loAqjFY1VqDWeFZdUVkAhEhQrDLDcVFQYMHlQrCBhBWVHJpYYDgYPbKx1ACJhYZIwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p7_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgWlKzVACJgrCqBWYawgAJcAOlNBhWMCZ8qFYJYUgoqBC6ECFYJqOAApWSS4jCNQQ5uSCqqCCeCqESFQKZUIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A==")) +}; + +var p10_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAOkQSdUFacK1WloCCSCaAAEFYKaQQSyEC0pvQirZTbomlIh6CYZAZFOQTBxDQhyCYOQhoPQS4bQHaBzaVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p20_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4AWgNVoAEGAERSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A=")) +}; + +var p30_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccFawkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p40_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccKFYkVFcwFDitVFccqFYkFFcuoFeNAFcWqFYkBFcugFYtQFUMCFYsAFcuAFYtUFcMKFY0VFcgHFitVFcMqFY0FFceoFY9AFcGqFY0BqtQFT8C1WgFeMAqtUFb8K1WAFY7cglQrIioriBI8FqtAFb2q1ArJbjzaBFZEBbj7aB0ALIFcLaHbkLaJFYbcd1QrKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjUBQR6EaiqCPQjVVQSATCqtUFSZvB1WACiSEUY4KCQQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p50_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjSCQQjSCQQjSCRAAIrB1AqTgorBoAUQQiyCSQgjdSbISCRQgZYSKwKCSQghYQKwSCSQghYQKwSCTAAMqFYOoCJsFFQNVFShYEwARMFQRWVLAiFMQIRWWLAosKFQZWXLAosIFQZWYLAzgFawZWbAAMKFgmq1IoEAANUFTQABFZtAFbgsFFYwqeWQorFVjZZJFYhVfcAwrCazoA/AHI")) +}; + +var p60_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAelNBqCLVxqEC0oRPQS6EC0oSQQSyECFYKEVQSIABFYI/QAAcFFYJDRCgSCmYYjdSCqqYCLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p70_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZAgoAggNVoAr/FbdUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +var p80_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AcIdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +var p90_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESquq1ArTgqESNgOqwArTIYKERH4KCUQigSBbKTdGCKKCVQiTCCFSyERCALBQQjAPBoArXDZ7ARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p100_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLFjzWEABLgbVgohEGoqyaiofDBihWVHJpYYDgYPbKxz5NLDJGCfBzgDKzA+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +function setLargeFont() { + g.setFont('Vector', 48); +} + +function setSmallFont() { + //g.setFont('6x8',1); + g.setFont('Vector', 16); +} + +function getSteps() { + //return fakeSteps; + try { + return Bangle.getHealthStatus("day").steps; + } catch (e) { + if (WIDGETS.wpedom !== undefined) + return WIDGETS.wpedom.getSteps(); + else + return 0; + } +} + +function getGaugeImage(p) { + console.log("p="+p); + if (p < 2) return p0_img; + if (p >= 2 && p < 4) return p2_img; + if (p >= 4 && p < 7) return p4_img; + if (p >= 7 && p < 10) return p7_img; + if (p >= 10 && p < 20) return p10_img; + if (p >= 20 && p < 30) return p20_img; + if (p >= 30 && p < 40) return p30_img; + if (p >= 40 && p < 50) return p40_img; + if (p >= 50 && p < 60) return p50_img; + if (p >= 60 && p < 70) return p60_img; + if (p >= 70 && p < 80) return p70_img; + if (p >= 80 && p < 90) return p80_img; + if (p >= 90 && p < 100) return p90_img; + if (p >= 100) return p100_img; +} + +function draw() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var da = date.toString().split(" "); + var time = da[4].substr(0,5); + var hh = da[4].substr(0,2); + var mm = da[4].substr(3,2); + var steps = getSteps(); + var p_steps = Math.round(100*(steps/10000)); + console.log("steps="+ steps + " p_steps=" + p_steps); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(0, 0, w, h); + g.drawImage(getGaugeImage(p_steps), 0, 0); + setLargeFont(); + + g.setColor('#0f0'); + g.setFontAlign(1,0); // right aligned + g.drawString(hh, (w/2) - 1, h/2); + + g.setColor(g.theme.fg); + g.setFontAlign(-1,0); // left aligned + g.drawString(mm, (w/2) + 1, h/2); + + drawSteps(); + g.drawString('Battery ' + E.getBattery() + '%', w/2, h/4); +} + +function drawSteps() { + if (drawingSteps) return; + drawingSteps = true; + setSmallFont(); + g.setFontAlign(0,0); + var steps = getSteps(); + g.setColor(g.theme.bg); + g.fillRect((w/2) - infoWidth, (3*h/4) - infoHeight, (w/2) + infoWidth, (3*h/4) + infoHeight); + g.setColor(g.theme.fg); + g.drawString('Steps ' + steps, w/2, (3*h/4) - 4); + drawingSteps = false; +} + +Bangle.on('step', s => { + drawSteps(); +}); + +// for testing the segments +/* +function nextSteps() { + fakeSteps += 100; +} + +function prevSteps() { + fakeSteps -= 100; +} + +Bangle.setUI("clockupdown", btn=> { + if (btn<0) prevSteps(); + if (btn>0) nextSteps(); + draw(); +}); +*/ + +g.clear(); +Bangle.setUI("clock"); +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="";} + +draw(); +setInterval(draw, 60000); diff --git a/apps/thering/app.png b/apps/thering/app.png new file mode 100644 index 0000000000000000000000000000000000000000..0c68d224683b5ff3d5e67563c806973a418b0e23 GIT binary patch literal 3305 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 literal 0 HcmV?d00001 diff --git a/apps/thering/calc_precentages.js b/apps/thering/calc_precentages.js new file mode 100644 index 000000000..b94815c2e --- /dev/null +++ b/apps/thering/calc_precentages.js @@ -0,0 +1,58 @@ +/* + +Used to calculate the x,y coordinates (so that we can manuall create +images) of the outer circumference of a rotating ring guage where +cx,cy is the centre of the screen r1 is the radius of the circle. p +is the % completion or % measure for the guage to take we need to +generate images at percentages 0,2,4,7,10,20....100 + + +the output is below + +p=0 x=88 y=4 +p=2 x=99 y=5 +p=4 x=109 y=7 +p=7 x=124 y=12 +p=10 x=137 y=20 +p=20 x=168 y=62 +p=30 x=168 y=114 +p=40 x=137 y=156 +p=50 x=88 y=172 +p=60 x=39 y=156 +p=70 x=8 y=114 +p=80 x=8 y=62 +p=90 x=39 y=20 + +*/ + +const h = g.getHeight(); +const w = g.getWidth(); + +function radians(a) { + return a*Math.PI/180; +} + +function calc() { + var i = 0; + var r1 = (w/2) - 4; + var startrot = 0 - 180; + var endrot = -360 - 180; + var cx = w/2; + var cy = h/2; + var p = 0; + + // calc coords for each percentage point + for (i = startrot; i > endrot; i -= 3.6) { + x = cx + r1 * Math.sin(radians(i)); + y = cy + r1 * Math.cos(radians(i)); + x = Math.round(x); + y = Math.round(y); + + if (p==2 || p==4 || p==7 || p % 10 == 0) + print('p=' + p + ' x=' + x + ' y=' + y); + p++; + } +} + +g.clear(); +calc(); diff --git a/apps/thering/metadata.json b/apps/thering/metadata.json new file mode 100644 index 000000000..bb82d4a27 --- /dev/null +++ b/apps/thering/metadata.json @@ -0,0 +1,14 @@ +{ "id": "thering", + "name": "The Ring", + "version":"0.01", + "description": "A proof of concept ring guage clock using images, acts as a tutorial piece for discussion", + "icon": "app.png", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"thering.app.js","url":"app.js"}, + {"name":"thering.img","url":"app-icon.js","evaluate":true} + ], +} diff --git a/apps/thering/screenshot_thering1.png b/apps/thering/screenshot_thering1.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7e6cebc0c8160a1dee247ccf534da2d978d850 GIT binary patch literal 3113 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 Dgx=Ia literal 0 HcmV?d00001 diff --git a/apps/thering/screenshot_thering2.jpg b/apps/thering/screenshot_thering2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..521a610171da359e9ae8e2c3f2816846d541a258 GIT binary patch literal 45141 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

PZ>rG*M~V* zC=?>g<|qzUT^}9eqm`cR-)I=G%D(J`n$g*O+P+6K*i1SmQxJoPJy1-=+C!XPq zXt}li9;HoaA#*YruFn<(?aZy;Gk-omgP;Tu?VX>u{|%i&05tz4)r&W<>4qON|T{S-l=El;BD@~G0;3Zdw%_I;xJ>C7skh{n8_ z1r$-3d%J?jPxjaGb$HYSfy%xHQ>HkGn6ze-HgDn`h}pCJ=JMyPk9(uQ2l2^x*)FNT z^A7CU%y;7fKhtN~z0ti&UTiI15>bra(5u6?V_VDzCEA3#^b#d>BSPB$lA!y*g9uU4 z@wD()0iq7>8$RVJgXqm#qdS}gc)T|aqDjqh=FXpNj2z{KQaA~9m)+coK$QAmy+r20C+G~`6dK8p$cTg#30zac>=!9*{mlU4^%FzH1GLUxT42Yhv+dMStgI@awnB8-Z5@|- z>ai1%5l&rW0ul=# z=U}w1>YAUs6lhCUs;as3+lo}t0`d&j)e1+ZskBSsRbBf_AXsgynhZw-Ps=Q+)d~8RH-A$ncazPIV650N=byGl>S7t ze)cA`)PbBe(Pl=#v$U(Er#qT;B`d0(G$4!f7EgY-rpeT^@a0v7GW|9eSgy*OJtAwt z7!PX@&dPGDpkBTkk3d7@^OZwHK(34kH?HHe?-Cc3^Dicom*#y9k6y%`mUIt4oxuCPn9;^520*>@VS z3-Sa~*vAWYZU^dgHbQ-`_3OdAt^D z8R>^Zw_ymMw3SY1)iX0Xe!T4&@uOJH&5T2DDh4Kag``Qsg#B4l&Qbjr@T@y#kR{T; zv6t?G8X9}m4nhH|H8w)6=kLEMh6qRQAH$}Rol%DJOn2|k;R?tHqpHiEmjn|;8x|iN zi5M>#!RVvAiP(R8<6jm|ka`f_dt=!?#40l``=kY~Nww$o{9aCu)P@5>p_eJKi|2J( zs;y>#3qL`Cy<(*&E%PVN_YWLQ@K?N9gEIod�e9j3!`F3^QxZK5jA}%d6?l5dX7% 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 OpD1M{07xEZSpV5*ZhS)k literal 0 HcmV?d00001 From a00d2a59a6543bdafc8ae2e5b6e0746dde81b50a Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 20:34:52 +0000 Subject: [PATCH 088/199] Fixed metadata --- apps/thering/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thering/metadata.json b/apps/thering/metadata.json index bb82d4a27..a2d5e9e4e 100644 --- a/apps/thering/metadata.json +++ b/apps/thering/metadata.json @@ -5,7 +5,7 @@ "icon": "app.png", "tags": "clock", "supports" : ["BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"screenshot_thering1.png"}], "readme": "README.md", "storage": [ {"name":"thering.app.js","url":"app.js"}, From 94b2363fdcd4fa651247cc1d50b99f6a7e8d157e Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 21:21:25 +0000 Subject: [PATCH 089/199] Fixed metadata --- apps/thering/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thering/metadata.json b/apps/thering/metadata.json index a2d5e9e4e..4cc61bd93 100644 --- a/apps/thering/metadata.json +++ b/apps/thering/metadata.json @@ -10,5 +10,5 @@ "storage": [ {"name":"thering.app.js","url":"app.js"}, {"name":"thering.img","url":"app-icon.js","evaluate":true} - ], + ] } From a460f4c315b0e577ae6e43022ab455762784adfb Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 21:40:00 +0000 Subject: [PATCH 090/199] updated README --- apps/thering/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thering/metadata.json b/apps/thering/metadata.json index 4cc61bd93..03f2d12fd 100644 --- a/apps/thering/metadata.json +++ b/apps/thering/metadata.json @@ -1,7 +1,7 @@ { "id": "thering", "name": "The Ring", "version":"0.01", - "description": "A proof of concept ring guage clock using images, acts as a tutorial piece for discussion", + "description": "A proof of concept clock with large ring guage for steps using images, acts as a tutorial piece for discussion", "icon": "app.png", "tags": "clock", "supports" : ["BANGLEJS2"], From 4812a8043e99a9abd1010dad16dc9827dc57159b Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 21:40:57 +0000 Subject: [PATCH 091/199] updated README --- apps/thering/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thering/README.md b/apps/thering/README.md index a63f7896a..f932278ee 100644 --- a/apps/thering/README.md +++ b/apps/thering/README.md @@ -1,6 +1,6 @@ # The Ring - *A proof of concept ring guage clock using images, acts as a tutorial piece for discussion* + *A proof of concept clock with large ring guage for steps using images, acts as a tutorial piece for discussion* Written by: [Hugh Barney](https://github.com/hughbarney) For support From 0c5d7a564a04a6806795050c00bf3cc713508985 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Mon, 21 Feb 2022 22:02:49 +0000 Subject: [PATCH 092/199] added screenshot , updated README --- apps/thering/README.md | 2 +- apps/thering/metadata.json | 4 ++-- apps/thering/screenshot_thering3.jpg | Bin 0 -> 19580 bytes 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 apps/thering/screenshot_thering3.jpg diff --git a/apps/thering/README.md b/apps/thering/README.md index f932278ee..382fe853f 100644 --- a/apps/thering/README.md +++ b/apps/thering/README.md @@ -1,6 +1,6 @@ # The Ring - *A proof of concept clock with large ring guage for steps using images, acts as a tutorial piece for discussion* + *A proof of concept clock with large ring guage for steps using pre-set images, acts as a tutorial piece for discussion* Written by: [Hugh Barney](https://github.com/hughbarney) For support diff --git a/apps/thering/metadata.json b/apps/thering/metadata.json index 03f2d12fd..32b1dae4b 100644 --- a/apps/thering/metadata.json +++ b/apps/thering/metadata.json @@ -1,11 +1,11 @@ { "id": "thering", "name": "The Ring", "version":"0.01", - "description": "A proof of concept clock with large ring guage for steps using images, acts as a tutorial piece for discussion", + "description": "A proof of concept clock with large ring guage for steps using pre-set images, acts as a tutorial piece for discussion", "icon": "app.png", "tags": "clock", "supports" : ["BANGLEJS2"], - "screenshots": [{"url":"screenshot_thering1.png"}], + "screenshots": [{"url":"screenshot_thering3.jpg"}], "readme": "README.md", "storage": [ {"name":"thering.app.js","url":"app.js"}, diff --git a/apps/thering/screenshot_thering3.jpg b/apps/thering/screenshot_thering3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da8f140c0b36dbcc3c09c9fcc163a02bd1cfdc4d GIT binary patch literal 19580 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 Date: Mon, 21 Feb 2022 22:38:47 +0000 Subject: [PATCH 093/199] Daisy created --- apps/daisy/README.md | 73 +++++++++ apps/daisy/app-icon.js | 1 + apps/daisy/app.js | 248 +++++++++++++++++++++++++++++ apps/daisy/app.png | Bin 0 -> 5008 bytes apps/daisy/metadata.json | 14 ++ apps/daisy/screenshot_thering1.png | Bin 0 -> 3113 bytes apps/daisy/screenshot_thering2.jpg | Bin 0 -> 45141 bytes apps/daisy/screenshot_thering3.jpg | Bin 0 -> 19580 bytes 8 files changed, 336 insertions(+) create mode 100644 apps/daisy/README.md create mode 100644 apps/daisy/app-icon.js create mode 100644 apps/daisy/app.js create mode 100644 apps/daisy/app.png create mode 100644 apps/daisy/metadata.json create mode 100644 apps/daisy/screenshot_thering1.png create mode 100644 apps/daisy/screenshot_thering2.jpg create mode 100644 apps/daisy/screenshot_thering3.jpg diff --git a/apps/daisy/README.md b/apps/daisy/README.md new file mode 100644 index 000000000..382fe853f --- /dev/null +++ b/apps/daisy/README.md @@ -0,0 +1,73 @@ +# The Ring + + *A proof of concept clock with large ring guage for steps using pre-set images, acts as a tutorial piece for discussion* + + +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/) + +* The ring is a proof of concept to establish a clean way to draw a +large ring guage with few aliasing issues and artifacts. +* Rather than use grahics commands to draw the ring a series of fixed images are used. +* This allows for better accuracy of the initial image and also does not suffer from performance issues. +* The downside is that more storage and memory is used to hold the + initial images. This is not an issue on a Bangle 2. +* The ring effect is constructed from 14 images that represent a range of different percentages +* The percentages of the images are 0,2,4,7,10,20,30,40,50,60,70,80,90,100% +* The app is not intended to be enhanced further (apart from bug fixes) but rather as code that can be reused in other apps +* The full set of original images are included in the source code to demonstrate the concept +* I will use this code to build a new clock similar to Pastel but + using this ring guage for steps. The new clock will use more + attractive fonts and provide a settings meu to change the primary + color of the ring. + + +## Screenshots + +![](screenshot_thering1.png) + +It is worth looking at a photograph of the clock in action as the +screenshot does not do the final effect justice. + +![](screenshot_thering2.jpg) + +## Production + +1. I first generated a circle on black background using [The +Gimp](https://www.gimp.org/) image editor. I used this [Youtube +video](https://www.youtube.com/watch?v=AoIAznSdLik) to get started. +The initial image is 178x178 pixels. + +![](1circle.png) + +2. I then drew another smaller black circle over the top of the original to make a ring + +![](1ring.png) + +3. From the empty ring image I coloured segments of the ring and saved new images at specific percentages + +4. I used the file `calc_percentages.js` to work out the x and y +coordinates of the end point of each percentage position along the +ring. + +5. The [Image +Converter](https://espruino.github.io/EspruinoWebTools/examples/imageconverter.html) +was used, set to 2-bit optimal, transparency Y, compression Y and +ImageObject Y, to convert each PNG file to code. + +6. NOTE that the generated image object pallete seemed to switch the +order of the colors from 50% onwards. + +7. The greying out of the unused part of the ring is acheived by +using a dithered color. So if the ring colour is green #0f0 then the +greyed out part is done in '#020'. + + +## Stages of The Ring + +Below are some examples of the different stages of the ring + +![](0p.png) +![](7p.png) +![](60p.png) diff --git a/apps/daisy/app-icon.js b/apps/daisy/app-icon.js new file mode 100644 index 000000000..b577b3d5e --- /dev/null +++ b/apps/daisy/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///pf+sdR0n8CAkCwAcJhNgBI8KwALBgWgCo8NqAZHhNYktYloLKkoLHqwLByoLEgXoBYsrK4UDq0CqulrVVwGV4AXCquCBYYEBC4UC6tiBYeJq57DytayttvNW0tWHgclq2VtNpAYNYKQgiBBYIkBKgUK9Q8B9Nq1Nrqug1WgCoOqytq1/61NW1XVsALBq2ttbMB9N62olBKQNVtNvBYP61dVKgWlqtY34LB/wGBvQ8CEgIKBAAOVq7NDGwILD2/qBQWqAAILDAwUAlIzB1YLD9X1q+oytVqtbBYflA4NeBZVWlQjJ9A7LKZhrLQZS9Bqvq16bGWZXgZY2JZYcK1TjC9WrcYOAcYL7FpL7EAAMlq219NrRYNYBYeVrWV9t7q2lqwKCFwNi6utvVXxLuCBYWCGAIuBAgILCgdegVXBYPVwG1C4eohNWktYyvglYLCKgVeBYO1KQgLCrElvElBY94loBBBY/ghtghILGhSsBsECRgQZHBI5XCJ4kAA=")) diff --git a/apps/daisy/app.js b/apps/daisy/app.js new file mode 100644 index 000000000..7e148381b --- /dev/null +++ b/apps/daisy/app.js @@ -0,0 +1,248 @@ +const h = g.getHeight(); +const w = g.getWidth(); +// palette for 0-40% +const pal1 = new Uint16Array([g.theme.bg, g.toColor("#020"), g.toColor("#0f0"), g.toColor("#00f")]); +// palette for 50-100% +const pal2 = new Uint16Array([g.theme.bg, g.toColor("#0f0"), g.toColor("#020"), g.toColor("#00f")]); +const infoWidth = 50; +const infoHeight = 14; + +var drawingSteps = false; + +function debug(o) { + //console.log(o); +} + +var p0_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLLLzWEABLgbVgohEGopYaiofDBihWVHJpYYDgYPbKx1ACJhYZIwT4OcAZWYHyRYUIgQXQH4RqOThCXUYRpCHNyQVVQQTwVQiSZWIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p2_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette: pal1, + buffer : require("heatshrink").decompress(atob("AH4A/ADNUFE8FqtVq2q1AqkFIIrDAAOAFMEBFQYrE1WgKsYrGLL4qFFY2pqDWeFZdUVkAhCAQMKFYdVLDUVFQYMHlWq0oMJKyoOJlQrCLDBWDB5clB5xWOoARMCARYWKwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p4_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFY2loAqjFY1VqDWeFZdUVkAhEhQrDLDcVFQYMHlQrCBhBWVHJpYYDgYPbKx1ACJhYZIwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p7_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgWlKzVACJgrCqBWYawgAJcAOlNBhWMCZ8qFYJYUgoqBC6ECFYJqOAApWSS4jCNQQ5uSCqqCCeCqESFQKZUIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A==")) +}; + +var p10_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAOkQSdUFacK1WloCCSCaAAEFYKaQQSyEC0pvQirZTbomlIh6CYZAZFOQTBxDQhyCYOQhoPQS4bQHaBzaVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p20_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4AWgNVoAEGAERSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A=")) +}; + +var p30_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccFawkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) +}; + +var p40_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccKFYkVFcwFDitVFccqFYkFFcuoFeNAFcWqFYkBFcugFYtQFUMCFYsAFcuAFYtUFcMKFY0VFcgHFitVFcMqFY0FFceoFY9AFcGqFY0BqtQFT8C1WgFeMAqtUFb8K1WAFY7cglQrIioriBI8FqtAFb2q1ArJbjzaBFZEBbj7aB0ALIFcLaHbkLaJFYbcd1QrKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjUBQR6EaiqCPQjVVQSATCqtUFSZvB1WACiSEUY4KCQQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p50_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjSCQQjSCQQjSCRAAIrB1AqTgorBoAUQQiyCSQgjdSbISCRQgZYSKwKCSQghYQKwSCSQghYQKwSCTAAMqFYOoCJsFFQNVFShYEwARMFQRWVLAiFMQIRWWLAosKFQZWXLAosIFQZWYLAzgFawZWbAAMKFgmq1IoEAANUFTQABFZtAFbgsFFYwqeWQorFVjZZJFYhVfcAwrCazoA/AHI")) +}; + +var p60_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAelNBqCLVxqEC0oRPQS6EC0oSQQSyECFYKEVQSIABFYI/QAAcFFYJDRCgSCmYYjdSCqqYCLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p70_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZAgoAggNVoAr/FbdUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +var p80_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AcIdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +var p90_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESquq1ArTgqESNgOqwArTIYKERH4KCUQigSBbKTdGCKKCVQiTCCFSyERCALBQQjAPBoArXDZ7ARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) +}; + +var p100_img = { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLFjzWEABLgbVgohEGoqyaiofDBihWVHJpYYDgYPbKxz5NLDJGCfBzgDKzA+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) +}; + +// 300 +Graphics.prototype.setFontRoboto18 = function(scale) { + // Actual height 18 (17 - 0) + this.setFontCustom(atob("AAAAAAAAAAAAAAAf8Qf8QAAAAAA+AAAAA+AAAAAAAABGABGwB/wf2AZGABHwD/AfGABGAAAADhwHw4MYIYIM4MOMMIGGYDDwAAAAAAPAAQgAQggZjAPOAAYABjgDPwEIQAIQAHwADAAAAAHgPMwZwQQwQR8QfGQODwADgAPwAAQAAA+AAAAAAAAA/wD/8OAHYABAAAQAAYABOAOD/8AfgAAAGAAGQACwAfgAfgACwAGAAAAAAAAAYAAYAAYAH/gH/gAYAAYAAYAAAAAAAAA8AAQAIAAIAAIAAIAAIAAAAAAQAAQAAAAAIAB4AHAA8AHgAeAAQAAAAAH/AOBgYAQQAQQAQYAQODwH/AAAAAAAEAAMAAIAAYAAf/wAAAAAAAAAAAAAAAOAQMBwYDQQGQQMQYYQPwQHAQAAAAAAGDgMAwYQQQQQQQQY4QPtwHHgAAAACAAOAAeAByADCAOCAf/wf/wACAACAAAAABAfxgcgwQgQQgQQgQQwwQfgAAAAAAB/AH7gMgwZgQZgQQgQQxwAfgAAAQAAQAAQAQQBwQHgQcARwAfAAcAAAAAAAAHHgPswYwQQQQQQQY4QPswHHgAAAAAAHwAMYQYMQQEQQEwYIgPfAH+AAAAAAADAQBAQAAAAAADA8BAQAAAAAAAYAAcAA0AAmABiABDADDAAAAAAAAkAAmAAmAAmAAmAAmAAmAAkAAAAAAADDABDABiAAmAA0AAcAAYAAIAAAAMAAYAAQGQQcQYwAPgAGAAAAAAfwBwcGAGEACIPzI4RZgRZARZBhY/zIAQMAQGAwD/gAeAAAQADwAfAB+APGAcGAPGAD2AAeAAHwAAwAAAf/wf/wQQQQQQQQQYQQYwwP5wHPgAAAAAAD+APvgIAwYAQQAQQAQQAQYAwODgCDAAAAAAAf/wf/wQAQQAQQAQYAQYAwMBgH/AB8AAAAAAAf/wf/wQQQQQQQQQQQQQQQQQQQAQAAAf/wf/wQQAQQAQQAQQAQQAQQAQAAAAAD+AP/gIAwYAQQAQQIQQIQYIQOIwGPgAAAAAAf/wf/wAQAAQAAQAAQAAQAAQAAQAf/wAAAAAAAAAAAAf/wAAAAAAAAAADgAAwAAQAAQAAQAAwf/gf+AAAAAAAf/wf/wAYAAwAB4ADMAGHAMBgYAwAAQAAAf/wf/wAAQAAQAAQAAQAAQAAQAAAf/wf/wOAADwAA8AAHgABwADwAOAB4AHgAeAAf/wAAAAAAAAAf/wf/wOAAHAABwAA4AAOAAHAABwf/wAAAAAAAAAD+APHgIAwYAQQAQQAQQAQYAwODgD/AAAAAAAf/wf/wQIAQIAQIAQIAYYAIQAPwAAAAAAAD+APDgIAwYAQQAQQAQYAQYA4ODsD/EAAAAAAf/wf/wQIAQIAQIAQYAYeAMzgHgwAAQAAAHDgPgwYwQQwQQQQQYQYYQMNwGHgAAAQAAQAAQAAQAAYAAf/wQAAQAAQAAQAAAAAAAAf/Af/gAAwAAQAAQAAQAAQAAwf/gf+AAAAYAAeAAHwAA+AAHgAAwAHwAeADwAeAAYAAQAAfAAD8AAPwABwAPgD4AfAAeAAHwAAfAADwAHwD+AfgAYAAAAAYAwMBgHHAB8AA4AB8AHHAMBgYAwAAAQAAcAAHAADgAA4AAfwA4ADgAOAAYAAAAAAAAQAwQDwQGQQcQQwQRgQXAQcAQYAQAAAAAA//////wABQAAeAAHgAA8AAPAAB4AAIwABwAD///AAAAAABwAHAAcAAOAADgAAwAAAIAAIAAIAAIAAIAAIAAIAAIAAAwAAYAAIAAAAAAAAAngBmwDMQCMQDMQDMwB/wAAQAAAAAA//wf/wBAQDAQDAQDAQBxwA/AAAAAAAA/gBhwDAQCAQDAQDAQBxgARAAAAA/ABxwDAQDAQDAQBAQf/w//wAAAAAAA/gBtwDMQDMQDMQDMQB8wAYAAAADAAf/w7AAzAAwAAAAAA/ABxyDATDARDARBAzB/+D/8AAAAAA//wf/wBAADAADAADAAB/wA/wAAAAAAT/wT/wAAAAABT//T/8AAAAAA//wf/wAMAAeAAzABhgDAwAAQAAAf/w//wAAAAAAD/wB/wBAADAADAADAAB/wB/wBAADAADAADAAB/wA/wAAAAAAD/wB/wBAADAADAADAAB/wA/wAAAAAAA/gBhwDAQDAQDAQDAQBhwA/gAEAAAAD//B//BAQDAQDAQDAQBxwA/AAAAAAAA/ABxwDAQCAQDAQBAQB//D//AAAAAAD/wB/wBAADAADAAAAABxgB4wDMQCMQDEQBGwBjgAAADAADAAP/wDAQDAQAAAAAAD/gB/wAAQAAQAAQAAwD/wD/wAAADAADwAAeAADwABwAHgA8ADgAAAAAAAD4AAfAADwAHwA+ADwAB4AAPAABwAHwB8ADgAAAAAAADAwBxgAfAAOAA7ABhwDAwAAADAADwBAeDAH+AB8AHgA8ADgAAAAAAADAwDBwDHQDMQD4QDgQDAQAAAAIAAMAH/wfz+wACgADAAAf/8f/8AAAgADwAGfz8D/wAMAAAAAAAAMAAcAAQAAQAAYAAMAAEAAEAAEAAYAAA"), 32, atob("BAQFCgoNCwMGBggKAwUEBwoKCgoKCgoKCgoEBAkKCQgQCwsMDAoKDA0FCgsJEA0MCwwLCwsMCxALCwsEBwQHCAUKCgkKCQYKCgQECQQQCgoKCgYJBgoJDgkJCQYEBgwA"), 18+(scale<<8)+(1<<16)); + return this; +} + +// https://www.1001fonts.com/rounded-fonts.html?page=3 +Graphics.prototype.setFontBloggerSansLight46 = function(scale) { + // Actual height 46 (45 - 0) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAAA/AAAAAAAAPwAAAAAAAD4AAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAH/gAAAAAAP/wAAAAAAf/gAAAAAAf/AAAAAAA//AAAAAAB/+AAAAAAD/8AAAAAAH/4AAAAAAH/wAAAAAAP/gAAAAAAf/gAAAAAA//AAAAAAB/+AAAAAAA/8AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///8AAAAP////4AAAP/////AAAH/////4AAD+AAAB/AAA8AAAAHwAAeAAAAA+AAHgAAAAHgADwAAAAB4AA8AAAAAPAAPAAAAADwADwAAAAA8AA8AAAAAPAAPAAAAADwAB4AAAAB4AAeAAAAAeAAHwAAAAPgAA/AAAAPwAAH/////4AAA/////8AAAH////+AAAAf///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAPAAAAAAAAHwAAAAAAAB4AAAAAAAA+AAAAAAAAfAAAAAAAAHgAAAAAAAD4AAAAAAAB8AAAAAAAAeAAAAAAAAPgAAAAAAADwAAAAAAAB//////4AAf//////AAH//////gAA//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAD4AAHAAAAD+AAD4AAAB/gAA8AAAB/4AAfAAAA/+AAHgAAAf3gAB4AAAPx4AA8AAAH4eAAPAAAD4HgADwAAB8B4AA8AAA+AeAAPAAAfAHgADwAAPgB4AA8AAHwAeAAHgAD4AHgAB4AD8AB4AAfAB+AAeAAD8B/AAHgAAf//gAB4AAH//wAAeAAAf/wAAHgAAB/wAAA4AAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AADgAAAAPAAB4AAAADwAAeAAAAA+AAHgAAAAHgAB4ABgAB4AAeAA8AAeAAHgA/AADwAB4AfwAA8AAeAP8AAPAAHgH/AADwAB4H7wAA8AAeD48AAPAAHh8PAAHgAB5+BwAB4AAe/AeAA+AAH/AHwAfAAB/gA/AfgAAfwAH//wAAHwAA//4AAA4AAH/8AAAAAAAf4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAD+AAAAAAAD/gAAAAAAH/4AAAAAAH/+AAAAAAP/ngAAAAAP/h4AAAAAf/AeAAAAAf/AHgAAAA/+AB4AAAA/+AAeAAAB/8AAHgAAA/8AAB4AAAP4AAAeAAAB4AAAHgAAAAAAAB4AAAAAAAAeAAAAAAP///4AAAAH////AAAAA////gAAAAP///4AAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAD4AA8AAD///gAPAAB///4AD4AAf//+AAeAAH+APAAHgAB4AHgAA4AAeAB4AAOAAHgAcAADwAB4AHAAA8AAeADwAAPAAHgAcAADwAB4AHAAA8AAeAB4AAeAAHgAeAAHgAB4AHwAD4AAeAA+AB8AAHgAP4B+AAB4AB///gAAOAAP//gAABAAA//wAAAAAAD/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAAB///4AAAAD////wAAAD////+AAAB/////4AAA/gPgB/AAAfgDwAHwAAPgA8AA+AADwAeAAHgAB4AHgAB4AAeAB4AAfAAHgAeAADwABwAHgAA8AAcAB4AAPAAHAAeAAHwAB4AHgAB4AAeAB8AAeAAHgAPAAPgAB4AD8APwAAOAAfwP4AADgAD//8AAAAAAf/+AAAAAAB/+AAAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAAB4AAAAA4AAeAAAAB/AAHgAAAB/wAB4AAAB/4AAeAAAD/4AAHgAAD/wAAB4AAH/wAAAeAAH/gAAAHgAP/gAAAB4AP/AAAAAeAf/AAAAAHgf+AAAAAB4/+AAAAAAe/8AAAAAAH/8AAAAAAB/4AAAAAAAf4AAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAA/AB/+AAAA/8B//wAAA//gf/+AAAf/8PgPgAAH4fngB8AAD4B/wAPgAA8AP8AB4AAeAB+AAeAAHgAfgADwAB4ADwAA8AAcAA8AAPAAHAAPAADwAB4ADwAA8AAeAB+AAPAAHgAfgAHgAB8AP8AB4AAPgH/AA+AAD8H54AfAAAf/8fgPwAAD/+D//4AAAf/Af/8AAAB/AD/+AAAAAAAP+AAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAAAf/wAAAAAAf/+AAAAAAP//4AAwAAH//+AAeAAD+APwAHgAA+AA+AB4AAfAAHgAOAAHgAB4ADwAB4AAPAA8AAeAADwAPAAHgAA8ADwAB4AAPAA8AAeAADwAPAAHgAA8AHgAB8AAeAB4AAPgAHgA+AAD8ADwA/AAAfwA8A/gAAD/wef/wAAAf////4AAAB////4AAAAH///wAAAAAD/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AB4AAAAAfgA/AAAAAH4APwAAAAB+AD4AAAAAPAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DRAcHBwcHBwcHBwcDQ=="), 56+(scale<<8)+(1<<16)); + return this; +}; + +function setLargeFont() { + g.setFontBloggerSansLight46(1); +} + +function setSmallFont() { + g.setFontRoboto18(1); +} + +function getSteps() { + try { + return Bangle.getHealthStatus("day").steps; + } catch (e) { + if (WIDGETS.wpedom !== undefined) + return WIDGETS.wpedom.getSteps(); + else + return 0; + } +} + +function getGaugeImage(p) { + //debug("p="+p); + if (p < 2) return p0_img; + if (p >= 2 && p < 4) return p2_img; + if (p >= 4 && p < 7) return p4_img; + if (p >= 7 && p < 10) return p7_img; + if (p >= 10 && p < 20) return p10_img; + if (p >= 20 && p < 30) return p20_img; + if (p >= 30 && p < 40) return p30_img; + if (p >= 40 && p < 50) return p40_img; + if (p >= 50 && p < 60) return p50_img; + if (p >= 60 && p < 70) return p60_img; + if (p >= 70 && p < 80) return p70_img; + if (p >= 80 && p < 90) return p80_img; + if (p >= 90 && p < 100) return p90_img; + if (p >= 100) return p100_img; +} + +function draw() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var da = date.toString().split(" "); + var time = da[4].substr(0,5); + var hh = da[4].substr(0,2); + var mm = da[4].substr(3,2); + var steps = getSteps(); + var p_steps = Math.round(100*(steps/10000)); + debug("steps="+ steps + " p_steps=" + p_steps); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(0, 0, w, h); + g.drawImage(getGaugeImage(p_steps), 0, 0); + setLargeFont(); + + g.setColor('#0f0'); + g.setFontAlign(1,0); // right aligned + g.drawString(hh, (w/2) - 1, h/2); + + g.setColor(g.theme.fg); + g.setFontAlign(-1,0); // left aligned + g.drawString(mm, (w/2) + 1, h/2); + + drawSteps(); + g.drawString('Battery ' + E.getBattery() + '%', w/2, h/4); + queueDraw(); +} + +function drawSteps() { + if (drawingSteps) return; + drawingSteps = true; + setSmallFont(); + g.setFontAlign(0,0); + var steps = getSteps(); + g.setColor(g.theme.bg); + g.fillRect((w/2) - infoWidth, (3*h/4) - infoHeight, (w/2) + infoWidth, (3*h/4) + infoHeight); + g.setColor(g.theme.fg); + g.drawString('Steps ' + steps, w/2, (3*h/4) - 4); + drawingSteps = false; +} + +Bangle.on('step', s => { + drawSteps(); +}); + + +/////////////////////////////////////////////////////////////////////////////// + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + //prevInfo(); + //checkIdle(); + draw(); + }, 60000 - (Date.now() % 60000)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +g.clear(); +Bangle.setUI("clock"); +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="";} +draw(); diff --git a/apps/daisy/app.png b/apps/daisy/app.png new file mode 100644 index 0000000000000000000000000000000000000000..89252e5dfd0295126c077ec1c75e06fea87f2632 GIT binary patch literal 5008 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 Dgx=Ia literal 0 HcmV?d00001 diff --git a/apps/daisy/screenshot_thering2.jpg b/apps/daisy/screenshot_thering2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..521a610171da359e9ae8e2c3f2816846d541a258 GIT binary patch literal 45141 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

PZ>rG*M~V* zC=?>g<|qzUT^}9eqm`cR-)I=G%D(J`n$g*O+P+6K*i1SmQxJoPJy1-=+C!XPq zXt}li9;HoaA#*YruFn<(?aZy;Gk-omgP;Tu?VX>u{|%i&05tz4)r&W<>4qON|T{S-l=El;BD@~G0;3Zdw%_I;xJ>C7skh{n8_ z1r$-3d%J?jPxjaGb$HYSfy%xHQ>HkGn6ze-HgDn`h}pCJ=JMyPk9(uQ2l2^x*)FNT z^A7CU%y;7fKhtN~z0ti&UTiI15>bra(5u6?V_VDzCEA3#^b#d>BSPB$lA!y*g9uU4 z@wD()0iq7>8$RVJgXqm#qdS}gc)T|aqDjqh=FXpNj2z{KQaA~9m)+coK$QAmy+r20C+G~`6dK8p$cTg#30zac>=!9*{mlU4^%FzH1GLUxT42Yhv+dMStgI@awnB8-Z5@|- z>ai1%5l&rW0ul=# z=U}w1>YAUs6lhCUs;as3+lo}t0`d&j)e1+ZskBSsRbBf_AXsgynhZw-Ps=Q+)d~8RH-A$ncazPIV650N=byGl>S7t ze)cA`)PbBe(Pl=#v$U(Er#qT;B`d0(G$4!f7EgY-rpeT^@a0v7GW|9eSgy*OJtAwt z7!PX@&dPGDpkBTkk3d7@^OZwHK(34kH?HHe?-Cc3^Dicom*#y9k6y%`mUIt4oxuCPn9;^520*>@VS z3-Sa~*vAWYZU^dgHbQ-`_3OdAt^D z8R>^Zw_ymMw3SY1)iX0Xe!T4&@uOJH&5T2DDh4Kag``Qsg#B4l&Qbjr@T@y#kR{T; zv6t?G8X9}m4nhH|H8w)6=kLEMh6qRQAH$}Rol%DJOn2|k;R?tHqpHiEmjn|;8x|iN zi5M>#!RVvAiP(R8<6jm|ka`f_dt=!?#40l``=kY~Nww$o{9aCu)P@5>p_eJKi|2J( zs;y>#3qL`Cy<(*&E%PVN_YWLQ@K?N9gEIod�e9j3!`F3^QxZK5jA}%d6?l5dX7% zweYRB%N|he3aI^AR9TsDj^hI5yQKeP>}IO|#J;Kch4qnW`E$@@oC6vrvO3=tHJYN|AsVjE7IbGaA7Jxv!3Zss+@P~ z)7f&^^K;M^DY*uZ!T(;G;>_Ox#1*d(g;J{Ik_wJiu0!pIQS(`RXU0Gt-$)?0iiItV3(8*)3$!9l$c_X0$$2WZk& z=wDzVHt-G>d7=#J9p%RkEn-@Cn+9yP2rv(MdY*J%P1N|ex;dypvypg$$ht$?EKw_t z08+x&vFgJqFiIujt6a7_5(`?wqMZKN@mQZc*Ik}t$Z;!fneSIwq8cwND8`8BZ%;}3 z*0UnB{CToBshd7S{%#go^P=p^L*xPc_SLJ<#&XoylSW#2*IR}7p%j^Y`m3sei0(KZ zhF_WYm&S)rU(QT1VZWOWV)ZZ5u33#-8M$ne5(1gyoZ z?6=%Wq;+j0bRgzb^>)v0K0mujd)xJ4xn4S8R;$_JA+5B|zs{!J9@N@nbc4AsCLVb& z;TdsgkrUQQ8l7}qS?BR-v*_;8wO6L9U&wES@H;SqJ5fh8fmf-!o)tV9;Zc^}{n}?t zxW3dY*KG*>3W;~%3Y4t`DXqDOWJgq<$MWzk$;;)a9mS$flYYz8GTE0xjX)?#Kfy=e zzie}DnJj4XQF^CB{u|wKre)nbKrLv;QNc>mu?zL+y~;M}b$Q{AJJ~oYf?Pg9dsH2@ zvUW=U2N7+*4O!*}KpOFrya_!5vSCa(!(V*E(mAS^{Eq=*qhG&J5{fzh*Bb6ORhNA-cm%ZaaA zO$l@VN+$BTmRPmc1E^>w*t*cbl0O-*kp0r@y$np_^*rQJaH>+of-J13q4Tf}K zbB~?G`DBg!l(L2&Q5YYegps$$A$)%ezH-FuUiJd@KVKSm4QQsE+^YT7TnTxZbwl^t zJf|Mj((CgE%-e>LQ*FT2tlA@5@g+qt^wVUg%!6dk zcw#d0>-vw4+@6Pq!WF&2H4lxvG)xnZNa>GQ{8P_@G3x_l@zMY2o6xIF%jZWg|HWV! zNhMJG+ARFZl8AowjF#67XuEKQj0FBMwKr0^x<)Y@u4;8^D#Sk&J!rV^Jv1dZcAC0S z-ytlc;KQ^O0OD4+M*(~AT9CTtxB|X6(MYn;Jw49cOd!*6vHiI`BL62^#&J~U;nYOZ z0-R+RKJKFVbB7^WU`gQSEb%koF?}iTjmKo8iHWsp`79MoQEXChO9*#H6%f3!WDryb z5A+<_4A;3e0!Xdz z>cUmEClN~q@wRKv2{(c9SO0n_-xZ-TKIQq7T8+iq`6rq{Fv1fF#6Wi(EzkNlg5TKU z5jCxiXRY^el&&|KiRY)FbDtyFe&q&_f^eac-KQ6*&w%|}#LjF1qB`vCIzKUax$wG3 zQOj^g99Hj+;gzg%cT$1$&QjmlN<*-39qz_FtA^d*pxwIPPbT_}C0oYPmv6p_1*t~S zCG5o4H4|X`EjqnmMueL*@6adv0iwb0BkNieD3|)K1PUkz;*K2Uc5PB0Th5qip^0F% zDu5)o$1H+M5Cxg1?oyb{X_TTlyZ%*YwMe@fofWIeSYG3`pw4=Hd~#f6Kzbcp*cSC? zN5~>JJ@Mjd&;B0%Z)dG8QL}C~S;}_E1>XQBn6pRQ*zHtlyq(X3*V2S~$#-s-a7{L1 z4TQ4hB|tr51EUSXbHsC`@#4-IY41Crl~Yan$sW5fNs~e%+T4@Sxf|JfZQ4WXPumM7 ztQz#&>(i;e&uO5=KsnVr;EB?}#f3I#@wZe#7D55u!U-kbzM>w3ZUc_XM(wu-SGar? zYkkjOf@Z&eED3?i&wgJaf_Hcw@fOB*KB5ZZvKPD=ll1etSTnY)j=w}&;q0iA&Btqx zEFS3|OX;thp{ygY}8D(mT4YG=F3 zxdT}ZE-ruhCp7o7_X5Z2nb7FHI^+TkD3s4Eyw31a)OEgV7S?242&v#c6@*12M%PnT zCruM)6ipir2vLXgt5{%)fCPrvqZbxtH<~u_A9}y_Q1^|m_IYKMeYhlob^7gsU~6?- z$+zKpuVSv!uc3kn3}LQDd0ONs7{Nlgr|Xr{CPs7A$V>RUnt0S-4?&6-)Yh!AGgUGl zQzJuHwP%!p}k%Qrvctv3)P@~`i_eQc#O z?T$^Dk5*fwrdqMbTJ4DFbjyqdA@04y{VQvj00>7o%tS2CoyAscI1~`53LNy1RZ>Ef zbrKIj?cA}~0mtFOy!sEcER&o-)QX%W7zE7_&H^ZMjQu$)K_7|{^*U%Fj^!72{jEao zvr++~M}ZH?O0YdT02S~K>=@h@NZX8~68WP4@*z6JfT^VDy^7P{qC7l#l|^TR+<5Z1 z$+8I8^Q_4iVeU=dBIDT${kx0q&_GKVoF6xY;9!qO{qMQmfY>oH3(S&oHBq+oWcz7y z^Q%!6r%|K`e9__P1Xsda==oy$KZ4D{M0&%~Ao4ZyAZ!Pm-;Cc+9>1}cpR${j3$a#LVmnFsMzfuOYJx<5l9Gf703%SCQ z(keESvCCfen$xwtDbc3O=#=I*##jEFM0SF7DP@xaVT0&e>rXjfVH^yb<GW{27i;I3@)3xdsUll3mrhBQGgDF~ z-bE)?oWxeKX1|)i3_AT>*s6?WQJgTNM|gk%xp_UVR9lq-rT5Slg(jMA=U7X%3?)S~ zDYf`@a8V-SOc}zNXs&;f(!_zdWyjKIUa&D_@(Y3uJMMYS(lO;C>V&D5Iuphi(kLZ4gKj5?%E720zhiK#YdJpv3Q9z}}Ocy%HvcRRbk z)|n7*E1Ch5Lwy=RJwGmH8M#AG*;D6`SMf{GN1S*L`HJ-}zv=mvDE0lhc;ID$$VT5o zUGiPrpxSc#L}!1}M_jiS*nq^bEVxB;wY#^ABrW0O9ia4(g>JO+0U&|<+JtH$v9Q2S z)2|eqnWTWI~E!q9pO z;zzG;R&P=q7iH$S;c9aAidC4DyEE^Z`0&WNSJJw|Y@toPlq60{q9F4&N0(_AKP3;C z)x=O2Q)`DRE!iB*evUh4pCSUZb?r8>q=>B=y&oNIjkL_y}U<=ZN z=`M)K>^Y#QbZmv}yv9+qH%OHKfiS7D4c5r%kMnhmUUiZ9eE{1ls5|4`V2S0`pgj z=L7$J-rigdWFju>Xr7`5Bhec}>qmLBUN`bkImWGt6s>rIq}j^@nwu#a=My zMrZSMT5VQ?|K`OXy z%x;+tNo;ZotNui_8I5@HLxe(43k?%8(!TN{? zKafv^GUH%MbB_TZc)~i_$a@-mK6;6$Fr?pG<;7;q(FGCvAmV^Rl#1;j1BPbpt9?<5 z=56=JCi^sYZ+S1P^&+tTDSmnfzC03DmP1zCE_KAwb?b$^1G(V1b2)gEIgDiz3nnx% z8S-^a*79E)C^V05_vdruwNb^w-Ax?^+o7}eZgOen&@CThLA9||M{~BqhXIXAuj`>R zbW@H?@aRNbxF9U65UVESEF55^GbWFRI7yiC;-UebN(aB;Ad}PxxRc9%XBQ>X0n?Wb z)-hfW#-a@&ix`od=?0oG%d0{Z`KYAEHx&Oevb}sWOz4cLSLODFOWM72BFMN*WuAcM z0Qusdw1fW~HPcJ8zs*gJKdz#m~mXrln?;O7Zw_KE%AX^dz%z$0+ z+ZUCcTrxMkteOVw(39nucz6>!mzEK_0*Ad#Ib*}L90Vs|uPfNRO($AeFmQNMf&0_6>vL4@w zwySS(O@?ka?jo`%Nm8|VP77qkYg+p51Tl^+D??=A7ROs>%vc4^OY76wOq9UQ6=61a zf1f0>w!P$t#UpDO#zoHEWX>2SFe3Yc6`VmvnOX=sqOZGO;EOdVLLe@cZB$amV5^sW z5S#6*9OE@{A~R!iZ%W>Q({|{P+V&`D9*ui0!f#gUUcP%v6ZzbD-T~5~f41groyrCR zm6J1ED*X&eG+*Uy7W~X`7|m1`! z#0roVCtWqUX@3z_?=Kxy?UdQaA} z%ptY%tZ}|w$GcLymQo)2M{HQlClj4C+jHZ!N6AdrIh(&oLQ+GGi+_Js5nNsFDdeME zrgN7?7ts)3opS_|IUP5cmk)8qE59l#nCzU*XGt{5(R~WnhB+@`0);YsF`)y+e{!ty zRV`BG-k7C|BocwV=Yw@9%WeM&mFM*KWyisM)Qg6-IAcS3=!$)t9sl7(+=1_&0pnJK zU%eRIH9CGwDT^Fm9g9|zA4wbTGCo}y3Hb*uw;cH93q9pakhUXYc1#W27d+;3Ac;|U)CD&o(MK3ftIc^#% zWsai$`*ZL0G1qPNPJ)MQ<_%cJI+XU3onkJBQg^QYRE*i|nh&m(39$)unuAkq%j!1b4F^aOArEyz`Fj=cddeZz57vy#f$C{D%!8O4i@xHkf$~fUe-5vtFj5li}M2IV-J8+ zPPVB__84K6mB@w$lp3MbKmFBzWQh*I`T1~1;A&2dc?o_yboJ1+D~Uv;Gm&!83p&A1 z!lL;%(eGzE-G!Pz85nLh{HH0yV|4$>#753yPpgf%dMVa=QRi_(@TNu_TT3d*!t- zwhxh!K_wkz*YsQyRpH#zili2|E10>RL2I2Mg65j;&FdN2-?fU2!_4 znOv8wYcq^8{PwY_l8LW;EyYC->WJ95GxpeDga1Tr zCZxggZyxuLq1C_Wu0lg{6MS-UQZmMprw}oY#QJvtmr*WJXodrcIia!U(QqX3=5<(` zS$6&{BIQeLzvbWGbaV?|LdHGc5eG+J38iQ00kx-^MVXyK;vfmvVv1UUiI*{e6m@~VRs!IWEFy=@t9 zlskco4Ihi?9}+t8ygSCX_eg z#Z#;5BlskX^k18}l&X2U%89(m?16V1uuQkI91m|Ta~U+}D|@wl7=LlNB#|x2^0Syr zLet-!{%-x5PJM(R5VYiN6_14sAaV1~C3pgVh9%CUE}z^U-+>_m@}G|raJvD{{SW#Z zhSJ~Ofl@nftdRYeutEE^zP$zyns0Q$JF`SC{uBY-(G4-~SqK=_Bli-}MT0WRO0=j1 zQ5M)1i>U@f`hE-M`Au71F! z?+GyQeogqPn&b4wo6yZ{$uxXuQN_uRUr}vZSz0IY{AI4}!j2*oa%pr-guK^*-m zh~1UXbiw)BoZW+Sj10&4`0uhr5e646^eUcCqc>W}n%UJxPtE`)A(gi*rsgV>4g1WA zuB2Z)W@x2Car5Md>4(hg#>e8a`kxv^v12eXEfD9;J0}xl>N0JR|AOcLl;64fRiK`e zJhnfw*YBQZoN4dIkg{K;iRW$|{%f<)WF2NSy7Vgw?Lh&P;aCO+4xIgp`NyMcMcX1x z9f7&4!-o|+nXFz~0YmNG?i+)~brV^E$c4D2^9&y<{JEEd^mF@PVJxrg!5sPFC1>uo z+idN{F{4k-yJQ3wbt?}i&K(bLdPR7Cd&a|Z4-@y)c0Yt^6p83`G(%?VDIjqZ<*M}c zyB}u5n?uIM`k7^&EuH259{`0wdcW)K4u8%K&l-5s<@=A^ZyE8PA@c$AC&qYfuOZ;S zqhKKa07t{cp^W8u78etZsPym_xpknEztJ@;yx9q|D-g<5m8y{dxj8d)q*zAKP$G<2 z)Lt5CW)9qH{6LCj z3Q(myxf;Wz!Tj6ciXLeBh~*9Q6D2+$dT%-;%^2_`C}O+AWfD0iUTP?RoNoo-A5;K9z56MkA=o2LGer% z*@?rlm$O2kkfIbeMoMCCZ*d9Fo-YVN;!h~HbB|JvpAhFU9JLr>4AA5AA(&?|q!}mr zYb388P6a_6F~xPN)la8T^pC^-AgS1Ir9D8dR?11th5!>voQnYL7z;+9!5%n#N5j*F zoafpYN)tt+z;qbWX~RYz-5mprDob zs-+O%i;aBk7It4`icml1@om4O#tL3R^JU6X2e4$N;=V_6IqJ%l=Y~i#TwuXFwWd^P zp2yIFKbkrva)!@UHy-7M6;mG`_6c^%h&?e7%B`omYv zTBnQ6=4sK!Np;o{6-!nw$V_<1)K4svW2$`+VU9}a3{PX|s4CVZkPoL<2!G}Qm^J3y zduV(}qMuMX7QcS9=L;LTIsPIS{C`Qyf$x2n`({76m(XVnpfKt^wu1%-qn0Rmw@>af z2x3P604$<$n~ga7XIMvd*t9>M7F7O^eZlM&;6x4o z0D_1?W?%ttY|Ef`uWP+%53YVgf}aY_|$`*=P%e;`!Bf-{L`&X1GCc8x>Uco&dh_6Z)HKnei)xyvmn z$9rcLW+{otfEX5jpWn1;WF?rfatC00dM93nlzTe^XYu(5dOv}X2x9|EK?Iw>4LL?E z>^Hr2*Z7b@_qAVJI?+D#e}nvNd`DqB;!Kb%DVYP#3zDRg+XMgs*1scX-@Onx^jl(gp!UATq1i>lE zjzr(}761a#ulh&nha2uY5TJq;cd+^Z>tkN~Xale3e-mmF_G)YWL*569He$Wb)R024 zVnyzB$9vJkK^J%06}*qz-!cb-Wh;u3R~8X1`FX|e$sB#w_6=JjOhu%%pCGO;NXm?(AzSwCt!P4C7D~%Aa!6vXqEo}Vm3^I zQr7G4EfNF^hvv{`ywb-yNef9E#K|%;p06B{>6S!c>=k4ztP~K#?a@2LEcqI7^qQ*VH}eZN$jUcODP?9??8eH zAgcOahkOstH3_~MgjM#{wd9s+)sF36J<|s?OiES_6vSGt92#;IKCwMNO#E9n81kNB zlnvR&QHoYoF_%ixS#;jJ0)gwf4i!OU1eapV^7P68NPVJdP{b4X_KlfE#}>Wl?+L$| zBnOOn8YNI7-8C!-VIhv~Q{S&p70%<+A7Fy&8`u?>{7-qsnPJbDQX&U%Q7YS&nS`pi z$%qU?1p-L+0-r>Z2wjj*@<-$1qSOsEK6MQj0I(Z?i-P?Zqpx%3{{WCJg<@O9x%Pol zS*tho2=hFBsw*1hR7T1rSyFIoNg;_{WMG9eaW2G+ijTLv90m>9j$^`7SkhTz5@^8rdtY-mZ2i_GK^F}a)%wU^ z9Gijh9#2YykmKaZWGf4jQ(eu)7=&{C{Je~)c;QglkcMJy02yPYa{ zX&DRtN6(B-48n-G6rx>)ZUvV5ETMjyBI6|rgKS7tiBU?QXW09}09Z>fv$p5{q7PPM z#i-vjv?tbSkoo(tG|`wobi%V zhalZmxo!7r+aZ1NF8rsE2JSx*98jfbA{L|QNpR$S7E%cvQA9wZs;+@z!PpIb2_Y;f z?OXBXQ(*Z5MIJGHB3LR?%e_duGn(g5&l4Ii9B^ERkok@ihvIuBjJ36{*B&OC8jt{5 zYZ9uoOV%U}r4lG+>YbN+1fM_X%2L>!l&F9+BCKo3dPV;L6vrn4gPVvc+u2FkNPoFN zP&l=7^tiFxo&xzm@zYe|UPR>-EOLof8*|>wXRl&qb7DB)`eGbxkX5HxOB+uZn3ssn zDVk{_0V3olc)yFSYE-!@Ot3%Hk^reYR3L$1Ex$PN%typu72+n%orA*^;nM0!`%9+9 zEmAiUNd%9yULxnsAIkPG#Pn(N&Iys9C&9A$7^;fbBuh5%(_ey1RN53Ua^#;e|yDjP0lSaQSJ(`8yks=e+kfHV1>@teDv=%M>;;D_ntOwV5N8YF1Yw zCUlMGEwxlpBr>slPsFF;(i4V3TFD@}X3C_}+{01n7d{~Pixq-b`!)(un>>S5ki+c? z0BwSjt2k!>oT5m{^0)H6Bj?JU&}iqb=N31FVPs_mnd zK-mZ5qmzh4$wFdO6p}WdFilvwrv35i{u$zUe-XjS#$nV7Cd&l5s!m|$2+-Rni}m?; z{VV(p#=KjC^54!skmBQY`8GDB@bTN6j;{#AarelEnu_E(9m(p+XDKu<6lRi@q?7*u zY8JdFjzAUTW&%XCmImR7H0C_{X9S;%QcldXwm@@Gz~!Hyp=jQD{{Zxh@SiyGMpMim zC4NVI>tZo?F4yC)$#Hzsit^a;AhqgvE>%!{TxM}26R=#3td2Hokwr>jiH=DwS0s#a z+Sr^K%?Z@xOP@ig(kl#n@P71=DRP?<&iBjua}gW#ulX(USIy5Z^6wk-3>>1oTrUmB z@8c%pnN-5wt#19?txJ{di!|=RCvgNN;hwM5f?DB~!kJ@o<1vR05KzRZZ4CEc(X+iG zbMcB2wu9|G_Oh!7Z%DOUf29ZMnO5}Ft$D*ai^$NC;Jb{m<~|6vYswD3mD<)Y>t?)> zv&O*m+aq@d>iHLrz+-{tmhu577E9Z_&+DDW`Y#yirUPR!81hx zRC!}$E@Zue#NubIrphwII3>z+2ksyPO97b&Cyfac=PZP&M&Mn`WpjR9T7oEmIqZ8K zMx}#D7?4RlLV>gFjSt3%ADx{IRV36GZAay!O(nzk$}K1K-sSb=zvLerUUM`#jAd-i zN|Lj6oItiHUr3^42nW%gyppQ6`jX#BC^CF`$HrJ)l}W`QHpyB|T7j&?Ck^*pR2cF9 z0GQZQDsB@Rl$S{xN)AOCuEE?3W@}2C$@#V7aB!|~%ecs`En1kqRhxpnY2h$S9Urdp zQ4Am3AgeuRhE>|j5spM92>9`TnbU;t1;8k^uK9|FA+n`hn@6O4GmHNKZ1B81*K_p1 zHZ}lU685dR-X@Rfr4r5J&nSe`B612c#1SJav5Ay++3e00(T8GUJ78y{sxFBbOBI3l0E!ZD7mRM)6ezN zE+s;OuEM8Yw~K52A?jYre9&@l*+0;^jqzV0$_Ye|9)(=T9ts^+NSavQNuY>;B?_(# zut^z^#h-~mBXM&_ww!H9vV~ZSidR%6mj~md7BmFFAaFN5yjxK z4jM|c@(SfEEHq}Pe;Lv{P|XC51nGWR#PAdh%(2Wvp$r^&P}3M)oz2J;BZYYwmLX1x z1^|LJb|c@Wan4s8k~ul{IFdU507=R*+XZgjqAeL7z$dQB00m-$uC?*dC-{!-NXt=m z9-McWo>|Q=0h#78Fir!Q4k2#J#N(!Joe1o&^v|_q_T`tcIu1nt03p+@A~8bQlEP^e z^&}pkF(-b(2eBZYz>m&|{(Y0H(u1TO2yP`&6}HLLupi#+yLox?nOeQewvys8NF-}f zc6I_e;r+WKofPh*D>*`1GQ;lfJ0be-?|{Z-^#r%1Cw@ zmj3`8{{VM77=1bI=_ln`7^Y=tsZ0B6=lg%zg;iNWDxeZszNcbYw#c66z8rKJ-R6q4?fP)Magq2@Cp#Jh{*j}-X>&HR<4 zrTgo2R(O*$$?}rTC2DahfJFB#mo{w(<6#wbGs?wObqGeWd`lOEz{;2unSW70ge8(x zr=#RYZD@h_&ScxMEVkd%_ECWVc`H)kNREftqjl=8L5z7DQ`Hy##ekxmk} zM%;Mmn#(G(nh{L3UZOr)S^0wD6 zN_){`+09t3*{4=2_N_+0THIBt#WS+iu0A7=8xv)bLR0}3u)RAw=+-V(=Vum%Z9B7>9lt&aI2$)42Xv-(kAbo&@R_P&T z9yBR(r8BGTOXk)bX}~pIqKwc?gd6YAIvTxck-r#xypQ@s{IB^l$eh!b^A9%js$A!t z^1Q}sY<43*!Ex|bx0kfnAfsOkk-_A06B^OW4Ruzy&t)Qw)gkU<3Qi?*fB^u94oU`0 zIWvYd%Xo_Dn=uRmRYs__HyzquC~N1(jqXIO z*$zFN$F!DH7n-KZ)4;LXwOc8UXl_-VEJu;X<9bXUCQczAVp5d?LX)xq1Z%`pF)z5% zHE`IHvXrPYsY^etb2a6qeHlux z=kFo_%eLl4+H)x2gRo!1aq4q09`qEv!$h{p4yAg4&GXXo z;;$nfoRGn@cQD2L*LO@Gm7^}*`UuVZ1B%m^1Ey1Vm(r9_s}ub%HX zmA@>%F?^5Zv&@n6o;)U`L5 z&XEEC08lR(ahm@CE`A{LeI=f~iE3KoI6Q0;wHg?%GSEwYl?TAV3fHRGxgq_uQpGs~ zf44D77>Uy(2%u(f*);EPi!%V(R@PPKICP2;;?W=eM5LsYCmWMhQo(yScwe)tY=8+e z4Fw*+LOmhhL+taX5AEYEWCBak&a|z!@rmD^2z+~bNdqTN0h(xvw@_qUOwt8EP7+cw zLF~){D#aZ2B!Z*)4t|COw#4Q#%i1VkH!8_71a{eAq_cv0{k?%B(fkAK4@?YWjX$M8^3+JGYW7=sKj!7i|=fgom>1x7j)Q3<>3CWa29I>D*b8^Eo z8NU*EvG9)#orp+zj8KPm3Q!^6EtdxEtpSTa^6q<=c$bM|_)mhoeUix7nwwVstB%99 z+Bn+D7t?78td4Bt$(L{&1!GnY#b!h+@#j)htY#q0#!T9EIdilK6(A(AdQb-0u#XeL zE>DZ&%>Muv#e{;QrkJ9kRv=XD>q`dF%vBeVI5(J($Rl(*G-d3wFfyqdf)qif$ zA(3jR`eig&vj7b|2*ZY&wF0t6Pg8f)*z>$c;Y=TbU`lbA%tX1EsfuuwC@Wy8h&2EL zDu3-NVB_sETZ>0$f%zARSml`8*l~vBymu{;tCFW?3o%irl&NxATBL~_?yUq)$g9*k zpS9OzhW^r4f>Ti6-F0f-J!=m#Rw7>9g{5-Je$^z=&5bjw`qalnf2(f-=iYGe-+{ST ziMYmh$ygc|Y-B9W!m*cm9LrNLfv+||}4+!&`<6m0};dF~*Zdv&yjd`T{vCODkg5F%xC%IU!9!dN9y_ zB6z9dazaB8GjR33LrAW_mx})YGJZq(tn>Xplix34xIZJ$a&BXso_qO;FpzStF&{F$ zVi~Ez_$<738kg?kv(`%WEX7{bvBX{}?m_XYC7~!mT1NL54qWdCP4Q-2rjmj{HMzJP z3Ddj7HRRt3eCkQ(+Y$5rA>|wXW4Fq2!~IniOohtR=APUi(sFoySBgP_j*J#eGE}*b zyB#_oOocVgcSIb+hY3*tS=_TeL9cd!%v76z1sTppx2#_m>Y#2_{W*9RE6Voh-SVYe zkBy?1?n-L*GM2eD8Zt$lvqILD=DlW*^$9IJAT`Jhwy=OCr7CzySNmyaDRK=Pn9;egMvkaNg8M<^;C$?U+dUaH>6(D&>pAwl~{{FDCxA$~g|91zdDg?C3l zh5e-FY&Y9Z5ih<+!#B)73P1|CT*@~46VPFsuhn}|`Kcm)u1_4pku-7!^b*WU1ZyMx6V@~( z0ahfmjDeW5e7*A!5#X3ZXPGjMmd(Mr8GF0~<(djSIHcJu!0#c3`UB?@hxC+%kIToE z!zmzh>CAE#XOywyIIvf)-4KuzgVjE%?dYm0Ujm#G0MuIfpV953)&fbbghu}Wn=Kp< zl_QX;WwTYIK&RQ3{eJ8TIxbZ7KbF~*7wsipl9Eca2R>c4uwVe7irVoPMVBnD@6+~7 z#Cz;j$@*hn$pMG*r?W5w^#GU<#ElC=i8J!k;S3+l7nZX=KF;N`n5iV=`7FjR_9~PY zrTy+ORh1&MTHI?KwdSbP#uQtnF|=!>R$fLGtk#)bu0DmJ(zd9@pNBGa=cfqmf8`FY zKA+1^hw?WszTxqf4}e_cHW};Xl;F}_Nz2M!OV#TcEmJRR=+7XG$jq%GL=p4;p$lV~ zNGEp&^oxZg2Rhq!v0dM+4<5N!#T*Yl_u&1c_ioawiLDb!TA+MeJIvCpmX6G<@J$Ji z_LW+>kLj=^ec3oN4BNG{4{+^T+yVzyiE`g-TaGDoUkxqvIS#yJwh~) z#u0U|&vqS8Whxn?Q`iORC6`Y+bP6}pKt&Y%v66XfuoiWYW0foLU~ygtP#~f+Mj(rANB-#VY9YScA)I& zX@<0~;A#bke3<@yVMMO^Wg%yY%l$R}uAaywcj(F(Y`6H6zq|6mi6jzF*MA|xkAvgM zcKYce^!rcZxifE!9~T8uAARc8dQtr1PkBbYp`3=(#@|J%L0&mZu#QKKrfCrv06x`l zy9&jWDQ=_l^em+?PJ{y7Ys2*z_z9n3Npfl$$1}Q=p%xsNw~PF%obewkkCosmsw zcPJP#k=T-o!Udl@Kj+|7cGBsKw?QDlV=2w z^r_I0@u%UR2H|`%c*IDUy|7)jj>$Tav_Wm)z$sAx{z|O4H;& zs4R~h_9U>&GQ(%7V$u*=GZFRG)k?!LxCsHmpE~!;hbShBLro!lhPi{+5u)CVA`soETL0CY@dpQ zzy!4tCN97CFv`F%7Rjz&wT$8N_X^>$Gc~390tZ)XhKR%EA0}kHt;=NP*;+L5x2K^_ zgV)Ej#woRsP!SVerOGu`H+*fkrjrUGJ9d?oV&w9uhn& z2%IWr8KEWim3|q}WE`-xPk)uq)l1HwF5Gh+z;d)PUQys!8jC{#isY8mi8vo&?0C9`T#u39UM0uo)^24~^9^WH63u8$Gv48+iPRMHQti>QZ{PsoPmA+oxtC(OR!6GEEb@5}=J~DIsYoHa++GtZ01}K}8sY zy!v@(oL>I`3;lU=)VS_CzdG&f#b?&`0p!|6NF*ejT9g^FQ=K(bT* zv0*!`vOzj0(}-rP!(Cs@F|J1MrT80+>lur{l4wIcfI6M@rlKnA=L6@D%D*`LryZ8& ztxF5Wxb$+x#yEZ(>b5f)(-t!1EX_N#*D|(ZWQN6$>_haShB)gZ#_~(2g2JN?Qa}Wj zB!OFBb9z0Z#GE1}5Lgl__0P*Y{$d@)Aa)~NKm*zC2A9_MOMV9Wk^n8}o#>riw@G`q zt()F0#fE;K9C`0~hW2%9!!%ePF?HTadYLNAa#(A{G+$9nn`p&|iHNHLP&e4buMhFG z^o$xM1u@%=Zg9x@e%#U|8nyrMhHbSazagBvJa3zVjUJHKV_z!vSX@$;PHmB<0e6b0XVP{*Ys_>O+D8GdXP;>3APNK+%vMn*dX zAUA5R$OW~as$I4~W$nJbg3~D_LFx{f0j{6hM1{lKIIb@YpqkcMm@2pI58TDK_DiiY zg-}2~)q@arSM3@AOQ2BE$Ls_rqS<-BD^H;N3 zV=Bg2riIc-zL(ldBZfUfk@k<7V2l53ZevG65=}C5BxizfYDZF2InBcD9{o1~9be06@9wArj zGsZ1pyaVIAc|6-$%Sp)Z3Gr`EI`2{ph9-MayegL%eG1dW(H_vvA(7G@!4#4YjNA=o z1En~*2fM|o;1n0!End5$mX0){Pa~_bA(sz!C0%{wtgyF#M_p5>Bo#X#7A!~urk88I zeT8EpV5^H8KJNOwOaA~eN@{qAIWi)%F95i#TW&(wi|Mk+s(Y~O)WrQ;qd4`{F!-@8 zH3WfD8$94eDR(E4A-v*KOy4SyyQ_lAGWUqtzU0seJNm#B!8+FFsTbf z58W1sW_D#w1Mdk|%?YIk4H#*=gmN<0B+Ob!YL>~3+wrV0wwtLPHcGJ#rW*I`vHt*Z z?42KH*-&@!WdvI8+$iQW(ygHV`@tg4R4S>GLRbJcPL9Cz0N3P$t&)WMKA6E|2P_)E zWP7|j0gxV0tjX|hbBcU5T$c{y_}e^`AN1rF`1V$?#3uXKnRvcVvz0yQD7(2|l15X&SMW0DDBc8XZ0Mn;NQ*rbuk8})Q} z%8<(HtgNIk1dv3cn~H0oF)*O2f(zD#)MY*{(EeINZz)f0|HWR z#jF8;EaAap-?JDQBt;B65XX8WNANxN2hbgTgXn%wtr7zh+bzBKx386>XHN^7%EHp) zF&R7YtGY`)JbkNCsYFL)X)DDdDO8#w-IxRuMq6FiXpk;I;{sCB58OZ|uvQv528rc0 zEPmc6Xyuf{A%!Mhot583QNHv#W*vT_Z`%#bOiDlix#P~6`b2)JC^m&(%e#LV>DY<_#)838i{Mv6$j)hJ{P zz0{G_)Q|*-NZK$u-(aWw$T(0na2sCph6_rG0E4Y_(~Nl>A!T5?&?IZnKD0-#dr`CZ z4f_C*uWD4R0iLw5+$(65ZeglQjYywzpZxSSy%Dk5NFT^yu%war0GH~p{z8{GKK@Y^ z76j6o@r#f7DC0l;W8m&_Sd~B!LajBU%;NWau{+8Nw2d4#O!jYyb~_tD*g~@$#JSwS}F@>T}Nd-Gp^W3?DO| z;pctv8oq59j9-((_U`i0&=1@)t?1)Wtf7HGtrLapI(>k}!u)@6G+glfMX3Ig+&hAEFPn_Q^Zqr* zIW`juz;E(j>70`nUoT8qqnW_R47BUnf>m6Kn<3z3DC`ng(V5v}Y@A|>Q$k#gNY8h7 zi_$=6&-?sStaZWU1@Y~U8_THWa&zD~w=UxOJZzUM*LbhtX;-H7ugOyzDt_iV(bToG z9CYKchn}=@))Bj}T;vv7NpnyQawK0?zbZl23PIN?@=s8wG@IK6Lp~-H)OsWR#{=;>VwX%6fdp2zMe7n3@!p-`L4o1)f zCo*LI-jb zw7}>(v1qnx4+9s&r@&*M(r`o+#y< za>DXHHNoK5o!; zQQRGOb>|Eh&v(mbjywpyF}LGonJ97$MVi@mxykEhr^wu;^reF@9T!xyS#6_ONoK~q z-ah{TMzE(mQac+*Ly&W4=}xh3MCGj4BEUa)hjLP6(r4Ca&ODFwG#flL&HpKN?DTl9yu{~KU!;_MD=A|H(2q&2heBojO zixLP9PIuxcKt zR=W-hEi2roVG@<~nreZ*nYlzcoMXw^w71$tCD~EP z*ShJ>2&pPjNpcGfpx`;q$I+gk(jyc;7&j&i(DA&##LzsIO? z>hk7mHyp#>ids;AOAS^#7idz*GRrI5vtbpQXW3+u?DW#&$M7JMP*F0qpcge`e4V&w zxW!$YL0J0VreggWf-x!vza%!s*n0!s#)rG0kb-nRRQ$#GbNpAtbDl=!xQ;7_hQ!Aw za;o0?0I;i%Sy%U$9g47xVTHQ}{{ZeZNuo&A9DX!maOznjX^0gLNwqc5QSTUjH;+$; z;Ai4WnUF$qB}4!KdpV^N(xXUE@G6-4N}S30XG1-1(afx{KY!SjK`>dr`l@`rg9=3lnr&!8`rl7LqSV# zUi{zZ;0f^03=L_@NE9>)1IouHt4FzDRD^~A3RpcHmtm(~Q9S!WkUO&>pHc_)8#2`5mKpIUE9=>f zN6o4+!ud?73-ns5i8ecsnJR#H>FuN}su|f>g)O}S?ubEphS&84Vp^AW<#?_y3^`kQ zhBF@j0JZ4x`qYZjsb<*gv$fFyPP>fP9)%1L*j7TkBlkwp-0#B=OL#D0vFWx4Z@ zn`pmh6VUO-O8d=X877LDgE4`QD~$>SNg=N_m|?Zqlt%@r0`_S-OO1{oBBysfJ^99j zhbdq@_nK*uG1YfG<6NhgMda*EzqP>f8yrsdCyi%+rpJFDQoeSb+;Pgs0^AlpwF?lL z9tNHn{);MFF*_i9$w%)GS0eke=@zC6JGH>3XYkPhe_IEEVS`?nYe$n?O0gZbV5;F-t(&Pas>E&9Xs0T-kIm#|brAwFN)7h^N z@6FamI6O<00rs+DDN;}rvN@8__Ps-f9fxBvexxW0y@*q8N&B}^xR)P@t_U_S6p3j& z&cqU%APw)R{CnTzru~7Tv9J^`p{pv~lkWro>=UkB5BCzM!jT8#x1=l!HMh_wuU@hJ zqhsIPSnosdLH_`7KF0YDpZ?y(Dd;gI0h=>j?VjhY;)W~yd)6Jg_ov6&hIl3V62g9} zN~d}!_&vKRRt1ECfmTw%f!>e1Y=&l_;}}?(X_^XGp{W%b`a`FX6}hh(HXurmo31OB z2wXbJvXaC|=!%l6o}xn0hGZ)JQ-2W&WjMA&$lpun7|16JH$9iGiU&OZ0FME!o!NP7 zN|G3zT^u=AQVQvmov8<1db2QMK_f@-8i0a_(senlKqrWcz_+2m*v~R458`7wr{T3Sz|i{@Rk)083RwQk^x_cmv<9caujM>NdB7|HCZ0A_Ea8QPAC^v3=5 z>;W=uofqc9sDih-E`kK;mJhz7h19%nAFmXy0Q@$}&vELS+@m`rA04~FF2gBOa< zg~TZqBa5UvCSG#7^;CT4YIb zfUTMWMF|CFgaX;nGYgX*E8~7EjQF3$Q{ng!P8kz6K^sX5*elyz?b@7w zUGCo%*Wx+9zmog4(xiv#f{OnD-1MhFgSBE=e&M3Nh%yuLDZjw?a6}-dQ`(K^7cKfO zEKl>7nxSg#jCCBJjPmrZ&0VX)?E__a`>lCJg^2Fnfm^`&9{K>k4g0F%GtMG9d?$@q$QxuU{;;dZkESXRC7iBsXv?eS|( z*Ilj=w%*u{E`ptb)peo2Udi9&eVy_gAN;XBL=U?ZNiOel8kG!dR(dv+abW$lprej` zjxgd|mq2wriS#s3Y&P}RY!n42?jW7$=x<*h;tPSP0JLPSJ5|p&&sU?EHG|CE!(B_& zBs&CsSX*C4cz-527w!k{A%g%J7=}}`@Km5FBJW#X{0*Z!5g;r&Uuo#U@+GLuGO24? z@a)>f;yJZd%FvxD?`tq55e-aesibRdQjA!9#RXNVF5C{U9DxNDg^&gYEjYMX~y z4nkbelE-}qrJ=LPV{YQ)RJm4K?nH_{q-=sv8JBUifCf*rkjMcb1|$MDbQc^c-41AF)Pd^-&XNU&51cNMRHy1*U6 z9R<)UqU3@B)`33A1Z#T$=#PP|EW)I3sPFX;A8Slm0U85G+N%wFC;U%c5>$2cM*WZv z#5O_y01>0Nm*JX_?sYw5)DFx8AYgZ)r5Y#r8vK7h;=NbbZGETVwgEOg1vJWmT_jjDez|u`ESHOl6<3+#7Uj{P`xIUJcAfySc^eYy@ZBYGD>!e@j}u> zG{Qu3>lX))$6`EEcl$OG3i?jPOyrvo&p>EHf;YJ)Jd4LZA;)|}h!`&pM8Stq3Hx2t z6rGxiWF3j4Ug9Bd%rBmDK4#=`y?ABE@qAm$9v2?vnn^_J7fR2hz#7$q6JvdIYY6)U ztfi6q``9c10lOUnb`INn8a{~rHQVELAQHz<#C6F=WLF{jhPTWP?~KQdgh;26Sc9TL zK!3;|zzRY3N3Of{N5{_J_=JD=XNI##k5%Bm1I>c<)n*Aq-RWAYDpC6U6>5Ut{SwB83c_l zp6+|zI<)20^SNw}FC&G$Yx-romNN!=RpF7O$%rEb25L;;sQIO!2fBPzTk+9Yb!*S7>ZW1RfxJ`8!86K0cJmO8B++W(&^)R<=BUF=Vru__`3>)lq}~Ifs2+= z+9?SB8IM&^La9Y&V#l_en`w6(M||R%?l^bfVxU5SESft9)BgYjX_)JNwm-xlTOerb z+4!=OKqjmRCA6#3CX(PENR?hFlj(7bDi{S@T{H)7&d8y@?z;o0KwZC`pU2(t_MgbI zN5d0oPp?da`Pr=e;)Wt-(FxM6UCp~O&KA}j2hdUsUeF1 z{06bR$7F5e=Z5V$WQxRYtgfNd9UYkD&_N_*2JI0nSUDf?w}gG19PA_?OU9 zMFWlB>T6e*<2cNlDRP*n?$d~R9o99tqh2z~_}&>{OI&X2UqG(kN=cxUODY6Y^rxVo~N18D|{ zK;}q9iiMaSrHZNQz%Saw4P-MpeFs|Z?|_ z$4<vB*%+abmj1(SnTeDDd#&xNUhTn;o2A7*U3|gHnlp;vd9+t{U#pRdJUSkPeL%m|q^#-&+pDq! zb_}sQ&9nnPD}FQ&RYW9SdR2am$JkunxI3SbzdZpwMvoa(rDj8}c!2DmvRu_oc zlO&22g(Md{OcEX3;zIGNn=U~lmCXbIE)axmGF+sFJ4J$O(OiC3 z^6xbAwr*^vC%onbENSB_Jfj;&swx$$T33*c-A>)RGYy4cnp4$az8;a`vf5Ojr7#Lo zllK}5I;zfG0YKx7dS8Wj77xPZp%SHqOail%l$DkPbr{=2YSgpu8!Pr;NY}C0s_#Ss zq^V)DH@y#A0B_gC=E&I=ZN;+O2A1C)0w_T4(d1%6QNP`k22y>K)DL<+j=uyQk+Mgz zs;mWo^n*iX<|QkN#cVNFoXkk*6RA{5CO@BFYsQOkvz?g@Mpzics4cZGd|? z4e|=o>8Rga#X<6aNVW+D?sxQwIp*n$c=MkX?7iw^o1>#Q-zC^gY|k3DkTV23-_wYe z(JTv9Qb4HI)bjjA#1}~8P82@z1iVs%_ji@T`>i1nq4v^=RCXT1k^cZ6aRHO6pS!Fe zfH`iwBFO&$P40K)o)Pm^a>s{w{x6eqEWZ@Hhq;fhI%}LS3yZTxrcC8Am+^Tz#w>(x*YRR048&#Oiyrf&(Kxw7=%Z=#EJIS> zw;jA#Svw}DuJI7_^*zRN7<_Hw3mk6F8ea+Gc-!DOt5L|^wSOsQtWir}EobV|hO1+y zts6yFdigA@vsjAMw;naKMlXsOVxOo0t8t^4oa0Vh>R9ggiX8FaSiF;PN7OI$Yu{)? z_m;H`YxjF*3<++;1K0xXq3fbWxR>_!jJ1M6b5P{(A@rmlBFtcOr!(htR8egjnakOK&3OCu|JO2P+!GIpYCtbb! z<*&?)55k@pzYfPrm{L|2l_eoYpwN-%xHU=T2Fzgt~N{A>g00#tl@I(~Qf0I$)Xqij~D_h2bdYn#|Weu-@Qj$gXg4Z-DZ zGZ_l$eV;+M`*kCs{OGKnm<{@K=xKj|J~Z&3JpLC;eOY*v)}$dMXu;NyUvjMGln^z^ zEZXP5_wA%?Yx#4C{{VwE@V$X7)j?sfx@96~-&3;0snG|bJ08Cs1fQPY1%`8q1e+Nt zs~pH#6dpur70iOHp7p3di{$4zM(z(SaG8iEYu{e%`1 z@G97STtIeF{{WPeQZ5-*%ahs|;EKp`M&4_#m9;%1Z4a9`<~l{OM=O4`wcF}+T9WnI zU>N;3?+GPH2eyy~1bZv-75wY?5@4n#XjX<;3dombWmo>#Gkhfrr~n!RovBYdYH1tF zpE5Y4WBaR-T}a6KX3Z9_^x|R^p?c9MkPPy=} z$||1&QK(Q$PDlj3<4)GJ<(8zheKE841NR)Tm}tp5PDup{gB zNp@&tG6Ag;s6{+S&0mCP%2EbAq^KH{B=8RI+R^VBek<^%CmDrYsaT1UW+)JqrCS70 zk*Kc&z{IeJ^*G>31OD5DD%z5l=JoEk+_?c5q@fphil26pVY{8C}t56ux<^KRv8@UIOc+`Aj zj>9x?MzUFk{#NB{Dp)*`O*D0>DizRJWyi`RQo*D>)rRg1<1c_*8U8+s8l_Um4y>H4 zu&vo7md-V#e5%6@mCl;As)UWQLC&rS<-WCeV!2PvUT>ZKI5{_ztXrmwV5Kyfv9yvq z68%XK)ujbUS3H+7T$=C#I-&Owr z5k3M5X@3!TaW!C>^65)#xB|I>M$akYl8__M^O15eB7 zGwT|8IW`FQRm|husQ_x+1o~w=8)3bI7$_dLe<$C@CMV;6g%(*JGl3)!&4`v=z|1Jv z0{6b?l5p!5K@X@uhKyH`VV9?Dr44sdJKBX#$t72RR1VuZ16u$tz3iOjd}Hw7asKte zn}63ujSVZqc5QIxO2xx)1pXlro&O|dT$a_Q(1~HZhb{HYw;4xi= z`+j=)=kXVX__hlHhrr@x&s3?i6tgUYk{mcDiD2rcgD1O(L9Uehbg8ZM+~NV?>kU|| z%8{f(Df<;wRt4mB=*WlDYy=LySE*(!2-d!0QTuC9GPTWO=E8LIF)jSNEVB5^nmmp5 zW0M_-c4X?kjCUbWT?z(8cPe@S-qmsb-V4cSV-6KX{77>q8Q@NhA3eVaLiYN(PK?y4v4_bqBs&;`a=iACGl#-HiIrIF)AN^u%RL6Mpg>k$+Tz)GZ$FlO{&JP#Tr7G=mm+p5#>v$k#lPdOl+=O<#~3yW}<8XYKI?HuKBDVX^%yB}?Zv{p3U zi=^-_z+j}7Q>Ik|-(myoH^*9!;xq3(?-=V=S(=)0?$EaR;j$lraZ(+(^{aI3e%4j2 z&DXi#wc4oABk7K<8ncFLa*L4UIR~9!QB_MEpLrx`^(Zu}v9d{4{C3bJ{{T88U!Pau zKyp5Ws_(F*dOA7;kUJmbZ+Zu3-naaGO*0y*|OB>Mgd z-^4`3le9_mdg#@o*O@e|364OX0sSK9-=z>a-zQBG<5<3t*@87S9sYyTT z-Jm=lIzI?Wm!eyF?fOQ-ypm`t6Q%&2?1H_3Ah%(o+j~184@3MxASw@?G&#PR^E{xT z13hxmJ(;A45Hv#&Tp`%d(f9E#WTmTD6x@8fA_n^JC)!&`0UFTQBVK?3Se@u? zyEceZ@7Kh($OON?M~RT(yZjyn;}5GScl*fL0a!U5wm&2RtsiG!@-|NWK+SVfssoh{ z{yK54;S?7&0Bc6}{AmNNwg9JcHcA8U{sCgZ5?j&UyJ!KTeGvesAh~TA3ykaS($O@4 z13R4kzgobHGnUwqivglp$E9N6d;S#cfvqa&`rgOERI&wBMcKbz@Y@L$>%Fyu3ueon zsr6X5r3wz)?$(!Jlf53_{{X}3Pry|*Vy0q=79`i8Zu6`ll$@+u=DYdE(ylKxY%zuj z)2C4E@AT9S6Ryri$ONmNq>`bC9hCee;$~awEFDQ_=v(@|-4qO|>H3YlJadsJS9Mkl zM*jf5jVgdO`F(x6*RV+n3D$~{Kd(4{)Ll3B`<~fAsi59-Ja|UZzZ%YTNADVi{E4Mt zLDu?gf&+u-5IUWmo%{GAaZ}xuI$;Kb?^tU!LV*m_tvbX?L9e7L@z@uLeQDe}5!Isa z_bFhyBSenQM^eK;Xb_~51SZW=+$m~ZMadvFGpRJWeO=ww&dZSQ#`W}U;X@7CVVbOQ zF$!lu>OkI=!O`ppE1&`Gu)Erx+aDE{C=QJFXteLr`a7@lGt6hlEXLg*9NT!BD|YF)S@QTw zGePxg!tt}s9l2dnH3%X1fQB7+krLK@rJWnPng|f8Aw^{7WecKARG( z7UZjn0N~}to4n4jqOnp<=n{Gkst5oPv-uhtAbJBt>=UuDH)YgAU#UF%(i9Pqm%Bx! zV8oILDhWDb6zuD;9<(%c5AZ%DfT6f(U#mib>^-+Z_#pkj_1c0+C3Fse+3LrBy=eRr z6kyS>W^ll%*RQ)uM*Rj|fxR#XV}6GB)8Rs3EC7rguo~Ie05H)b?%5rP^arlHAA$$1 zhWMV@X3nlpv@?fn;M9L)NZo?${{V`B7yt*_NYFYgcc7>L0MOZlJbf#(Y=Qjiw!ro^ z??Cnd`v=g`-|}`;Mad??AhqlG(@ie{0vQNhleZf8=!Vvt{yh*#+5C>A5I!9#D))hv z5=#;X7{ft9O%d6MZl7ry1n*?_8v{qEE&QIo$aMxemlr+oiKRrAEpNno^vUYQo7o{( zVTcFOB=7hnot^vc!Rk)O{B1*3@^3qL$`tsh zsmh2aRC$Yipn~cP4UMnzps4_`KK}sn>b}^P1e(MaqU~Yp`usx5rFf!cRZv&*5dlCB zkF(U00N4yWdt#^C6R{|{aQ4rfKo%oFL1^C8A|S)CMb~E=Be!A|R58}b9XlPJ2I>Iy zrU@k2jv&O8w{R`z2iDX>w%mQcYKA*4ue)bpoddtP>;^yN315T6BP7a=JS>1GwTzOW zkXZLW;zv{19@`~>Dl|g?p-0brGNUULEuyMdL5N=4B!EhiN|FYF8Y|ae#HbAU4*g-k zCeQ$za@3H6vVN>!0#~vYKFA~p#)&!rof7{5^A!-JxX9FJn1+e3&L)MtGoE>!f4#@B zl0v?ZbM1}!Gko_UhpBedXUDMOvJz4? z47H%lattI<%OrNBgauili@eb|mKBeu)0JlWa${pAP=LYBHLGvq8ZuH&dyfF$(DRO> zI1WQKfU(I4{oOpQSxmGz*mBcDW(<^O5AVohuQS)JBZ1x<5l2}MX)9Zd%C+Q=AuIcZ z??(5oUzo78hI=-Yy(_FT{{X3{g@>9xTs(o2z}BB3e+5M?(=mzGG|1tU*>1B+W2(`9 z+8Lwm8DNtYE=+OCqdy2tsnXQ%_Xm41YUgJCJQ{G?mQ$@fj|k#RkkXnORP$)TnvPHj zTVLErWsAG@8w$%P45zpsbYr0)ACA&WwyF=>QVW5eWH_zqk&Fq62|VrZcG8e*%y}G# zFX8-CJ@r<4G%B1HMG^L*Xpv>7XX(azM3Y1$=^}&F2*Wb=R9zWjqj2G%fbD`0s_SRK!A&1$i9C{flU!*bKdaKauNWK#c$i-oX5PT>uMn-x7@s@7iWy=V6cBTiTEh zU$hUkk6yrN5Pu)yL3mN)lCbQ%63h8JCqt+W{I{jh*WjN={k{|^1~3#Xe}Fok+foPe zssU{RNY;S#NAa<>3Nj&qbvh02vY+6u;FTc$Hm5}XN%x_$K$l2s*PZF<1K1*<)KpVG zuxVeS0IbXoivU6Er686kYDfP7o$RP1WNYAdf(KytYVnU5hQ88BEBu{n{nNJhruFaF zvZML-q6>DVv$p69O4@Qlge*_~%ojkPTRQ4=NZ+6o9=`-YH9FhQ1p`J&_6%cXy^;3o zUe3wte;f34-|_63C^+F>fWeX&Z#Vo$!?J?IM@RnvA-}U=bcd|9vgA#$2 z*_gN?n|dHC594e!b-u@X(Fb0=AA|uVgecfjxRFW->+B+TBr5_7cLaa|9)^eqdjOI& zeiD_k+}Taa3iyQOJnK;ek?L10h#=mFJs9R|Qw1$2M%4cUGIQbEuX!1JbW0gaTl z(UpkMDgHY<8w;YujgR*yet`gfLD8W>HnsI9DkR$k1ZzyAU}*30v#>_N2eHui>MB!r zp$<8ULXR5i#2E=JLYUmB*)C5|3G7#AP3wKPvd$ZS5!ja>7~q$={`?fI_etP2E^ zFj7K-z<>h~tFy8W#`ZK$kNl8z`HHV*CamvrYtANvR?FUzvy#H1tY~`}SxPx#NqvFn z09dd-wls7Gx1zrZwm}AjvvM`HGu9bbHF%Uf>y`uIx*|p{`8wEYF`-rZpGpeq@7)Li zNf9aUwRQ~|+Y&=onzpA)-#(wwtPvl?cbSHp#c;GA)iNe9fh(*^%Daq~jlQ0XI_ceZ-&?q353`+NT@+Sg<@^3l;?G z%?)4OWi7pP^omVcCXx@`N8U*ckyn#d%qT2jV-^bPXbBe2quMm&fwJw-jmIlR{BSGm z)$M0wrnYa7>oV3eQLZ7L+|Wp?(Ic<>$L@?H3ml5hBX|}iWmZ}U{zIRkf|`Rz-K;LT zmOCxUxb!|b#wAFwl_9G9hb?H!ZbT9*M->->R6Hq;$WmHR@ZRI%^O7EeMEI~jHkG5XqzHoAl3c3H>@xX zo0D^^TAQOt)!~$PQ_zOl8_{*&zxOIg00XxE2;crP`kTD}08t>$9?xD7Qd;G{r$9IS zF&pfv00l>)zWtIv8Xyt*_#^Ib5B$1=t)E1Zwk_*h*!%&nf|`wYS@%9r7B0Ry_5ml~ z`-TVLDtE87xn2wd05^H(0e!)fK(LcUsQexNSE(crNjfdEyE`M<_-J??P=GoG3%%=S zxCcSKf0tHe>(x%%{JMfya!F$5%tv&7kfXyWFA&$-10H}7!~wSc55K@)XRgO>jgc~- zL9Rz5-C;(`u13XacCKDM028xx3Qzu^C=3}-@}qxup|Avc==#8vk}Ype^@Su^H=Rp; zzyf<914L{UD!K)A_$)@f58#&g8r4Q?hv8q;LIyMGJ2MsN>OdLr)2bynJIu~HZ>a!F?D7vKKcEH$#hQj|dqT90AA2$VAtd2fyX02{|yaiN-XBB!>2fyNBIHI%Ac-q`uR4#E`}D5 zAC^Ha+CREhY6_+Di2<(@l9gKmws^UX+u)n;9f0>vY47! zJZ)yRn9f|QLZw>j=GB`s$rN?tjREY;)5>8THQ2EB3F;_fCTyie#VK7g9D3^(g~k&m zkw-EpQ!n=+kXZigaeX^f%+X2o8nd~L<%cD&LFZpiP*tcKWtpSUZlG{ZcijuDjcYWs z`8pJtqpedNjGpL)lEGHP3rLS9D%Gm>rTQ)Vd)2DiMv3~|G~+f{RYlp2FW$aUnKc82*l0s` zX%S8Uoj2XIC8_U6xvvPyy82b!id`Pz((@WyUc5MO_iL(fpC7{Ad6O z(vh!2(I0|@YfTxc$JwEZwzP3}cijHb_tfr)6_BwfT0efaz>-^FcGwHqLV_E6{vYY@ z@`fdWIzVeGt805@?5?9jMSk7-8{V|q+1F$5KobH8EMfs*yVFdm*6?6Y8xG}&RW7|h zi9G@LFS2xYeF30$eVfRaM_Endcb^7k`ni`s!Hr-=-w!f(NbZ@zjuXJ{d^`&0GpWW7d%N1qdvE8~l1Y z0Bc+OPvmw0H(~~W_!vn!HyT2Ldb=rZ-*^LTqz#kkDFbI+gD}|Nw)B5L2%%e#Kg&dt z0X1>c&EwLngvh{wAqop^dXhmqVXxtK6!j-Wjr%JWBH^H+DFB8A^Dg6qH)D(7%wu3w z4@1)cb?kxnAIQ);(DlB%P+Qu8sUTaXdHF$@?92*2_0*6EI`!9MS|eoalkcv^zTgP> zMFg{h)7At~33}Iu;tj4%l$CVR&@9^j0MrFQ#ILeXt>^$WG)UjW0NV2}4#COR{qN2U z$9cBu$FK|AsRU?fYY$UrAb7J{ikN{_U@Qn#lm;yk0 zTQf##R4|U4@PAh)#Q4T>sae9~qq9;B-0*Hn%|I8(jA;$JB7wYt~Ag~jLBDmj&WKBcy2`u^EDK;JZ2OIh@Jlc zZ(&4+6_FGfCP#;}&I)yYqE+LGnBe$QEJ!5{Am zI9CwKI{*aAvUJjDDwUQR)~R? z%E6w&&^*5!EeSrX7_LMBY}zCf^pd@&58BKNBR5a3CEA1{Ga+N~sE|d^Eh9ZkW2w#I zkI&$iCwSv=HE@5n;y3PyL+f#X(IWNN+8zK@uvAi|fu+5CxQ@qSBnyXx#QYO0^d9OyD>GS(>p((+4$O$U&<9@4fiajhLs#C_;a%|N$0$uT3egS!08pvj znS_zLxC!~v`iSlIq1A%^4$A&METwx~?Rvm=ib=6{t@uU<8y7(9dZ_9~khI82BU=mf z2myT`Ub=e@zfVQVfPG-Z149{qM@8yQx=Y*^B-lRx0Lw$OL;2B7j-Z_%&#j3^XuCBU z22jDlwQHy5JX}E}>eW810QWO**Z=@bVS62bKxWuo5wB$>oIRj%=k!nt?#*v!ex?BE z1Eqb00f*=Oy#u}M5DHWQVtkAzZ_IqSivh=bRTMW+5ZZ-$54+iN>Y8QhK^r4yeuyfz z)31^IL%F-2XW7V)P7=#D`$AZ;1TDIyNBIG!S-R~10OU)8#PvFGKz9H;)ARWBiKS$a z3u(?id_9VD)PepU(~v8&m)ciytvEYHtAv5)kNg&RupfzU_w3W*pqXo5qy*z^hB zm3p_J6c$MUl60pWqA)PPdD=eCq2oq%+K$~=ASD!n2XYoNHVbD? zfQ}y|NMx&J<17QZ!z(ACKGHe@LD4;c_E$_){0bBtrGm^)Fpe7Yk<_xQBSt=&l@9%- zSkwevkV9-}=}1z3AXXT)@}w{z+7|c@1(~^ZYgVf*sTfBg71T`KhL}cVguF_EHtg~= zs)(VzkGFN^O(W8p*CS4GG>0sE{6vQ196t@lk)0o^$1HC_K&O%!FJ^i#CrH;8lO8 ze_qLVk)fwG`u5yb!{ecql0i<`d-oz$Gt@|?c1+Af(niQpHPFyDxj&yMvVxi%tCt+O z{^OvZ7I?a?p9fRnnyp6G6CL#J$3)SoH9G|(lO1jlvPdh}dk6~GR4D`YjX_3J7Fxk2 zi9Ct5X;&@AE}(`1>MQ3Gcf zL0H8iBy7qD^og)M!@lv`#FVzVI_n#*Bg^;+&?Gd`MwXwnpiX0Put%zgOzgj=nlqEs+k&V2CqI^c5WZ5i;0{5x;i-0KvA9B`NnbM?Wom+Vaj3Ys6kI zp+ghMJpTaBF=rh9IKt#H)^WINa6Cr!Y~Eg3yV0pmn;Q{cmbT}PCwSl=*@i)VG}|nL z3VD7Z39ms?DtC^J%tDtrnB-MCJzNd~Iynh!)}edJJc8uOCNqs=EJGcPwHj6-k~1z| zx-`iJS^6lAVY2A4*ATg7p)XpIQ2n(%;gqr~TF?Q%yWTkA{YSi)$hmjT2bJhcpS#I; zrx4_Kc;*G;mI&j5rF2A^k}Ms&Jxem$ibo?|)?kPtSbFq$6a=Eh)Xq;A6r;a8Gv^uD zg}c*S^l!sOc}J1TwAg88HovChuRz^ib#OnvvbjjRpzdP?IRmu7b&#<3Z>cR&Z%@o; z!Cq-{#XduD(wXB{b(KQ2i|SNn-h%#$Bl1Mm%jSJ5YB5>w(3>k zJ&Rn{O2DUw7G$|2j`2j&Dl}(b_mN|CbyJ{rb=yjI-;xsi1pv|}Y--!|jc!ka@~CV~ zXTsY(rYE#95{FH$$3XM|e~=&meGbSyl^?`&^)Lt_{*}%ph`yDgvjgmAD^u!ed*-+(a#oF+{ep<&j$fD|1l8a;vUpa274cGpnF6b(cZPP+H!0lyjLE56uFp&JDM0MW`% z;1StKA()mQ;#={v>=E#yFc12Fkt(2kHc)8nE7Gu470SQ-h{R%ZTPoQ6hj~)}N9m9L~=Yu=2xlBIyG6@YkUi9)d&{{SWGdobAF-My;x z**^*<7eeggQUmVxfSN0Q!HUFeHKZ#duu-)H??3`ofGkKJi6cxxh?$ROYZ|-iABQ*^ zG`3FL_eeowq8vFp_6Y1tfxVJFefu8CB|%ce41;lMM#2d)3gfALGN|?kWefoB8%o8G zU6RMS*ZYr35drmU8)f^A^(=s`V7#J3Adz(&_CQd5+C70Pt_buuzQvBthrraI^o}+5 zC)3^-04=G0F2(n~4@h$B`7-;gG-?rB{?%}mqX>$Hm3C(B;1(bcGx&m}lU8ji?-R>Co67v3@L4=5W0mAN z4?FUnKZ)lsmbv0sC(5uATaMgzjXY?tHOzD^OXz(lZp5=saK?|GOOkbi zA$C^&t$1jUF)U0R~Ecu zAN1{%Y?f@DubuCBg261@>%to^obMg+zYuZ`0rL&Oad_-!nmKF98U~IUet)@4 zoVVt?&Up!FSH{FS&O;9Ls1%AR8wFmjANS5u2>aN#`!i}oDoE)hr5ah412i2#w^V>o{` z4a3{>7Iok+kW2^6PYU9E=ON^Lw;H>iUuw{H=bPiQ^owcc?#Yhk1n&x z(xq;~YZz3-w2dpwHqpnG$N&_>*bc<)y)Xksu$bwXg))FkFrg*ik0%x_4L(pvCEcCc zjzPW4KQ@T}0LrqqR&fHc3J`DD_FbHl=|TJ^hRGv;Ybe+|a_R}x4|t+YQZ;wvA+@n? zcC=Hzw)kO13#+u0}LDkK6&b%2$U^|^g}?|X~;%YR8hu_FhM zsqDm+J-T*H5ES|+@J`4(>XulIB8Jj1}_(|XiKK9aEQv>W@1gC@7xyD`@N0#B`m?fLjt!zP=L7bUtKaC3&pgdEI2z@Rwf6^$Au`T3FJAi zDdlTw=8JY|6490qS4<5%|_Q;@VQ zaTen*OBD`Y%hkVA6%dp)O0qnyVkl#kQWuuWDwyR(g|>@|oXzxa%u8W9d7sQEd~M*L z9(bk*=BmGBzx2vUOkomPK OpD1M{07xEZSpV5*ZhS)k literal 0 HcmV?d00001 diff --git a/apps/daisy/screenshot_thering3.jpg b/apps/daisy/screenshot_thering3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da8f140c0b36dbcc3c09c9fcc163a02bd1cfdc4d GIT binary patch literal 19580 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 Date: Tue, 22 Feb 2022 11:44:50 +0100 Subject: [PATCH 094/199] Update 7x7dotsclock.settings.js Color Settings of Minutes and Seconds --- apps/7x7dotsclock/7x7dotsclock.settings.js | 51 ++++++++++++++++------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.settings.js b/apps/7x7dotsclock/7x7dotsclock.settings.js index c2b5d6c2b..fe9fbc022 100644 --- a/apps/7x7dotsclock/7x7dotsclock.settings.js +++ b/apps/7x7dotsclock/7x7dotsclock.settings.js @@ -1,21 +1,8 @@ (function(back) { -let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {}); +let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: "",ColorMinutes: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {}); -function showMainMenu() { - const mainMenu = { - "": {"title": "7x7 Dots Clock Settings"}, - "< Back": ()=>load(), - "swipe-up": ()=>showSelAppMenu("swupApp"), - "swipe-down": ()=>showSelAppMenu("swdownApp"), - "swipe-left": ()=>showSelAppMenu("swleftApp"), - "swipe-right": ()=>showSelAppMenu("swrightApp") - - }; - - E.showMenu(mainMenu); -} function setSetting(key,value) { print("call " + key + " = " + value); @@ -26,6 +13,42 @@ function setSetting(key,value) { } + // Helper method which uses int-based menu item for set of string values + function stringItems(key, startvalue, values) { + return { + value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), + format: v => values[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + setSetting(key,values[v]); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values) { + return stringItems(name,settings[name], values); + } + +function showMainMenu() { + const mainMenu = { + "": {"title": "7x7 Dots Clock Settings"}, + "< Back": ()=>load(), + "Minutes": stringInSettings("ColorMinutes", ["blue","pink","green"]), + "swipe-up": ()=>showSelAppMenu("swupApp"), + "swipe-down": ()=>showSelAppMenu("swdownApp"), + "swipe-left": ()=>showSelAppMenu("swleftApp"), + "swipe-right": ()=>showSelAppMenu("swrightApp") + + }; + + E.showMenu(mainMenu); +} + + function showSelAppMenu(key) { var Apps = require("Storage").list(/\.info$/) .map(app => {var a=storage.readJSON(app, 1);return ( From 3b3c01677abb0584a63cb6937a695b5e8f4b084b Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Tue, 22 Feb 2022 11:46:08 +0100 Subject: [PATCH 095/199] Update 7x7dotsclock.app.js Color Settings of Minutes and Seconds --- apps/7x7dotsclock/7x7dotsclock.app.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index c6daee542..ce2b3011d 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -5,7 +5,7 @@ by Peter Kuppelwieser */ -let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {}); +let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: "", ColorMinutes: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {}); // position on screen var Xs = 0, Ys = 30,Xe = 175, Ye=175; @@ -13,8 +13,19 @@ var Xs = 0, Ys = 30,Xe = 175, Ye=175; var SegH = (Ye-Ys)/2,SegW = (Xe-Xs)/2; var Dx = SegW/14, Dy = SegH/16; - -const mColor = [0.3,0.3,1]; +switch(ColorMinutes) { + case "blue": + var mColor = [0.3,0.3,1]; + break; + case "pink": + var mColor = [1,0.3,1]; + break; + case "green": + var mColor = [0.3,1,0.3]; + break; + default: + var mColor = [0.3,0.3,1]; +} const bColor = [0.3,0.3,0.3]; const Font = [ @@ -141,9 +152,9 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { for (let j = 1; j < 8; j++) { if (Font[Num][j-1][i-1] == 1) { if (Color == "fg") { - g.setColor(g.theme.fg); + g.setColor(mColor[0],mColor[1],mColor[2]); } else { - g.setColor(g.theme.fgH); + g.setColor(g.theme.fg); } g.fillCircle(x1+(i-1)*(x2-x1)/7,y1+(j-1)*(y2-y1)/7,Size); } @@ -153,7 +164,7 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { function ShowSecons() { - g.setColor(g.theme.bgH); + g.setColor(g.theme.fg); g.fillRect((Xe-Xs) / 2 - 14 + Xs -3, (Ye-Ys) / 2 - 7 + Ys -3, (Xe-Xs) / 2 + 14 + Xs +1, @@ -164,13 +175,13 @@ function ShowSecons() { (Ye-Ys) / 2 - 7 + Ys , (Xe-Xs) / 2 + Xs -1, (Ye-Ys) / 2 + 7 + Ys, - ds,"",1); + ds,"fg",1); drawSSeg( (Xe-Xs) / 2 + Xs +1, (Ye-Ys) / 2 - 7 + Ys, (Xe-Xs) / 2 + 14 + Xs +1, (Ye-Ys) / 2 + 7 + Ys, - es,"",1); + es,"fg",1); } From f6a2a03448f2d68fd6c533e2d8a126fb7d49f916 Mon Sep 17 00:00:00 2001 From: Marco H Date: Tue, 22 Feb 2022 15:15:18 +0100 Subject: [PATCH 096/199] New color option: foreground --- apps/circlesclock/app.js | 3 +++ apps/circlesclock/settings.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 903c7bdb2..ba7ab474e 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -248,6 +248,9 @@ function getGradientColor(color, percent) { const colorList = [ '#00FF00', '#80FF00', '#FFFF00', '#FF8000', '#FF0000' ]; + if (color == "fg") { + color = colorFg; + } if (color == "green-red") { const colorIndex = Math.round(colorList.length * percent); return colorList[Math.min(colorIndex, colorList.length) - 1] || "#00ff00"; diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index bec539376..0b9e94aca 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -14,8 +14,10 @@ const valuesCircleTypes = ["empty", "steps", "stepsDist", "hr", "battery", "weather", "sunprogress", "temperature", "pressure", "altitude"]; const namesCircleTypes = ["empty", "steps", "distance", "heart", "battery", "weather", "sun", "temperature", "pressure", "altitude"]; - const valuesColors = ["", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", "#00ffff", "#fff", "#000", "green-red", "red-green"]; - const namesColors = ["default", "red", "green", "blue", "yellow", "magenta", "cyan", "white", "black", "green->red", "red->green"]; + const valuesColors = ["", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", + "#00ffff", "#fff", "#000", "green-red", "red-green", "fg"]; + const namesColors = ["default", "red", "green", "blue", "yellow", "magenta", + "cyan", "white", "black", "green->red", "red->green", "foreground"]; const weatherData = ["empty", "humidity", "wind"]; From 9977460d1f41f15058fba03359e6099f560bb6f0 Mon Sep 17 00:00:00 2001 From: Marco H Date: Tue, 22 Feb 2022 15:16:40 +0100 Subject: [PATCH 097/199] Draw the circles a little bit delayed so we decrease the blocking time --- apps/circlesclock/app.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index ba7ab474e..1e713c2e6 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -138,10 +138,19 @@ function draw() { g.drawString(locale.date(new Date()), w / 2, h2); g.drawString(locale.dow(new Date()), w / 2, h2 + dowOffset); - drawCircle(1); - drawCircle(2); - drawCircle(3); - if (circleCount >= 4) drawCircle(4); + // draw the circles a little bit delayed so we decrease the blocking time + setTimeout(function() { + drawCircle(1); + }, 1); + setTimeout(function() { + drawCircle(2); + }, 1); + setTimeout(function() { + drawCircle(3); + }, 1); + setTimeout(function() { + if (circleCount >= 4) drawCircle(4); + }, 1); } function drawCircle(index) { From 0eb5cd9292622a4057b4a87c7cd8a121625aa2da Mon Sep 17 00:00:00 2001 From: Marco H Date: Tue, 22 Feb 2022 15:17:09 +0100 Subject: [PATCH 098/199] Move icons to the functions which use them to reduce memory usage --- apps/circlesclock/app.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 1e713c2e6..d5df2fe44 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -3,23 +3,8 @@ const storage = require("Storage"); const SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); const shoesIcon = atob("EBCBAAAACAAcAB4AHgAeABwwADgGeAZ4AHgAMAAAAHAAIAAA"); -const heartIcon = atob("EBCBAAAAAAAeeD/8P/x//n/+P/w//B/4D/AH4APAAYAAAAAA"); -const powerIcon = atob("EBCBAAAAA8ADwA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4AAA"); const temperatureIcon = atob("EBCBAAAAAYADwAJAAkADwAPAA8ADwAfgB+AH4AfgA8ABgAAA"); -const weatherCloudy = atob("EBCBAAAAAAAAAAfgD/Af8H/4//7///////9//z/+AAAAAAAA"); -const weatherSunny = atob("EBCBAAAAAYAQCBAIA8AH4A/wb/YP8A/gB+ARiBAIAYABgAAA"); -const weatherMoon = atob("EBCBAAAAAYAP8B/4P/w//D/8f/5//j/8P/w//B/4D/ABgAAA"); -const weatherPartlyCloudy = atob("EBCBAAAAAAAYQAMAD8AIQBhoW+AOYBwwOBBgHGAGP/wf+AAA"); -const weatherRainy = atob("EBCBAAAAAYAH4AwwOBBgGEAOQAJBgjPOEkgGYAZgA8ABgAAA"); -const weatherPartlyRainy = atob("EBCBAAAAEEAQAAeADMAYaFvoTmAMMDgQIBxhhiGGG9wDwAGA"); -const weatherSnowy = atob("EBCBAAAAAAADwAGAEYg73C50BCAEIC50O9wRiAGAA8AAAAAA"); -const weatherFoggy = atob("EBCBAAAAAAADwAZgDDA4EGAcQAZAAgAAf74AAAAAd/4AAAAA"); -const weatherStormy = atob("EBCBAAAAAYAH4AwwOBBgGEAOQMJAgjmOGcgAgACAAAAAAAAA"); - -const sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA"); -const sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA"); - Graphics.prototype.setFontRobotoRegular50NumericOnly = function(scale) { // Actual height 39 (40 - 2) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAB8AAAAAAAfAAAAAAAPwAAAAAAB8AAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA4AAAAAAB+AAAAAAD/gAAAAAD/4AAAAAH/4AAAAAP/wAAAAAP/gAAAAAf/gAAAAAf/AAAAAA/+AAAAAB/+AAAAAB/8AAAAAD/4AAAAAH/4AAAAAD/wAAAAAA/wAAAAAAPgAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wAAAB////gAAA////8AAA/////gAAP////8AAH8AAA/gAB8AAAD4AA+AAAAfAAPAAAADwADwAAAA8AA8AAAAPAAPAAAADwADwAAAA8AA8AAAAPAAPgAAAHwAB8AAAD4AAfwAAD+AAD/////AAA/////wAAH////4AAAf///4AAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAPgAAAAAADwAAAAAAB8AAAAAAAfAAAAAAAHgAAAAAAD4AAAAAAA+AAAAAAAPAAAAAAAH/////wAB/////8AA//////AAP/////wAD/////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAfgAADwAAP4AAB8AAH+AAA/AAD/gAAfwAB/AAAf8AAfAAAP/AAPgAAH7wAD4AAD88AA8AAB+PAAPAAA/DwADwAAfg8AA8AAPwPAAPAAH4DwADwAH8A8AA+AD+APAAPwB/ADwAB/D/gA8AAf//gAPAAD//wADwAAf/wAA8AAD/4AAPAAAHwAADwAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAADgAAAHwAA+AAAD8AAP4AAB/AAD/AAA/wAA/wAAf4AAD+AAHwAAAPgAD4APAB8AA+ADwAPAAPAA8ADwADwAPAA8AA8ADwAPAAPAA8ADwADwAfAA8AA8AH4APAAPgD+AHwAB8B/wD4AAf7/+B+AAD//v//AAA//x//wAAD/4P/4AAAf8B/4AAAAYAH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAHwAAAAAAH8AAAAAAD/AAAAAAD/wAAAAAD/8AAAAAB/vAAAAAB/jwAAAAA/g8AAAAA/wPAAAAAfwDwAAAAf4A8AAAAf4APAAAAP8ADwAAAP8AA8AAAH8AAPAAAD/////8AA//////AAP/////wAD/////8AA//////AAAAAAPAAAAAAADwAAAAAAA8AAAAAAAPAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAB/APwAAH//wD+AAD//8A/wAA///AH+AAP//wAPgAD/B4AB8AA8A+AAfAAPAPAADwADwDwAA8AA8A8AAPAAPAPAADwADwD4AA8AA8A+AAPAAPAPwAHwADwD8AD4AA8AfwD+AAPAH///AADwA///wAA8AH//4AAPAAf/4AAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAD//+AAAAD///4AAAD////AAAB////4AAA/78D/AAAfw8AH4AAPweAA+AAD4PgAHwAB8DwAA8AAfA8AAPAAHgPAADwAD4DwAA8AA+A8AAPAAPAPgAHwADwD4AB8AA8AfgA+AAPAH+B/gAAAA///wAAAAH//4AAAAA//8AAAAAH/8AAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAA8AAAAAAAPAAAAAAADwAAAAAAA8AAAABAAPAAAABwADwAAAB8AA8AAAB/AAPAAAB/wADwAAD/8AA8AAD/8AAPAAD/4AADwAD/4AAA8AD/4AAAPAH/wAAADwH/wAAAA8H/wAAAAPH/wAAAAD3/gAAAAA//gAAAAAP/gAAAAAD/gAAAAAA/AAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwA/4AAAH/Af/AAAH/8P/4AAD//n//AAA//7//4AAfx/+A+AAHwD+AHwAD4AfgB8AA8AHwAPAAPAA8ADwADwAPAA8AA8ADwAPAAPAA8ADwADwAfAA8AA+AH4AfAAHwD+AHwAB/D/4D4AAP/+/n+AAD//n//AAAf/w//gAAB/wH/wAAAHwA/4AAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAAAAAD/8AAAAAD//wAAAAB//+AAAAA///wAAAAf4H+APAAH4AfgDwAD8AB8A8AA+AAfAPAAPAADwDwADwAA8B8AA8AAPAfAAPAADwHgADwAA8D4AA+AAeB+AAHwAHg/AAB+ADwfgAAP8D4/4AAD////8AAAf///8AAAB///+AAAAP//+AAAAAP/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAOAAAB8AAHwAAAfgAD8AAAH4AA/AAAB8AAHwAAAOAAA4AAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("DRUcHBwcHBwcHBwcDA=="), 50+(scale<<8)+(1<<16)); @@ -337,6 +322,8 @@ function drawStepsDistance(w) { function drawHeartRate(w) { if (!w) w = getCircleXPosition("hr"); + const heartIcon = atob("EBCBAAAAAAAeeD/8P/x//n/+P/w//B/4D/AH4APAAYAAAAAA"); + drawCircleBackground(w); const color = getCircleColor("hr"); @@ -361,6 +348,8 @@ function drawBattery(w) { if (!w) w = getCircleXPosition("battery"); const battery = E.getBattery(); + const powerIcon = atob("EBCBAAAAA8ADwA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4AAA"); + drawCircleBackground(w); let color = getCircleColor("battery"); @@ -438,6 +427,10 @@ function drawSunProgress(w) { if (!w) w = getCircleXPosition("sunprogress"); const percent = getSunProgress(); + // sunset icons: + const sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA"); + const sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA"); + drawCircleBackground(w); const color = getCircleColor("sunprogress"); @@ -571,6 +564,18 @@ function windAsBeaufort(windInKmh) { */ function getWeatherIconByCode(code) { const codeGroup = Math.round(code / 100); + + // weather icons: + const weatherCloudy = atob("EBCBAAAAAAAAAAfgD/Af8H/4//7///////9//z/+AAAAAAAA"); + const weatherSunny = atob("EBCBAAAAAYAQCBAIA8AH4A/wb/YP8A/gB+ARiBAIAYABgAAA"); + const weatherMoon = atob("EBCBAAAAAYAP8B/4P/w//D/8f/5//j/8P/w//B/4D/ABgAAA"); + const weatherPartlyCloudy = atob("EBCBAAAAAAAYQAMAD8AIQBhoW+AOYBwwOBBgHGAGP/wf+AAA"); + const weatherRainy = atob("EBCBAAAAAYAH4AwwOBBgGEAOQAJBgjPOEkgGYAZgA8ABgAAA"); + const weatherPartlyRainy = atob("EBCBAAAAEEAQAAeADMAYaFvoTmAMMDgQIBxhhiGGG9wDwAGA"); + const weatherSnowy = atob("EBCBAAAAAAADwAGAEYg73C50BCAEIC50O9wRiAGAA8AAAAAA"); + const weatherFoggy = atob("EBCBAAAAAAADwAZgDDA4EGAcQAZAAgAAf74AAAAAd/4AAAAA"); + const weatherStormy = atob("EBCBAAAAAYAH4AwwOBBgGEAOQMJAgjmOGcgAgACAAAAAAAAA"); + switch (codeGroup) { case 2: return weatherStormy; From e16cbf73b550d846921f04df8a6bd79415c48a41 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 15:37:37 +0100 Subject: [PATCH 099/199] Create app.js --- apps/smclock/app.js | 108 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 apps/smclock/app.js diff --git a/apps/smclock/app.js b/apps/smclock/app.js new file mode 100644 index 000000000..6aff72a46 --- /dev/null +++ b/apps/smclock/app.js @@ -0,0 +1,108 @@ +const background = { + width : 176, height : 176, bpp : 3, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/4A/AH4ACUb8H9MkyVJAThB/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INP/AH4A/AAX8Yz4Afn5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INI=")) +}; + +const weekday = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; +var level = -1; + +function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + +function d02(value) { + return ('0' + value).substr(-2); +} + +function pollBattery() { + level = E.getBattery(); + return level; +} + +function getBatteryColor(level) { + var color; + if (level < 0) { + level = pollBattery(); + } + if(level>80) { + color = [0,0,1]; + } else if(level>60) { + color = [0,1,1]; + } else if(level>40) { + color = [0,1,0]; + } else if(level>20) { + color = [1,1,0]; + } else { + color = [1,0,0]; + } + return color; +} + +function draw() { + g.drawImage(background); + + const color = getBatteryColor(); + const bat = d02(E.getBattery()) + "%"; + const d = new Date(); + const day = d.getDate(); + const month = (d.getMonth() + 1); + const week = d02(ISO8601_week_no(d)); + const date1 = d02(day) + "/" + d02(month); + const date2 = weekday[d.getDay()] + " " + d02(week); + const h = d.getHours(); + const m = d.getMinutes(); + const time = d02(h) + ":" + d02(m); + + g.reset(); + + g.setColor(0, 0, 0); + g.setFont("Vector", 20); + g.drawString(date1, 105, 20, false); + g.setFont("Vector", 16); + g.drawString(date2, 105, 55, false); + + g.setColor(1, 1, 1); + g.setFont("Vector", 60); + g.drawString(time, 10, 108, false); + + g.setColor(1, 1, 1); + g.setFont("Vector", 16); + g.drawString("Bat:", 12, 22, false); + g.setColor(color[0], color[1], color[2]); + g.drawString(bat, 52, 22, false); +} + +g.clear(); + +pollBattery(); +draw(); + +var batInterval = setInterval(pollBattery, 60000); +var drawInterval = setInterval(draw, 10000); + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (batInterval) clearInterval(batInterval); + batInterval = undefined; + if (drawInterval) clearInterval(drawInterval); + drawInterval = undefined; + if (on) { + batInterval = setInterval(pollBattery, 60000); + drawInterval = setInterval(draw, 10000); + + pollBattery(); + draw(); // draw immediately + } +}); + +// Show launcher when middle button pressed +Bangle.setUI("clock"); From c9616d4233029406342f28312a494ba202f51a23 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 15:41:52 +0100 Subject: [PATCH 100/199] Create app-icon.js --- apps/smclock/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/smclock/app-icon.js diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js new file mode 100644 index 000000000..497389173 --- /dev/null +++ b/apps/smclock/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("2GwwkB/4A/AH4Aub1UP+93AFJX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X3/4A/AH4Avf8IAzK/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/A")) From 99c694c8e1cd193c7e3bccc422f660d5c7d529f4 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 15:43:28 +0100 Subject: [PATCH 101/199] Create ChangeLog --- apps/smclock/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/smclock/ChangeLog diff --git a/apps/smclock/ChangeLog b/apps/smclock/ChangeLog new file mode 100644 index 000000000..b029d805d --- /dev/null +++ b/apps/smclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: Initial version +0.02: Add battery level From 952f438c54aa9611b5f2a579293ffea4ba131812 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 15:55:20 +0100 Subject: [PATCH 102/199] Create metadata.json --- apps/smclock/metadata.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/smclock/metadata.json diff --git a/apps/smclock/metadata.json b/apps/smclock/metadata.json new file mode 100644 index 000000000..4c558f504 --- /dev/null +++ b/apps/smclock/metadata.json @@ -0,0 +1,13 @@ +{ + "id":"smclock", + "name":"Monogram Watch Face", + "shortName":"MonoClock", + "icon":"app.png", + "version":"0.02", + "description": "A simple watchface based on my stylised monogram.", + "tags":"clock", + "storage": [ + {"name":"smclock.app.js","url":"app.js"}, + {"name":"smclock.img","url":"app-icon.js","evaluate":true} + ] +} From 3b1a3ef801899e50671c73df172d8ce24e2b5245 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 15:58:12 +0100 Subject: [PATCH 103/199] Update metadata.json --- apps/smclock/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/smclock/metadata.json b/apps/smclock/metadata.json index 4c558f504..0b6f1613f 100644 --- a/apps/smclock/metadata.json +++ b/apps/smclock/metadata.json @@ -6,6 +6,7 @@ "version":"0.02", "description": "A simple watchface based on my stylised monogram.", "tags":"clock", + "readme":"README.md", "storage": [ {"name":"smclock.app.js","url":"app.js"}, {"name":"smclock.img","url":"app-icon.js","evaluate":true} From 9f5ac58edd7d152e637eaea3670c9223cf595316 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:00:27 +0100 Subject: [PATCH 104/199] Create README.md --- apps/smclock/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/smclock/README.md diff --git a/apps/smclock/README.md b/apps/smclock/README.md new file mode 100644 index 000000000..7b5613147 --- /dev/null +++ b/apps/smclock/README.md @@ -0,0 +1,5 @@ +# Monogram Watch Face + +Just a simple watch face for the Banglejs2. + +It shows battery level in the upper left corner, date information in the upper right, and time information in the bottom. From 762c375ab3569c960aba6e7fcc084b7280757346 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:02:20 +0100 Subject: [PATCH 105/199] Add app icon --- apps/smclock/app.png | Bin 0 -> 6033 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/smclock/app.png diff --git a/apps/smclock/app.png b/apps/smclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..49c87c39dfba2763c4b2ee301221ca5ef4a93342 GIT binary patch literal 6033 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 Date: Tue, 22 Feb 2022 16:17:14 +0100 Subject: [PATCH 106/199] Add supports and emulator entries --- apps/smclock/metadata.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/smclock/metadata.json b/apps/smclock/metadata.json index 0b6f1613f..1783ca7bf 100644 --- a/apps/smclock/metadata.json +++ b/apps/smclock/metadata.json @@ -7,6 +7,8 @@ "description": "A simple watchface based on my stylised monogram.", "tags":"clock", "readme":"README.md", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, "storage": [ {"name":"smclock.app.js","url":"app.js"}, {"name":"smclock.img","url":"app-icon.js","evaluate":true} From f067ee03be1ed81d6ae679508261eafd8e5886b7 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:29:22 +0100 Subject: [PATCH 107/199] Update app-icon.js --- apps/smclock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js index 497389173..a7105c743 100644 --- a/apps/smclock/app-icon.js +++ b/apps/smclock/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("2GwwkB/4A/AH4Aub1UP+93AFJX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X3/4A/AH4Avf8IAzK/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/A")) +require("heatshrink").decompress(atob("2GwwkB/4A/AH4Aub1UP+93AFJX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X3/4A/AH4Avf8IAzK/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/A")) From c7459aa962946901f1d7e71571a53cd6eeb84333 Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:32:58 +0100 Subject: [PATCH 108/199] Update app-icon.js --- apps/smclock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js index a7105c743..13fdc3f20 100644 --- a/apps/smclock/app-icon.js +++ b/apps/smclock/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("2GwwkB/4A/AH4Aub1UP+93AFJX/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X/K/5X3/4A/AH4Avf8IAzK/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/4A/K/5X/AH5X/K/5X/AH5X/K/5X/AH5X/K/4A/K/5X/K/4A/K/5X/K/A")) +require("heatshrink").decompress(atob("mYAK+YLKERUCm93ABIX/C/4X/C/4X/C/4X/C/4XP+czACk/mAwKABUDC/4X/C/4X/C/4X/C/4X/C54A=")) From c5eda52a11d0ac8c3720c9d6206bf2e7e05961ef Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:37:09 +0100 Subject: [PATCH 109/199] Delete app.png --- apps/smclock/app.png | Bin 6033 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/smclock/app.png diff --git a/apps/smclock/app.png b/apps/smclock/app.png deleted file mode 100644 index 49c87c39dfba2763c4b2ee301221ca5ef4a93342..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6033 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 Date: Tue, 22 Feb 2022 16:37:33 +0100 Subject: [PATCH 110/199] Add files via upload --- apps/smclock/app.png | Bin 0 -> 7276 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/smclock/app.png diff --git a/apps/smclock/app.png b/apps/smclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..315eb0af1a6b0175b16e3b30339ea171407062b1 GIT binary patch literal 7276 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 h*ecx5mN+(bdW Date: Tue, 22 Feb 2022 16:43:04 +0100 Subject: [PATCH 112/199] Update app-icon.js --- apps/smclock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js index 13fdc3f20..3f8f8dd4e 100644 --- a/apps/smclock/app-icon.js +++ b/apps/smclock/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mYAK+YLKERUCm93ABIX/C/4X/C/4X/C/4X/C/4XP+czACk/mAwKABUDC/4X/C/4X/C/4X/C/4X/C54A=")) +require("heatshrink").decompress(atob("mYAJn4LKiIAJkd3ABI4KC34W/C34W/C34W/C393iIAJCxczACsxFxQAJicxLhQAJC34W/C34W/C34W/C34WM")) From f698db3612221bce1fd4ac4cb60bc3f7fad18e8f Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 16:46:41 +0100 Subject: [PATCH 113/199] Update app-icon.js --- apps/smclock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js index 3f8f8dd4e..ddcb3a64d 100644 --- a/apps/smclock/app-icon.js +++ b/apps/smclock/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mYAJn4LKiIAJkd3ABI4KC34W/C34W/C34W/C393iIAJCxczACsxFxQAJicxLhQAJC34W/C34W/C34W/C34WM")) +require("heatshrink").decompress(atob("l0uwkEmYAJn4LKiIAJkd3ABI8KC34W/C34W/C34W/C393iIAJCxczACsxFxQAJicxLhQAJC34W/C34W/C34W/C34WMA=")) From 889c265baf3a092b529670215884cb9e5a0f711c Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 17:01:55 +0100 Subject: [PATCH 114/199] Update app-icon.js --- apps/smclock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smclock/app-icon.js b/apps/smclock/app-icon.js index ddcb3a64d..91494a528 100644 --- a/apps/smclock/app-icon.js +++ b/apps/smclock/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("l0uwkEmYAJn4LKiIAJkd3ABI8KC34W/C34W/C34W/C393iIAJCxczACsxFxQAJicxLhQAJC34W/C34W/C34W/C34WMA=")) +require("heatshrink").decompress(atob("l0uwkEogAgm4VUod3ugsUu93FigABFyQsCFyQsDFyQsEFyAsFFyAsGFxwsHFxwsIu9yCpVCmQWIkckCxMhkcnFg8yiQsJiEBFw9zkMBFxEhgEAiYuGmUQgAuHFgIWBFwwsBBQQuGBQQuHFgQABFwosDFwwsDFw4KEFwosEFwosFFwgsFFwoKGFwYsGFwYsHEYUzEJAuBoIKHBYMiEJEAilEBRESFhAABLYNAFiUERQQsUFw4sPFwwsPFwosRFwgsRFwYsTFwQsTAANBFigABFigABoQtIFhYuKCpguIFhouICpwuGFh4uGCqAuEFiIuECqQuCFiYuCCqgAMA")) From 1f1cd95d5aac56e9923178db911c484be4ce1d8b Mon Sep 17 00:00:00 2001 From: smekras Date: Tue, 22 Feb 2022 17:02:53 +0100 Subject: [PATCH 115/199] Delete app.png --- apps/smclock/app.png | Bin 7276 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/smclock/app.png diff --git a/apps/smclock/app.png b/apps/smclock/app.png deleted file mode 100644 index 315eb0af1a6b0175b16e3b30339ea171407062b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7276 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 h*ecx5mN+(bdW Date: Tue, 22 Feb 2022 17:03:12 +0100 Subject: [PATCH 116/199] Add files via upload --- apps/smclock/app.png | Bin 0 -> 14182 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/smclock/app.png diff --git a/apps/smclock/app.png b/apps/smclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..16712c63b2d383a6e1bf506c9712812e1d2d98e9 GIT binary patch literal 14182 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 z Date: Tue, 22 Feb 2022 18:46:56 +0100 Subject: [PATCH 117/199] MatrixClock: Removed "wake LCD on face-up" Removed "wake LCD on face-up"-feature of MatrixClock: A watch-face should not set things like "wake LCD on face-up". If you want, that the LCD get activated when facing up, go to Settings > System > LCD > Wake on FaceUp. --- apps/matrixclock/matrixclock.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/matrixclock/matrixclock.js b/apps/matrixclock/matrixclock.js index e116280af..2e4ba1ac4 100644 --- a/apps/matrixclock/matrixclock.js +++ b/apps/matrixclock/matrixclock.js @@ -239,15 +239,6 @@ Bangle.on('lcdPower', (on) => { } }); -Bangle.on('faceUp',function(up){ - //console.log("faceUp: " + up + " LCD: " + Bangle.isLCDOn()); - if (up && !Bangle.isLCDOn()) { - //console.log("faceUp and LCD off"); - clearTimers(); - Bangle.setLCDPower(true); - } -}); - g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From b7b64f62048d11c2a9d0ca4641dd42ebca6480ef Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:50:07 +0100 Subject: [PATCH 118/199] Update ChangeLog --- apps/matrixclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/matrixclock/ChangeLog b/apps/matrixclock/ChangeLog index 23819e26c..52f705301 100644 --- a/apps/matrixclock/ChangeLog +++ b/apps/matrixclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial Release 0.02: Support for Bangle 2 0.03: Keep the date from being overwritten, use correct colour from theme for clearing +0.04: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up". From 2a87c5f23dfa1cf799b536ad93af0fa7dd92ae22 Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:50:34 +0100 Subject: [PATCH 119/199] Update metadata.json --- apps/matrixclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/matrixclock/metadata.json b/apps/matrixclock/metadata.json index 5e05698a5..122cee3a1 100644 --- a/apps/matrixclock/metadata.json +++ b/apps/matrixclock/metadata.json @@ -1,7 +1,7 @@ { "id": "matrixclock", "name": "Matrix Clock", - "version": "0.03", + "version": "0.04", "description": "inspired by The Matrix, a clock of the same style", "icon": "matrixclock.png", "screenshots": [{"url":"screenshot_matrix.png"}], From d0ad38085b271931ae800cf8dfe97df5471c8e8e Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:53:30 +0100 Subject: [PATCH 120/199] Crow-Clock: Removed "wake LCD on face-up" Removed "wake LCD on face-up"-feature of Crow-Clock: A watch-face should not set things like "wake LCD on face-up". If you want, that the LCD get activated when facing up, go to Settings > System > LCD > Wake on FaceUp. --- apps/crowclk/crow_clock.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/crowclk/crow_clock.js b/apps/crowclk/crow_clock.js index 97e5e61d9..d06369fa8 100644 --- a/apps/crowclk/crow_clock.js +++ b/apps/crowclk/crow_clock.js @@ -133,15 +133,6 @@ Bangle.on('lcdPower', (on) => { clearTimers(); } }); -Bangle.on('faceUp',function(up){ - //console.log("faceUp: " + up + " LCD: " + Bangle.isLCDOn()); - if (up && !Bangle.isLCDOn()) { - //console.log("faceUp and LCD off"); - clearTimers(); - Bangle.setLCDPower(true); - } -}); - g.clear(); From 6156715f8243b8871d285d38668d2b4fd9662865 Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:53:56 +0100 Subject: [PATCH 121/199] Update ChangeLog --- apps/crowclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/crowclk/ChangeLog b/apps/crowclk/ChangeLog index 5560f00bc..b7e18abe3 100644 --- a/apps/crowclk/ChangeLog +++ b/apps/crowclk/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up". From c1b9d08a290942bc48b83d4287e46d04414fb1cc Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:58:13 +0100 Subject: [PATCH 122/199] SlidingText-Clock: Removed "wake LCD on face-up" Removed "wake LCD on face-up"-feature of SlidingText-Clock: A watch-face should not set things like "wake LCD on face-up". If you want, that the LCD get activated when facing up, go to Settings > System > LCD > Wake on FaceUp. --- apps/slidingtext/slidingtext.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/slidingtext/slidingtext.js b/apps/slidingtext/slidingtext.js index 3be502cfe..7b56af1a1 100644 --- a/apps/slidingtext/slidingtext.js +++ b/apps/slidingtext/slidingtext.js @@ -623,15 +623,6 @@ Bangle.on('lcdPower', (on) => { } }); -Bangle.on('faceUp',function(up){ - //console.log("faceUp: " + up + " LCD: " + Bangle.isLCDOn()); - if (up && !Bangle.isLCDOn()) { - //console.log("faceUp and LCD off"); - clearTimers(); - Bangle.setLCDPower(true); - } -}); - g.clear(); load_settings(); Bangle.loadWidgets(); From 79f4f50b7e38b94facc27f91f74d803ce8695aa4 Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 18:59:46 +0100 Subject: [PATCH 123/199] Update metadata.json --- apps/crowclk/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/crowclk/metadata.json b/apps/crowclk/metadata.json index 365393e6c..752e30fb0 100644 --- a/apps/crowclk/metadata.json +++ b/apps/crowclk/metadata.json @@ -1,7 +1,7 @@ { "id": "crowclk", "name": "Crow Clock", - "version": "0.01", + "version": "0.02", "description": "A simple clock based on Bold Clock that has MST3K's Crow T. Robot for a face", "icon": "crow_clock.png", "screenshots": [{"url":"screenshot_crow.png"}], From 207dfd5b19aa70b2bfdf7c4e5b8ebb7aae1b4ed2 Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 19:00:34 +0100 Subject: [PATCH 124/199] Update ChangeLog --- apps/slidingtext/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/slidingtext/ChangeLog b/apps/slidingtext/ChangeLog index 3bd656cb0..0327ff387 100644 --- a/apps/slidingtext/ChangeLog +++ b/apps/slidingtext/ChangeLog @@ -5,3 +5,4 @@ 0.05: BUGFIX: pedometer widget interfered with the clock Font Alignment 0.06: Use Bangle.setUI for button/launcher handling 0.07: Support for Bangle.js 2 and themes +0.08: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up". From 2a158db57334adb18d00bc71059cd4b484178473 Mon Sep 17 00:00:00 2001 From: Benjamin_6848 <83084481+Benjamin-6848@users.noreply.github.com> Date: Tue, 22 Feb 2022 19:00:57 +0100 Subject: [PATCH 125/199] Update metadata.json --- apps/slidingtext/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/slidingtext/metadata.json b/apps/slidingtext/metadata.json index 0f380ec8f..2937a618b 100644 --- a/apps/slidingtext/metadata.json +++ b/apps/slidingtext/metadata.json @@ -1,7 +1,7 @@ { "id": "slidingtext", "name": "Sliding Clock", - "version": "0.07", + "version": "0.08", "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported", "icon": "slidingtext.png", "type": "clock", From e9fbbe3c58c93ff6421682a9bc4a098ba948bb29 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Tue, 22 Feb 2022 22:06:34 +0000 Subject: [PATCH 126/199] Daisy updates --- apps/daisy/app.js | 265 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 247 insertions(+), 18 deletions(-) diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 7e148381b..54743d945 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -1,5 +1,19 @@ +var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); +const storage = require('Storage'); +const locale = require("locale"); +const SETTINGS_FILE = "pastel.json"; // XXX +const LOCATION_FILE = "mylocation.json"; const h = g.getHeight(); const w = g.getWidth(); +let settings; +let location; + +// variable for controlling idle alert +let lastStep = getTime(); +let warned = 0; +let idle = false; +let IDLE_MINUTES = 26; + // palette for 0-40% const pal1 = new Uint16Array([g.theme.bg, g.toColor("#020"), g.toColor("#0f0"), g.toColor("#00f")]); // palette for 50-100% @@ -9,8 +23,8 @@ const infoHeight = 14; var drawingSteps = false; -function debug(o) { - //console.log(o); +function log_debug(o) { + print(o); } var p0_img = { @@ -111,13 +125,6 @@ var p100_img = { buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLFjzWEABLgbVgohEGoqyaiofDBihWVHJpYYDgYPbKxz5NLDJGCfBzgDKzA+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) }; -// 300 -Graphics.prototype.setFontRoboto18 = function(scale) { - // Actual height 18 (17 - 0) - this.setFontCustom(atob("AAAAAAAAAAAAAAAf8Qf8QAAAAAA+AAAAA+AAAAAAAABGABGwB/wf2AZGABHwD/AfGABGAAAADhwHw4MYIYIM4MOMMIGGYDDwAAAAAAPAAQgAQggZjAPOAAYABjgDPwEIQAIQAHwADAAAAAHgPMwZwQQwQR8QfGQODwADgAPwAAQAAA+AAAAAAAAA/wD/8OAHYABAAAQAAYABOAOD/8AfgAAAGAAGQACwAfgAfgACwAGAAAAAAAAAYAAYAAYAH/gH/gAYAAYAAYAAAAAAAAA8AAQAIAAIAAIAAIAAIAAAAAAQAAQAAAAAIAB4AHAA8AHgAeAAQAAAAAH/AOBgYAQQAQQAQYAQODwH/AAAAAAAEAAMAAIAAYAAf/wAAAAAAAAAAAAAAAOAQMBwYDQQGQQMQYYQPwQHAQAAAAAAGDgMAwYQQQQQQQQY4QPtwHHgAAAACAAOAAeAByADCAOCAf/wf/wACAACAAAAABAfxgcgwQgQQgQQgQQwwQfgAAAAAAB/AH7gMgwZgQZgQQgQQxwAfgAAAQAAQAAQAQQBwQHgQcARwAfAAcAAAAAAAAHHgPswYwQQQQQQQY4QPswHHgAAAAAAHwAMYQYMQQEQQEwYIgPfAH+AAAAAAADAQBAQAAAAAADA8BAQAAAAAAAYAAcAA0AAmABiABDADDAAAAAAAAkAAmAAmAAmAAmAAmAAmAAkAAAAAAADDABDABiAAmAA0AAcAAYAAIAAAAMAAYAAQGQQcQYwAPgAGAAAAAAfwBwcGAGEACIPzI4RZgRZARZBhY/zIAQMAQGAwD/gAeAAAQADwAfAB+APGAcGAPGAD2AAeAAHwAAwAAAf/wf/wQQQQQQQQQYQQYwwP5wHPgAAAAAAD+APvgIAwYAQQAQQAQQAQYAwODgCDAAAAAAAf/wf/wQAQQAQQAQYAQYAwMBgH/AB8AAAAAAAf/wf/wQQQQQQQQQQQQQQQQQQQAQAAAf/wf/wQQAQQAQQAQQAQQAQQAQAAAAAD+AP/gIAwYAQQAQQIQQIQYIQOIwGPgAAAAAAf/wf/wAQAAQAAQAAQAAQAAQAAQAf/wAAAAAAAAAAAAf/wAAAAAAAAAADgAAwAAQAAQAAQAAwf/gf+AAAAAAAf/wf/wAYAAwAB4ADMAGHAMBgYAwAAQAAAf/wf/wAAQAAQAAQAAQAAQAAQAAAf/wf/wOAADwAA8AAHgABwADwAOAB4AHgAeAAf/wAAAAAAAAAf/wf/wOAAHAABwAA4AAOAAHAABwf/wAAAAAAAAAD+APHgIAwYAQQAQQAQQAQYAwODgD/AAAAAAAf/wf/wQIAQIAQIAQIAYYAIQAPwAAAAAAAD+APDgIAwYAQQAQQAQYAQYA4ODsD/EAAAAAAf/wf/wQIAQIAQIAQYAYeAMzgHgwAAQAAAHDgPgwYwQQwQQQQQYQYYQMNwGHgAAAQAAQAAQAAQAAYAAf/wQAAQAAQAAQAAAAAAAAf/Af/gAAwAAQAAQAAQAAQAAwf/gf+AAAAYAAeAAHwAA+AAHgAAwAHwAeADwAeAAYAAQAAfAAD8AAPwABwAPgD4AfAAeAAHwAAfAADwAHwD+AfgAYAAAAAYAwMBgHHAB8AA4AB8AHHAMBgYAwAAAQAAcAAHAADgAA4AAfwA4ADgAOAAYAAAAAAAAQAwQDwQGQQcQQwQRgQXAQcAQYAQAAAAAA//////wABQAAeAAHgAA8AAPAAB4AAIwABwAD///AAAAAABwAHAAcAAOAADgAAwAAAIAAIAAIAAIAAIAAIAAIAAIAAAwAAYAAIAAAAAAAAAngBmwDMQCMQDMQDMwB/wAAQAAAAAA//wf/wBAQDAQDAQDAQBxwA/AAAAAAAA/gBhwDAQCAQDAQDAQBxgARAAAAA/ABxwDAQDAQDAQBAQf/w//wAAAAAAA/gBtwDMQDMQDMQDMQB8wAYAAAADAAf/w7AAzAAwAAAAAA/ABxyDATDARDARBAzB/+D/8AAAAAA//wf/wBAADAADAADAAB/wA/wAAAAAAT/wT/wAAAAABT//T/8AAAAAA//wf/wAMAAeAAzABhgDAwAAQAAAf/w//wAAAAAAD/wB/wBAADAADAADAAB/wB/wBAADAADAADAAB/wA/wAAAAAAD/wB/wBAADAADAADAAB/wA/wAAAAAAA/gBhwDAQDAQDAQDAQBhwA/gAEAAAAD//B//BAQDAQDAQDAQBxwA/AAAAAAAA/ABxwDAQCAQDAQBAQB//D//AAAAAAD/wB/wBAADAADAAAAABxgB4wDMQCMQDEQBGwBjgAAADAADAAP/wDAQDAQAAAAAAD/gB/wAAQAAQAAQAAwD/wD/wAAADAADwAAeAADwABwAHgA8ADgAAAAAAAD4AAfAADwAHwA+ADwAB4AAPAABwAHwB8ADgAAAAAAADAwBxgAfAAOAA7ABhwDAwAAADAADwBAeDAH+AB8AHgA8ADgAAAAAAADAwDBwDHQDMQD4QDgQDAQAAAAIAAMAH/wfz+wACgADAAAf/8f/8AAAgADwAGfz8D/wAMAAAAAAAAMAAcAAQAAQAAYAAMAAEAAEAAEAAYAAA"), 32, atob("BAQFCgoNCwMGBggKAwUEBwoKCgoKCgoKCgoEBAkKCQgQCwsMDAoKDA0FCgsJEA0MCwwLCwsMCxALCwsEBwQHCAUKCgkKCQYKCgQECQQQCgoKCgYJBgoJDgkJCQYEBgwA"), 18+(scale<<8)+(1<<16)); - return this; -} - // https://www.1001fonts.com/rounded-fonts.html?page=3 Graphics.prototype.setFontBloggerSansLight46 = function(scale) { // Actual height 46 (45 - 0) @@ -125,12 +132,22 @@ Graphics.prototype.setFontBloggerSansLight46 = function(scale) { return this; }; +Graphics.prototype.setFontRoboto20 = function(scale) { + // Actual height 21 (20 - 0) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAH/zA/+YAAAAAAAHwAAwAAHwAA+AAAAAAAAAAAQACDAAYbADP4B/8A/zAGYZADH4A/+A/7AHYYADCAAAAAAAQAeHgH4eBzgwMMHnhw88GGBw4wHj+AcPgAAAAAAAAAAB4AA/gAGMAAwhwGMcAfuABzgABzgAc+AOMYBhBAAMYAB/AAHwAAAAAHwD5+A/8YGPDAw8YGPzA/HYD4fAADwAB/AAOYAABAAAAHwAA4AAAAAAAAAAH/gD//B8A+cAA7AADAAAAAAAYAAbwAHHgHwf/4A/8AAAAEAABiAAGwAA8AA/AAH+AAGwAByAAEAAAAAAAMAABgAAMAABgAH/wA/+AAMAABgAAMAABgAAAAAAAIAAfAADwAAAABgAAMAABgAAMAABgAAAAAAAAAAAAADAAAYAAAAAAAAADgAB8AB+AA+AA+AA/AAHAAAgAAAAAAB8AB/8Af/wHAHAwAYGADAwAYHAHAf/wB/8AAAAAAAAAAABgAAcAADAAAYAAH//A//4AAAAAAAAAAAAAAAAAAAAABwDAeA4HAPAwHYGBzAwcYHHDAfwYB8DAAAYAAAAAAABgOAcBwHADAwwYGGDAwwYHPHAf/wB58AAAAAAAAADAAB4AAfAAPYAHjAB4YA8DAH//A//4AAYAADAAAAAAAAAEMA/xwH+HAxgYGMDAxgYGODAw/4GD+AAHAAAAAAAAAf8AP/wD2HA5wYGMDAxgYGOHAA/wAD8AAAAAAAAAAAGAAAwAAGADAwB4GB+Aw+AGfAA/gAHwAAwAAAAAAADAB5+Af/wHPDAwwYGGDAwwYHPHAfvwB58AAAAAAAAAAAB+AAf4AHDjAwMYGBjAwM4HDOAf/gB/4AAAAAAAAAAAAYDADAYAAAAAAAAAAYDAfAYHwAAAABAAAcAADgAA+AAGwAB3AAMYABjgAYMAAAAAAAAAAAAAAABmAAMwABmAAMwABmAAMwABmAAMwAAiAAAAAAAAAYMADjgAMYAB3AAGwAA2AADgAAcAABAAAAAAAAAMAADgAA4AAGBzAweYGHAA/wAD8AAEAAAAwAB/4A/PwOAGDgAYYPxmH/Mw4ZmMDMxgZmM+Mx/5mHDAYAIDgDAPBwAf8AAMAAAAAAAYAAfAAPwAP4AH+AH4wA8GAH4wAP2AAPwAAfwAAfAAAYAAAAAAAAAAA//4H//AwwYGGDAwwYGGDAwwYH/HAf/wB58AAAAADAAH/AD/+AcBwHADAwAYGADAwAYGADA4A4DweAODgAAAAAAAAAAAAAAH//A//4GADAwAYGADAwAYGADAYAwD4+AP/gAfwAAAAAAAAAAAH//A//4GDDAwYYGDDAwYYGDDAwYYGCDAgAYAAAAAAAH//A//4GDAAwYAGDAAwYAGDAAwYAGAAAAAAAAAAH/AD/8AcBwHAHAwAYGADAwYYGDDA4YYDz/AOfwAAAAAAAAAAA//4H//A//4ADAAAYAADAAAYAADAAAYAADAA//4H//AAAAAAAAAAAAAAA//4H//AAAAAAAAABAAAeAAB4AADAAAYAADAAAYAAHA//wH/8AAAAAAAAAAAAAAA//4H//AAcAAPAAD4AA/wAOPADg8A4B4GAHAgAYAAAAAAAH//A//4AADAAAYAADAAAYAADAAAYAADAAAAAAAA//4H//A+AAB+AAD8AAD8AAH4AAPAAH4AH4AD8AD8AA+AAH//A//4AAAAAAAH//A//4H//AeAAB8AADwAAPgAAeAAA8AADwH//A//4AAAAAAAAAAAH/AB/8AeDwHAHAwAYGADAwAYGADA4A4DweAP/gA/4AAAAAAAAAAAH//A//4GBgAwMAGBgAwMAGBgAwcAH/AAfwAA8AAAAAA/4AP/gDgOA4A4GADAwAYGADAwAYHAHgeD+B/8wD+GAAAAAAAAAAA//4H//AwYAGDAAwYAGDgAweAHH8Afz4B8HAAAIAAYAPDwD8OA5w4GGDAwwYGHDAwYYHDnAePwBw8AAAAGAAAwAAGAAAwAAGAAA//4H//AwAAGAAAwAAGAAAwAAAAAAAAAH/4A//wAAPAAAYAADAAAYAADAAAYAAPA//wH/8AAAAAAAAgAAHAAA/AAB/AAD+AAD+AAD4AAfAAfwAfwAfwAH4AA4AAEAAA+AAH/AAH/gAD/AAD4AD+AH+AH8AA+AAH+AAD+AAD/AAD4AH/AP/AH+AA8AAAAAAAAAGADA4A4HweAPPgA/wAB8AAfwAPvgDweA8B4GADAAAIGAAA4AAHwAAPgAAfAAA/4AH/AD4AB8AA+AAHgAAwAAAAAAAAAGADAwB4GAfAwPYGDzAx4YGeDA/AYHwDA4AYGADAAAAAAAA///3//+wAA2AAGAAAGAAA+AAD8AAD8AAD4AAH4AAHgAAMAAAAwAA2AAG///3//+AAAAAAAAAAAOAAHwAD4AA8AAD8AADwAAGAAAAAAABgAAMAABgAAMAABgAAMAABgAAMAABgAAAEAAAwAADAAAIAAAAAAAAAAEeABn4Ad3ADMYAZjADMYAZmAB/4AP/AAAAAAAA//4H//ABgwAYDADAYAYDADg4AP+AA/gABwAAAAAAAAA/gAP+ADg4AYDADAYAYDADAYAOOABxwAAAAAEAAH8AB/wAcHADAYAYDADAYAcDA//4H//AAAAAAAAAAAAH8AB/wAdnADMYAZjADMYAZjAB84AHmAAMAAMAABgAB//gf/8HMAAxgAGIAAAAAAH8IB/zAcHMDAZgYDMDAZgcHcD//Af/wAAAAAAAAAAH//A//4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAGf/Az/4AAAAAAAAAAMz//mf/4AAAAAAAAAAH//A//4ABwAAeAAH4ABzwAcPACAYAABAAAAAAAA//4H//AAAAAAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/ABgAAYAADAAAYAADgAAP/AA/4AAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAAH8AB/wAcHADAYAYDADAYAYDADx4AP+AA/gAAAAAAAAf/8D//gYDADAYAYDADAYAcHAB/wAH8AAEAAAAAAEAAH8AB/wAcHADAYAYDADAYAYDAD//gf/8AAAAAAAAAAAf/AD/4AcAADAAAYAACAAAAEAB5wAfnADMYAZjADGYAYzADn4AOeAAAAAAAADAAAYAAf/wD//ADAYAYDAAAAAAAAD/gAf/AAA4AADAAAYAADAAAwAf/AD/4AAAAAAAAYAAD4AAP4AAP4AAPAAH4AH4AD8AAcAAAAAAQAADwAAf4AAf4AAPAAP4AP4ADwAAfgAA/gAA/AAD4AH+AD+AAeAAAAAAAAACAYAcHADzwAH8AAfAAH8ADx4AcHACAIAcAMD4BgP4MAP/AAPwAP4AP4AD4AAcAAAAAAAAADAYAYHADD4AY7ADOYAfjADwYAcDADAYAAAAADAAA4AH//B/v8cABzAACAAAH//w//+AAAAAAACAACcAAx/n+H//AA4AAHAAAAAAAAAAAAAOAADgAAYAADAAAcAABgAAGAAAwAAGAADwAAcAAAAA"), 32, atob("BQUHDQwPDQQHBwkMBAYGCQwMDAwMDAwMDAwFBAsMCwoTDg0ODgwMDg8GDA0LEg8ODQ4NDA0ODRMNDQ0GCQYJCQYLDAsMCwcMDAUFCwUSDAwMDAcLBwwKEAoKCgcFBw4A"), 21+(scale<<8)+(1<<16)); + return this; +} + +function setSmallFont20() { + g.setFontRoboto20(); +} + function setLargeFont() { g.setFontBloggerSansLight46(1); } function setSmallFont() { - g.setFontRoboto18(1); + g.setFont('Vector', 16); } function getSteps() { @@ -144,8 +161,70 @@ function getSteps() { } } +/////////////// sunrise / sunset ///////////////////////////// + +function loadSettings() { + settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; + settings.grid = settings.grid||false; + settings.font = settings.font||"Lato"; + settings.idle_check = settings.idle_check||true; +} + +// requires the myLocation app +function loadLocation() { + location = require("Storage").readJSON(LOCATION_FILE,1)||{}; + location.lat = location.lat||51.5072; + location.lon = location.lon||0.1276; + location.location = location.location||"London"; +} + +function extractTime(d){ + var h = d.getHours(), m = d.getMinutes(); + return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2)); +} + +var sunRise = "00:00"; +var sunSet = "00:00"; +var drawCount = 0; + +function updateSunRiseSunSet(now, lat, lon, line){ + // get today's sunlight times for lat/lon + var times = SunCalc.getTimes(new Date(), lat, lon); + + // format sunrise time from the Date object + sunRise = extractTime(times.sunrise); + sunSet = extractTime(times.sunset); +} + +const infoData = { + ID_DATE: { calc: () => {var d = (new Date()).toString().split(" "); return d[2] + ' ' + d[1] + ' ' + d[3];} }, + ID_DAY: { calc: () => {var d = require("locale").dow(new Date()).toLowerCase(); return d[0].toUpperCase() + d.substring(1);} }, + ID_SR: { calc: () => 'Sunrise: ' + sunRise }, + ID_SS: { calc: () => 'Sunset: ' + sunSet }, + ID_STEP: { calc: () => 'Steps: ' + getSteps() }, + ID_BATT: { calc: () => 'Battery: ' + E.getBattery() + '%' } +}; + +const infoList = Object.keys(infoData).sort(); +let infoMode = infoList[0]; + +function nextInfo() { + let idx = infoList.indexOf(infoMode); + if (idx > -1) { + if (idx === infoList.length - 1) infoMode = infoList[0]; + else infoMode = infoList[idx + 1]; + } +} + +function prevInfo() { + let idx = infoList.indexOf(infoMode); + if (idx > -1) { + if (idx === 0) infoMode = infoList[infoList.length - 1]; + else infoMode = infoList[idx - 1]; + } +} + function getGaugeImage(p) { - //debug("p="+p); if (p < 2) return p0_img; if (p >= 2 && p < 4) return p2_img; if (p >= 4 && p < 7) return p4_img; @@ -163,6 +242,14 @@ function getGaugeImage(p) { } function draw() { + if (!idle) + drawClock(); + else + drawIdle(); + queueDraw(); +} + +function drawClock() { var date = new Date(); var timeStr = require("locale").time(date,1); var da = date.toString().split(" "); @@ -171,7 +258,6 @@ function draw() { var mm = da[4].substr(3,2); var steps = getSteps(); var p_steps = Math.round(100*(steps/10000)); - debug("steps="+ steps + " p_steps=" + p_steps); g.reset(); g.setColor(g.theme.bg); @@ -187,9 +273,14 @@ function draw() { g.setFontAlign(-1,0); // left aligned g.drawString(mm, (w/2) + 1, h/2); - drawSteps(); - g.drawString('Battery ' + E.getBattery() + '%', w/2, h/4); - queueDraw(); + setSmallFont(); + g.setFontAlign(0,0); // left aligned + g.drawString((infoData[infoMode].calc()), w/2, (3*h/4) - 4); + + // recalc sunrise / sunset every hour + if (drawCount % 60 == 0) + updateSunRiseSunSet(new Date(), location.lat, location.lon); + drawCount++; } function drawSteps() { @@ -205,11 +296,142 @@ function drawSteps() { drawingSteps = false; } +/* Bangle.on('step', s => { drawSteps(); }); +*/ +///////////////// IDLE TIMER ///////////////////////////////////// + +function drawIdle() { + let mins = Math.round((getTime() - lastStep) / 60); + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + g.setColor(g.theme.fg); + setSmallFont20(); + g.setFontAlign(0, 0); + g.drawString('Last step was', w/2, (h/3)); + g.drawString(mins + ' minutes ago', w/2, 20+(h/3)); + dismissBtn.draw(); +} + +/////////////// BUTTON CLASS /////////////////////////////////////////// + +// simple on screen button class +function BUTTON(name,x,y,w,h,c,f,tx) { + this.name = name; + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.color = c; + this.callback = f; + this.text = tx; +} + +// if pressed the callback +BUTTON.prototype.check = function(x,y) { + //console.log(this.name + ":check() x=" + x + " y=" + y +"\n"); + + if (x>= this.x && x<= (this.x + this.w) && y>= this.y && y<= (this.y + this.h)) { + log_debug(this.name + ":callback\n"); + this.callback(); + return true; + } + return false; +}; + +BUTTON.prototype.draw = function() { + g.setColor(this.color); + g.fillRect(this.x, this.y, this.x + this.w, this.y + this.h); + g.setColor("#000"); // the icons and boxes are drawn black + setSmallFont20(); + g.setFontAlign(0, 0); + g.drawString(this.text, (this.x + this.w/2), (this.y + this.h/2)); + g.drawRect(this.x, this.y, (this.x + this.w), (this.y + this.h)); +}; + +function dismissPrompt() { + idle = false; + warned = false; + lastStep = getTime(); + Bangle.buzz(100); + draw(); +} + +var dismissBtn = new BUTTON("big",0, 3*h/4 ,w, h/4, "#0ff", dismissPrompt, "Dismiss"); + +Bangle.on('touch', function(button, xy) { + var x = xy.x; + var y = xy.y; + // adjust for outside the dimension of the screen + // http://forum.espruino.com/conversations/371867/#comment16406025 + if (y > h) y = h; + if (y < 0) y = 0; + if (x > w) x = w; + if (x < 0) x = 0; + + if (idle && dismissBtn.check(x, y)) return; +}); + +// if we get a step then we are not idle +Bangle.on('step', s => { + lastStep = getTime(); + // redraw if we had been idle + if (idle == true) { + dismissPrompt(); + } + idle = false; + warned = 0; +}); + +function checkIdle() { + log_debug("checkIdle()"); + if (!settings.idle_check) { + idle = false; + warned = false; + return; + } + + let hour = (new Date()).getHours(); + let active = (hour >= 9 && hour < 21); + //let active = true; + let dur = getTime() - lastStep; + + if (active && dur > IDLE_MINUTES * 60) { + drawIdle(); + if (warned++ < 3) { + buzzer(warned); + log_debug("checkIdle: warned=" + warned); + Bangle.setLocked(false); + } + idle = true; + } else { + idle = false; + warned = 0; + } +} + +// timeout for multi-buzzer +var buzzTimeout; + +// n buzzes +function buzzer(n) { + log_debug("buzzer n=" + n); + + if (n-- < 1) return; + Bangle.buzz(250); + + if (buzzTimeout) clearTimeout(buzzTimeout); + buzzTimeout = setTimeout(function() { + buzzTimeout = undefined; + buzzer(n); + }, 500); +} + /////////////////////////////////////////////////////////////////////////////// // timeout used to update every minute @@ -220,8 +442,7 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - //prevInfo(); - //checkIdle(); + checkIdle(); draw(); }, 60000 - (Date.now() % 60000)); } @@ -236,8 +457,16 @@ Bangle.on('lcdPower',on=>{ } }); +Bangle.setUI("clockupdown", btn=> { + if (btn<0) prevInfo(); + if (btn>0) nextInfo(); + draw(); +}); + +loadSettings(); +loadLocation(); + g.clear(); -Bangle.setUI("clock"); Bangle.loadWidgets(); /* * we are not drawing the widgets as we are taking over the whole screen From a1627605b672b5b5376461e733a2ab04a505ebca Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:40:26 -0800 Subject: [PATCH 127/199] Bugfixes Fixed issues with drawing of the quotes --- apps/aptsciclk/app.js | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index 8cc4cdbb7..c2903cf37 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -151,16 +151,21 @@ var drawTimeout; var maxWarning = 9; var curWarning = Math.floor(Math.random() * (maxWarning+1)); -function unPause(delay){ - setTimeout(function() { - pause = false; - draw(); - }, delay); +function unPause(delay, quote){ + if (pause){ + setTimeout(function() { + if (quote == undefined || quoteNum == quote){ + pause = false; + draw(); + } + }, delay); + } } +var quoteNum; + function quote(fontsize, width, height, specificQuote){ pause = true; - unPause(7000); var finalString = ""; var quotesFile; var finalFontSize; @@ -171,12 +176,16 @@ function quote(fontsize, width, height, specificQuote){ var curQuote; if (specificQuote == undefined){ - curQuote = quotes[Math.round(Math.random()*numQuotes)-1]; //quote to be displayed + quoteNum = Math.round(Math.random()*numQuotes)-1; + curQuote = quotes[quoteNum]; //quote to be displayed } else{ - curQuote = quotes[specificQuote]; + quoteNum = specificQuote; + curQuote = quotes[quoteNum]; } + unPause(10000, quoteNum); + var curWords = curQuote.split(" "); //individual words //console.log(numQuotes); @@ -241,8 +250,13 @@ function buttonPressed(){ setTimeout(buttonUnpressed, 500); } function buttonUnpressed(){ - buttonImg = getImg("butUnpress"); - g.drawImage(buttonImg, 0, 0); + if (!pause){ + buttonImg = getImg("butUnpress"); + g.drawImage(buttonImg, 0, 0); + } + else{ + setTimeout(buttonUnpressed, 500); + } } // schedule a draw for the next minute @@ -332,6 +346,9 @@ Bangle.on('touch',(n,e)=>{ else if (!pause && 117 < e.x && e.x < 172 && 117 < e.y && e.y < 172){ quote(2, 150, 140); } + else{ + unPause(0); + } }); //show Apeture laboritories From d2f72600655287a0b4a173c7f6dafeda1f837a89 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:42:59 -0800 Subject: [PATCH 128/199] added more quotes --- apps/aptsciclk/quotes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/aptsciclk/quotes.txt b/apps/aptsciclk/quotes.txt index e2cbb969f..bc7a04867 100644 --- a/apps/aptsciclk/quotes.txt +++ b/apps/aptsciclk/quotes.txt @@ -1 +1 @@ -Well here we are again^You euthanized your faithful Companion Cube more quickly than any test subject on record. Congratulations.^So get comfortable while I warm up the neurotoxin emitters^This isn't brave. It's murder. What did I ever do to you?^The difference between us is that I can feel pain.^Who's gonna make the cake when I'm gone? You?^Oh... It's you.^I've been really busy being dead. You know, after you MURDERED ME.^So. How are you holding up? BECAUSE I'M A POTATO.^You really do have brain damage, don't you?^You like revenge, right? Everybody likes revenge. Well, let's go get some.^It's been fun. Don't come back.^And then you showed up. You dangerous, mute lunatic. +Well here we are again^You euthanized your faithful Companion Cube more quickly than any test subject on record. Congratulations.^So get comfortable while I warm up the neurotoxin emitters^This isn't brave. It's murder. What did I ever do to you?^The difference between us is that I can feel pain.^Who's gonna make the cake when I'm gone? You?^Oh... It's you.^I've been really busy being dead. You know, after you MURDERED ME.^So. How are you holding up? BECAUSE I'M A POTATO.^You really do have brain damage, don't you?^You like revenge, right? Everybody likes revenge. Well, let's go get some.^It's been fun. Don't come back.^And then you showed up. You dangerous, mute lunatic.^Unbelievable. You, [subject name here] must be the pride of [subject hometown here.]^You are not a good person. You know that, right? Good people don't get up here.^Cake, and grief counseling, will be available at the conclusion of the test.^This is your fault. I'm going to kill you. And all the cake is gone. You don't even care, do you?^Momentum, a function of mass and velocity, is conserved between portals. In layman's terms, speedy thing goes in, speedy thing comes out. From 9760d7eb54c24146dc0142c0a2581ecc2ef73931 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:43:35 -0800 Subject: [PATCH 129/199] Update ChangeLog --- apps/aptsciclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index e185a3bc9..ed32a45a2 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -5,3 +5,4 @@ 0.05: Small bugfix 0.06: Formatting 0.07: Added potato GLaDOS and quote functionality when you tap her +0.08: Fixed drawing issues with the quotes and added more From 84375eb8950156753592bace04f15d4179d057d1 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:44:01 -0800 Subject: [PATCH 130/199] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0d7f1e605..7d547a554 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "aptsciclk", "name": "Apeture Sci Clock", - "version": "0.07", + "version": "0.08", "description": "A clock based on the portal series", "icon": "app.png", "type": "clock", From d050ffde67828257e4619e6d6558802cff712a4e Mon Sep 17 00:00:00 2001 From: hughbarney Date: Tue, 22 Feb 2022 23:19:02 +0000 Subject: [PATCH 131/199] Daisy - first release --- apps/daisy/ChangeLog | 1 + apps/daisy/README.md | 81 +++------- apps/daisy/app.js | 227 +++++++++++++++-------------- apps/daisy/metadata.json | 3 +- apps/daisy/screenshot_daisy1.png | Bin 0 -> 3072 bytes apps/daisy/screenshot_thering1.png | Bin 3113 -> 0 bytes apps/daisy/screenshot_thering2.jpg | Bin 45141 -> 0 bytes apps/daisy/screenshot_thering3.jpg | Bin 19580 -> 0 bytes 8 files changed, 135 insertions(+), 177 deletions(-) create mode 100644 apps/daisy/ChangeLog create mode 100644 apps/daisy/screenshot_daisy1.png delete mode 100644 apps/daisy/screenshot_thering1.png delete mode 100644 apps/daisy/screenshot_thering2.jpg delete mode 100644 apps/daisy/screenshot_thering3.jpg diff --git a/apps/daisy/ChangeLog b/apps/daisy/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/daisy/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/daisy/README.md b/apps/daisy/README.md index 382fe853f..09ecb78cd 100644 --- a/apps/daisy/README.md +++ b/apps/daisy/README.md @@ -1,73 +1,28 @@ -# The Ring - - *A proof of concept clock with large ring guage for steps using pre-set images, acts as a tutorial piece for discussion* +# Daisy + *A beautiful digital clock with large ring guage, idle timer and a + cyclic information line that includes, day, date, steps, battery, + sunrise and sunset times* 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/) -* The ring is a proof of concept to establish a clean way to draw a -large ring guage with few aliasing issues and artifacts. -* Rather than use grahics commands to draw the ring a series of fixed images are used. -* This allows for better accuracy of the initial image and also does not suffer from performance issues. -* The downside is that more storage and memory is used to hold the - initial images. This is not an issue on a Bangle 2. -* The ring effect is constructed from 14 images that represent a range of different percentages -* The percentages of the images are 0,2,4,7,10,20,30,40,50,60,70,80,90,100% -* The app is not intended to be enhanced further (apart from bug fixes) but rather as code that can be reused in other apps -* The full set of original images are included in the source code to demonstrate the concept -* I will use this code to build a new clock similar to Pastel but - using this ring guage for steps. The new clock will use more - attractive fonts and provide a settings meu to change the primary - color of the ring. +* Derived from `The Ring` proof of concept and the [Pastel clock](https://banglejs.com/apps/?q=pastel) +* Includes the [Lazybones](https://banglejs.com/apps/?q=lazybones) Idle warning timer +* Touch the top right/top left to cycle through the info display (Day, Date, Steps, Sunrise, Sunset) +* Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location +* The screen is updated every minute to save battery power +* Uses the [BloggerSansLight](https://www.1001fonts.com/rounded-fonts.html?page=3) font, which if free for commercial use +## Future Development +* Add settings menu to change primary clock color +* Add a heart rate option in the information line that turns on when selected +* Use mini icons in the information line rather that text +* Add weather icons as per Pastel clock +* Add a lock icon to the screen ## Screenshots +![](screenshot_daisy1.png) -![](screenshot_thering1.png) - -It is worth looking at a photograph of the clock in action as the -screenshot does not do the final effect justice. - -![](screenshot_thering2.jpg) - -## Production - -1. I first generated a circle on black background using [The -Gimp](https://www.gimp.org/) image editor. I used this [Youtube -video](https://www.youtube.com/watch?v=AoIAznSdLik) to get started. -The initial image is 178x178 pixels. - -![](1circle.png) - -2. I then drew another smaller black circle over the top of the original to make a ring - -![](1ring.png) - -3. From the empty ring image I coloured segments of the ring and saved new images at specific percentages - -4. I used the file `calc_percentages.js` to work out the x and y -coordinates of the end point of each percentage position along the -ring. - -5. The [Image -Converter](https://espruino.github.io/EspruinoWebTools/examples/imageconverter.html) -was used, set to 2-bit optimal, transparency Y, compression Y and -ImageObject Y, to convert each PNG file to code. - -6. NOTE that the generated image object pallete seemed to switch the -order of the colors from 50% onwards. - -7. The greying out of the unused part of the ring is acheived by -using a dithered color. So if the ring colour is green #0f0 then the -greyed out part is done in '#020'. - - -## Stages of The Ring - -Below are some examples of the different stages of the ring - -![](0p.png) -![](7p.png) -![](60p.png) +It is worth looking at the real thing though as the screenshot does not do it justice. diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 54743d945..5490d0740 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -24,107 +24,9 @@ const infoHeight = 14; var drawingSteps = false; function log_debug(o) { - print(o); + //print(o); } -var p0_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLLLzWEABLgbVgohEGopYaiofDBihWVHJpYYDgYPbKx1ACJhYZIwT4OcAZWYHyRYUIgQXQH4RqOThCXUYRpCHNyQVVQQTwVQiSZWIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) -}; - -var p2_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette: pal1, - buffer : require("heatshrink").decompress(atob("AH4A/ADNUFE8FqtVq2q1AqkFIIrDAAOAFMEBFQYrE1WgKsYrGLL4qFFY2pqDWeFZdUVkAhCAQMKFYdVLDUVFQYMHlWq0oMJKyoOJlQrCLDBWDB5clB5xWOoARMCARYWKwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) -}; - -var p4_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFY2loAqjFY1VqDWeFZdUVkAhEhQrDLDcVFQYMHlQrCBhBWVHJpYYDgYPbKx1ACJhYZIwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) -}; - -var p7_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgWlKzVACJgrCqBWYawgAJcAOlNBhWMCZ8qFYJYUgoqBC6ECFYJqOAApWSS4jCNQQ5uSCqqCCeCqESFQKZUIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A==")) -}; - -var p10_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAOkQSdUFacK1WloCCSCaAAEFYKaQQSyEC0pvQirZTbomlIh6CYZAZFOQTBxDQhyCYOQhoPQS4bQHaBzaVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) -}; - -var p20_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4AWgNVoAEGAERSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A=")) -}; - -var p30_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccFawkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) -}; - -var p40_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal1, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccKFYkVFcwFDitVFccqFYkFFcuoFeNAFcWqFYkBFcugFYtQFUMCFYsAFcuAFYtUFcMKFY0VFcgHFitVFcMqFY0FFceoFY9AFcGqFY0BqtQFT8C1WgFeMAqtUFb8K1WAFY7cglQrIioriBI8FqtAFb2q1ArJbjzaBFZEBbj7aB0ALIFcLaHbkLaJFYbcd1QrKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjUBQR6EaiqCPQjVVQSATCqtUFSZvB1WACiSEUY4KCQQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) -}; - -var p50_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjSCQQjSCQQjSCRAAIrB1AqTgorBoAUQQiyCSQgjdSbISCRQgZYSKwKCSQghYQKwSCSQghYQKwSCTAAMqFYOoCJsFFQNVFShYEwARMFQRWVLAiFMQIRWWLAosKFQZWXLAosIFQZWYLAzgFawZWbAAMKFgmq1IoEAANUFTQABFZtAFbgsFFYwqeWQorFVjZZJFYhVfcAwrCazoA/AHI")) -}; - -var p60_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAelNBqCLVxqEC0oRPQS6EC0oSQQSyECFYKEVQSIABFYI/QAAcFFYJDRCgSCmYYjdSCqqYCLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) -}; - -var p70_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZAgoAggNVoAr/FbdUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) -}; - -var p80_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AcIdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) -}; - -var p90_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESquq1ArTgqESNgOqwArTIYKERH4KCUQigSBbKTdGCKKCVQiTCCFSyERCALBQQjAPBoArXDZ7ARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) -}; - -var p100_img = { - width : 176, height : 176, bpp : 2, - transparent : -1, - palette : pal2, - buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLFjzWEABLgbVgohEGoqyaiofDBihWVHJpYYDgYPbKxz5NLDJGCfBzgDKzA+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) -}; - // https://www.1001fonts.com/rounded-fonts.html?page=3 Graphics.prototype.setFontBloggerSansLight46 = function(scale) { // Actual height 46 (45 - 0) @@ -224,21 +126,120 @@ function prevInfo() { } } +// putting into 1 function like this, rather than individual variables +// reduces ram usage from 70%-13% function getGaugeImage(p) { - if (p < 2) return p0_img; - if (p >= 2 && p < 4) return p2_img; - if (p >= 4 && p < 7) return p4_img; - if (p >= 7 && p < 10) return p7_img; - if (p >= 10 && p < 20) return p10_img; - if (p >= 20 && p < 30) return p20_img; - if (p >= 30 && p < 40) return p30_img; - if (p >= 40 && p < 50) return p40_img; - if (p >= 50 && p < 60) return p50_img; - if (p >= 60 && p < 70) return p60_img; - if (p >= 70 && p < 80) return p70_img; - if (p >= 80 && p < 90) return p80_img; - if (p >= 90 && p < 100) return p90_img; - if (p >= 100) return p100_img; + // p0 + if (p < 2) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLLLzWEABLgbVgohEGopYaiofDBihWVHJpYYDgYPbKx1ACJhYZIwT4OcAZWYHyRYUIgQXQH4RqOThCXUYRpCHNyQVVQQTwVQiSZWIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) + }; + + // p2 + if (p >= 2 && p < 4) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette: pal1, + buffer : require("heatshrink").decompress(atob("AH4A/ADNUFE8FqtVq2q1AqkFIIrDAAOAFMEBFQYrE1WgKsYrGLL4qFFY2pqDWeFZdUVkAhCAQMKFYdVLDUVFQYMHlWq0oMJKyoOJlQrCLDBWDB5clB5xWOoARMCARYWKwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) + }; + + // p4 + if (p >= 4 && p < 7) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFY2loAqjFY1VqDWeFZdUVkAhEhQrDLDcVFQYMHlQrCBhBWVHJpYYDgYPbKx1ACJhYZIwT4OgpYXKwY+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) + }; + + // p7 + if (p >= 7 && p < 10) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgWlKzVACJgrCqBWYawgAJcAOlNBhWMCZ8qFYJYUgoqBC6ECFYJqOAApWSS4jCNQQ5uSCqqCCeCqESFQKZUIQSEQNgSYSIYiEQQSyEUCQLDSOAyCnQiSCYQiSCYQiSCZDaDARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A==")) + }; + + // p10 + if (p >= 10 && p < 20) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAOkQSdUFacK1WloCCSCaAAEFYKaQQSyEC0pvQirZTbomlIh6CYZAZFOQTBxDQhyCYOQhoPQS4bQHaBzaVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) + }; + + // p20 + if (p >= 20 && p < 30) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4AWgNVoAEGAERSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A=")) + }; + + // p30 + if (p >= 30 && p < 40) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccFawkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHI")) + }; + + // p40 + if (p >= 40 && p < 50) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal1, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVqtW1WoFUgpBFYYABwApggIqDFYmq0BVjFYxZfFQorGLLrWCFZbgbVgtUBQcKLD8VFQYMHlQsDKzoOJFgZYYKwYPLFgZWaoARMLDJWCawgAJcAZWYCZ6FCLCkFFQNQCZ8CFYOoFaZWSLAmAQShWQLAiESQQRtTLAKESFQNUFacKQiSCCoArTgCESQSyEUirZTboyCnQiSCYQiSCYQiSCZQgeAVxwqYQgSwMVwNUFbMKWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbhdVFcTcHbT7cDFY0BbT7cD0ArxgtVoArfgGq1ArHFUDcBFY0VFceqFY1UFcMKFY1VFcmAFYtQFcMCFYsBFcugFYtAFcMAFYsFFcuoFYoqigEqFeEVFcuqFYlUFccKFYlVFc2AFYdQFccCFf4rbgNVoArjgGq0Ar/FbMFFc+oFYYqkgEqFf4r/FY0VqgrlhWqFf4r/Ff4rdqorowArBqArlgQr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlhQrCioroAYIr/Ff4r/FbcFqorllWoFf4r/FY9AFcmqFYUBFc+gFf4rZgFVqAqjgWqwAr/FbdUFccKFYkVFcwFDitVFccqFYkFFcuoFeNAFcWqFYkBFcugFYtQFUMCFYsAFcuAFYtUFcMKFY0VFcgHFitVFcMqFY0FFceoFY9AFcGqFY0BqtQFT8C1WgFeMAqtUFb8K1WAFY7cglQrIioriBI8FqtAFb2q1ArJbjzaBFZEBbj7aB0ALIFcLaHbkLaJFYbcd1QrKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjUBQR6EaiqCPQjVVQSATCqtUFSZvB1WACiSEUY4KCQQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) + }; + + // p50 + if (p >= 50 && p < 60) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAiEXKwKuNQjSCQQjSCQQjSCRAAIrB1AqTgorBoAUQQiyCSQgjdSbISCRQgZYSKwKCSQghYQKwSCSQghYQKwSCTAAMqFYOoCJsFFQNVFShYEwARMFQRWVLAiFMQIRWWLAosKFQZWXLAosIFQZWYLAzgFawZWbAAMKFgmq1IoEAANUFTQABFZtAFbgsFFYwqeWQorFVjZZJFYhVfcAwrCazoA/AHI")) + }; + + // p60 + if (p >= 60 && p < 70) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZgGq0AqjgNVoAr/FbeoFccFFYkqFcwFDlWqFccVFYkKFctUFeOAFcVVFYkCFctQFYugFUMBFYsAFctAFYuoFcMFFY0qFcgHFlWqFcMVFY0KFcdUFY+AFcFVFY0C1WgFT8BqtQFeMA1WoFb8FqtAFY7cgiorIlQriBI8K1WAFb1VqgrJbjzaBFZECbj7aBqALIFcLaHbkLaJFYbcdqorKbjzaKbkDaLbgSwcVwLaJWD6uLFYawaVwIrMbgKwaVwLaKbgawaVwLaLbgawZQQLaLWDiuOWAaEYQQKuMWAelNBqCLVxqEC0oRPQS6EC0oSQQSyECFYKEVQSIABFYI/QAAcFFYJDRCgSCmYYjdSCqqYCLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) + }; + + // p70 + if (p >= 70 && p < 80) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AFYegFccBFf4rbgWqwArjgFVqAr/FbMKFc9UFYYqkgEVFf4r/FY0q1ArlgtVFf4r/Ff4rd1QrooArB0ArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rb1ArlgorClQroAYIr/Ff4r/FbcK1QrlitUFf4r/FY+AFclVFYUCFc9QFf4rZAgoAggNVoAr/FbdUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) + }; + + // p80 + if (p >= 80 && p < 90) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AcIdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) + }; + + // p90 + if (p >= 90 && p < 100) return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESquq1ArTgqESNgOqwArTIYKERH4KCUQigSBbKTdGCKKCVQiTCCFSyERCALBQQjAPBoArXDZ7ARObKuBSZwcaVzR0QFYKuZWAYNZWCJJKMoKuaWAahKBhiwTJRSudURorBFTgfMVzqjDO5DaeZ5jaeJhhiKbi4rIbT4hLqoriPI7afUpS5BbTwiKFdZgIADSmHFYIqgbgIrGcgIriEYwzHADZ7HRY4rdaYrjHADcBFYoGBFcgkEGQwAeFYqKHFbzUEcQ4AdiorwiorlEogxFAD59FWoorhoArDqArjgIr/FbYwFAEJSDFf4rXgornqgrDFUkAior/Ff4rGAYYAjKYYr/Ff4r/FbdVFdFAFYNQFcsBFf4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/FbdUFcsFFYUVFdADBFf4r/Ff4rbAYYAjKYYr/Ff4rFoArkqorCgIrnqAr/FbIEFAEBSFFf4rYqgrjgorEiormAocVAogAfEooxFFcB9EFdq1DAD9VFYkBFctQFYoGEADokHFcp8FRQoAdag7iFFb4HFioHGADYjHGY4rcPYyLHADbTHcYNQFT4iIFdZgIADKmJqrcgiorIBIIrhMKIAXUpIrBbjzaBFZAKKbS5MJFcKkJbj4fLBYLcdqorKbjzPMbjxKNMhauTURawdJJorBWDShBFZiRBWDQcOHRyuPOhorBWDIbPWDRzQSYKEYIwLLOHgSEXDIJyPQjD2SQjCCQQjSCRCYY/QN4xDRQiyCSQgjdSCqqECLCRWBYyiECISBWCYqgXCLCBWCQSYYEIhxqCeChYFThoQCKypYEIxgPPLB4cKFQZWXDoosIBhhYWcArWDKzYhHABA1EADArNoArcFhgqeWQysgLJxVfcBLWdAH4A5A")) + }; + + // p100 + return { + width : 176, height : 176, bpp : 2, + transparent : -1, + palette : pal2, + buffer : require("heatshrink").decompress(atob("AH4A/AH4ACgtVAAVUFUgpDAAdAFMEBFQ4ABqBVnLMQqLFjzWEABLgbVgohEGoqyaiofDBihWVHJpYYDgYPbKxz5NLDJGCfBzgDKzA+SLChECC6A/CNRycIS6jCNIQ5uSCqqCCeCqESTKxCCQiBsCTCRDEQiCCWQigSBYaRwGQU6ESQTCESQTCESQTIbQYCJzZVwKTODjSuaOiArBVzKwDBrKwRJJRlBVzSwDUJQMMWCZKKVzqiNFYIqcD5iudUYZ3IbTzPMbTxMMMRTcXFZDafEJdVFcR5HbT6lKXILaeERQrrMBAAaUw4rBFUDcBFYzkBFcQjGGY4AbPY6LHFbrTFcY4AbgIrFAwIrkEggyGADwrFRQ4reagjiHADsVFeEVFcolEGIoAfPoq1FFcNAFYdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) + }; } function draw() { diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index c42432955..90b83ba97 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -1,11 +1,12 @@ { "id": "daisy", "name": "Daisy", "version":"0.01", + "dependencies": {"mylocation":"app"}, "description": "A clock based on the Pastel clock with large ring guage for steps", "icon": "app.png", "tags": "clock", "supports" : ["BANGLEJS2"], - "screenshots": [{"url":"screenshot_thering3.jpg"}], + "screenshots": [{"url":"screenshot_daisy1.jpg"}], "readme": "README.md", "storage": [ {"name":"daisy.app.js","url":"app.js"}, diff --git a/apps/daisy/screenshot_daisy1.png b/apps/daisy/screenshot_daisy1.png new file mode 100644 index 0000000000000000000000000000000000000000..afef3a4246d9a14451d3f3921459be353bfec9e7 GIT binary patch literal 3072 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 Dgx=Ia diff --git a/apps/daisy/screenshot_thering2.jpg b/apps/daisy/screenshot_thering2.jpg deleted file mode 100644 index 521a610171da359e9ae8e2c3f2816846d541a258..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45141 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

PZ>rG*M~V* zC=?>g<|qzUT^}9eqm`cR-)I=G%D(J`n$g*O+P+6K*i1SmQxJoPJy1-=+C!XPq zXt}li9;HoaA#*YruFn<(?aZy;Gk-omgP;Tu?VX>u{|%i&05tz4)r&W<>4qON|T{S-l=El;BD@~G0;3Zdw%_I;xJ>C7skh{n8_ z1r$-3d%J?jPxjaGb$HYSfy%xHQ>HkGn6ze-HgDn`h}pCJ=JMyPk9(uQ2l2^x*)FNT z^A7CU%y;7fKhtN~z0ti&UTiI15>bra(5u6?V_VDzCEA3#^b#d>BSPB$lA!y*g9uU4 z@wD()0iq7>8$RVJgXqm#qdS}gc)T|aqDjqh=FXpNj2z{KQaA~9m)+coK$QAmy+r20C+G~`6dK8p$cTg#30zac>=!9*{mlU4^%FzH1GLUxT42Yhv+dMStgI@awnB8-Z5@|- z>ai1%5l&rW0ul=# z=U}w1>YAUs6lhCUs;as3+lo}t0`d&j)e1+ZskBSsRbBf_AXsgynhZw-Ps=Q+)d~8RH-A$ncazPIV650N=byGl>S7t ze)cA`)PbBe(Pl=#v$U(Er#qT;B`d0(G$4!f7EgY-rpeT^@a0v7GW|9eSgy*OJtAwt z7!PX@&dPGDpkBTkk3d7@^OZwHK(34kH?HHe?-Cc3^Dicom*#y9k6y%`mUIt4oxuCPn9;^520*>@VS z3-Sa~*vAWYZU^dgHbQ-`_3OdAt^D z8R>^Zw_ymMw3SY1)iX0Xe!T4&@uOJH&5T2DDh4Kag``Qsg#B4l&Qbjr@T@y#kR{T; zv6t?G8X9}m4nhH|H8w)6=kLEMh6qRQAH$}Rol%DJOn2|k;R?tHqpHiEmjn|;8x|iN zi5M>#!RVvAiP(R8<6jm|ka`f_dt=!?#40l``=kY~Nww$o{9aCu)P@5>p_eJKi|2J( zs;y>#3qL`Cy<(*&E%PVN_YWLQ@K?N9gEIod�e9j3!`F3^QxZK5jA}%d6?l5dX7% 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 OpD1M{07xEZSpV5*ZhS)k diff --git a/apps/daisy/screenshot_thering3.jpg b/apps/daisy/screenshot_thering3.jpg deleted file mode 100644 index da8f140c0b36dbcc3c09c9fcc163a02bd1cfdc4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19580 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 Date: Tue, 22 Feb 2022 23:46:23 +0000 Subject: [PATCH 132/199] Daisy - first release --- apps/daisy/README.md | 2 ++ apps/daisy/metadata.json | 2 +- apps/daisy/screenshot_daisy2.jpg | Bin 0 -> 4775 bytes 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 apps/daisy/screenshot_daisy2.jpg diff --git a/apps/daisy/README.md b/apps/daisy/README.md index 09ecb78cd..f6c0014be 100644 --- a/apps/daisy/README.md +++ b/apps/daisy/README.md @@ -26,3 +26,5 @@ Forum](http://forum.espruino.com/microcosms/1424/) ![](screenshot_daisy1.png) It is worth looking at the real thing though as the screenshot does not do it justice. +(Though I need to redo this photo at some point) +![](screenshot_daisy2.jpg) diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index 90b83ba97..fe66683a7 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -6,7 +6,7 @@ "icon": "app.png", "tags": "clock", "supports" : ["BANGLEJS2"], - "screenshots": [{"url":"screenshot_daisy1.jpg"}], + "screenshots": [{"url":"screenshot_daisy2.jpg"}], "readme": "README.md", "storage": [ {"name":"daisy.app.js","url":"app.js"}, diff --git a/apps/daisy/screenshot_daisy2.jpg b/apps/daisy/screenshot_daisy2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fec6a4c7b82c9dd40f3993017eb3edaa1a457b1a GIT binary patch literal 4775 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 literal 0 HcmV?d00001 From aa86b3ffdb63f59d9b0823360855e8c40f86d02a Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 10:44:16 +0100 Subject: [PATCH 133/199] Update 7x7dotsclock.app.js Add color yellow for minutes and seconds Better color contrast for seconds --- apps/7x7dotsclock/7x7dotsclock.app.js | 57 ++++++++++++++++----------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index ce2b3011d..53b4c1bd6 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -13,18 +13,26 @@ var Xs = 0, Ys = 30,Xe = 175, Ye=175; var SegH = (Ye-Ys)/2,SegW = (Xe-Xs)/2; var Dx = SegW/14, Dy = SegH/16; -switch(ColorMinutes) { - case "blue": - var mColor = [0.3,0.3,1]; - break; - case "pink": - var mColor = [1,0.3,1]; - break; - case "green": - var mColor = [0.3,1,0.3]; - break; - default: - var mColor = [0.3,0.3,1]; +switch(settings.ColorMinutes) { +case "blue": + var mColor = [0.3,0.3,1]; + var sColor = [0,0,1]; + break; +case "pink": + var mColor = [1,0.3,1]; + var sColor = [1,0,1]; + break; +case "green": + var mColor = [0.3,1,0.3]; + var sColor = [0,1,0]; + break; +case "yellow": + var mColor = [1,1,0.3]; + var sColor = [1,1,0]; + break; +default: + var sColor = [0,0,1]; + var mColor = [0.3,0.3,1]; } const bColor = [0.3,0.3,0.3]; @@ -152,9 +160,10 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { for (let j = 1; j < 8; j++) { if (Font[Num][j-1][i-1] == 1) { if (Color == "fg") { - g.setColor(mColor[0],mColor[1],mColor[2]); + g.setColor(sColor[0],sColor[1],sColor[2]); } else { g.setColor(g.theme.fg); + //g.setColor(0.7,0.7,0.7); } g.fillCircle(x1+(i-1)*(x2-x1)/7,y1+(j-1)*(y2-y1)/7,Size); } @@ -164,23 +173,25 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { function ShowSecons() { + //g.setColor(bColor[0],bColor[1],bColor[2]); + //g.setColor(0.7,0.7,0.7); g.setColor(g.theme.fg); - g.fillRect((Xe-Xs) / 2 - 14 + Xs -3, - (Ye-Ys) / 2 - 7 + Ys -3, - (Xe-Xs) / 2 + 14 + Xs +1, - (Ye-Ys) / 2 + 7 + Ys +1); + g.fillRect((Xe-Xs) / 2 - 14 + Xs -4, + (Ye-Ys) / 2 - 7 + Ys -4, + (Xe-Xs) / 2 + 14 + Xs +4, + (Ye-Ys) / 2 + 7 + Ys +4); drawSSeg( (Xe-Xs) / 2 - 14 + Xs -1, - (Ye-Ys) / 2 - 7 + Ys , + (Ye-Ys) / 2 - 7 + Ys +1, (Xe-Xs) / 2 + Xs -1, - (Ye-Ys) / 2 + 7 + Ys, + (Ye-Ys) / 2 + 7 + Ys +1, ds,"fg",1); - drawSSeg( (Xe-Xs) / 2 + Xs +1, - (Ye-Ys) / 2 - 7 + Ys, - (Xe-Xs) / 2 + 14 + Xs +1, - (Ye-Ys) / 2 + 7 + Ys, + drawSSeg( (Xe-Xs) / 2 + Xs +2, + (Ye-Ys) / 2 - 7 + Ys +1, + (Xe-Xs) / 2 + 14 + Xs +2, + (Ye-Ys) / 2 + 7 + Ys +1, es,"fg",1); } From 66e1fa4e2f45c5fb8a2606f0d34036793af5cfa4 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 10:45:35 +0100 Subject: [PATCH 134/199] Update README.md --- apps/7x7dotsclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/README.md b/apps/7x7dotsclock/README.md index 76684bc1a..28fcac1b1 100644 --- a/apps/7x7dotsclock/README.md +++ b/apps/7x7dotsclock/README.md @@ -5,7 +5,7 @@ * A Clock with big numbers made of 7x7 dots * system widgeds ar not (yet) supported * when screen is locked it shows hours and minutes in full screen mode -* respects theme colors +* adjustable color for minutes and seconds ![](dotsfontclock-scr1.png) From b21da11e6c01d6b998d1388339764e53b62e580d Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:21:10 +0100 Subject: [PATCH 135/199] Add files via upload --- apps/7x7dotsclock/dotsfontclock-scr1.png | Bin 3874 -> 3737 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/7x7dotsclock/dotsfontclock-scr1.png b/apps/7x7dotsclock/dotsfontclock-scr1.png index dc86396c0606f0a4c5ea4895bc17543f2e51024a..5ab2e48639a4b5dcffbeb59e83b7819f89c4228d 100644 GIT binary patch delta 3724 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 Y?43dq;SVfZ;Q#;t07*qoM6N<$f-v!GOaK4? From 0a9516dee03586a53fc63580ec08fecf56a6409f Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:21:54 +0100 Subject: [PATCH 136/199] Add files via upload --- apps/7x7dotsclock/dotsfontclock-scr2.png | Bin 0 -> 3386 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/7x7dotsclock/dotsfontclock-scr2.png diff --git a/apps/7x7dotsclock/dotsfontclock-scr2.png b/apps/7x7dotsclock/dotsfontclock-scr2.png new file mode 100644 index 0000000000000000000000000000000000000000..f301bb50c7217253516345c09a3482f7e745455c GIT binary patch literal 3386 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 Date: Wed, 23 Feb 2022 11:24:30 +0100 Subject: [PATCH 137/199] Update metadata.json Added screenshots --- apps/7x7dotsclock/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/metadata.json b/apps/7x7dotsclock/metadata.json index 9f997e10d..41f0836d3 100644 --- a/apps/7x7dotsclock/metadata.json +++ b/apps/7x7dotsclock/metadata.json @@ -14,5 +14,6 @@ {"name":"7x7dotsclock.settings.js","url":"7x7dotsclock.settings.js"}, {"name":"7x7dotsclock.img","url":"7x7dotsclock.img.js","evaluate":true} ], - "data": [{"name":"7x7dotsclock.json"}] + "data": [{"name":"7x7dotsclock.json"}], + "screenshots": [{"url":"dotsfontclock.png"},{"url":"dotsfontclock-scr1.png"},{"url":"dotsfontclock-scr2.png"}] } From 040d765d946f245fa4bdb62f073c2f8da23b7545 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:28:56 +0100 Subject: [PATCH 138/199] Update 7x7dotsclock.settings.js add yellow color --- apps/7x7dotsclock/7x7dotsclock.settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.settings.js b/apps/7x7dotsclock/7x7dotsclock.settings.js index fe9fbc022..34935d668 100644 --- a/apps/7x7dotsclock/7x7dotsclock.settings.js +++ b/apps/7x7dotsclock/7x7dotsclock.settings.js @@ -37,7 +37,7 @@ function showMainMenu() { const mainMenu = { "": {"title": "7x7 Dots Clock Settings"}, "< Back": ()=>load(), - "Minutes": stringInSettings("ColorMinutes", ["blue","pink","green"]), + "Minutes": stringInSettings("ColorMinutes", ["blue","pink","green","yellow"]), "swipe-up": ()=>showSelAppMenu("swupApp"), "swipe-down": ()=>showSelAppMenu("swdownApp"), "swipe-left": ()=>showSelAppMenu("swleftApp"), From ca1b94fa8948df9cfb788a147a3ff9ed6a88ebe6 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:30:38 +0100 Subject: [PATCH 139/199] Update ChangeLog --- apps/7x7dotsclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/7x7dotsclock/ChangeLog b/apps/7x7dotsclock/ChangeLog index 50c5eca4a..d2c98a472 100644 --- a/apps/7x7dotsclock/ChangeLog +++ b/apps/7x7dotsclock/ChangeLog @@ -1 +1,2 @@ 0.01: Initial version for upload +0.02: better theme support, configurable colors, small improvements From ffa5b96de6eaf89db9f2a9e3b5238fadaa288b91 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 10:44:48 +0000 Subject: [PATCH 140/199] messages +0.23: Change message colors to match current theme instead of using green + Now attempt to use Large/Big/Medium fonts, and allow minimum font size to be configured --- apps/messages/ChangeLog | 6 ++- apps/messages/README.md | 3 ++ apps/messages/app.js | 69 ++++++++++++++++++++--------------- apps/messages/metadata.json | 2 +- apps/messages/screenshot.png | Bin 2931 -> 4194 bytes apps/messages/settings.js | 6 +++ 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 07da48198..1e6ac71d7 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -32,5 +32,7 @@ 0.20: Allow tapping on the body to show a scrollable view of the message and title in a bigger font (fix #1405, #1031) 0.21: Improve list readability on dark theme 0.22: Add Home Assistant icon -0.22: Allow repeat to be switched Off, so there is no buzzing repetition. - Also gave the widget a pixel more room to the right \ No newline at end of file + Allow repeat to be switched Off, so there is no buzzing repetition. + Also gave the widget a pixel more room to the right +0.23: Change message colors to match current theme instead of using green + Now attempt to use Large/Big/Medium fonts, and allow minimum font size to be configured diff --git a/apps/messages/README.md b/apps/messages/README.md index a355a58ac..cce4391e7 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -16,6 +16,9 @@ and `Messages`: * `Unread Timer` - when a new message is received we go into the Messages app. If there is no user input for this amount of time then the app will exit and return to the clock where a ringing bell will be shown in the Widget bar. +* `Min Font` - the minimum font size used when displaying messages on the screen. A bigger font +is chosen if there isn't much message text, but this specifies the smallest the font should get before +it starts getting clipped. ## New Messages diff --git a/apps/messages/app.js b/apps/messages/app.js index 96c48f02f..0cf13db2c 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -21,13 +21,11 @@ */ var Layout = require("Layout"); +var settings = require('Storage').readJSON("messages.settings.json", true) || {}; var fontSmall = "6x8"; var fontMedium = g.getFonts().includes("6x15")?"6x15":"6x8:2"; var fontBig = g.getFonts().includes("12x20")?"12x20":"6x8:2"; var fontLarge = g.getFonts().includes("6x15")?"6x15:2":"6x8:4"; -var colBg = g.theme.dark ? "#141":"#4f4"; -var colSBg1 = g.theme.dark ? "#121":"#cFc"; -var colSBg2 = g.theme.dark ? "#000":"#9F9"; // hack for 2v10 firmware's lack of ':size' font handling try { g.setFont("6x8:2"); @@ -143,8 +141,8 @@ function showMapMessage(msg) { eta = m[2]; } else target=msg.body; layout = new Layout({ type:"v", c: [ - {type:"txt", font:fontMedium, label:target, bgCol:colBg, fillx:1, pad:2 }, - {type:"h", bgCol:colBg, fillx:1, c: [ + {type:"txt", font:fontMedium, label:target, bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2 }, + {type:"h", bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, c: [ {type:"txt", font:"6x8", label:"Towards" }, {type:"txt", font:fontLarge, label:street } ]}, @@ -181,7 +179,7 @@ function showMusicMessage(msg) { checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); } layout = new Layout({ type:"v", c: [ - {type:"h", fillx:1, bgCol:colBg, c: [ + {type:"h", fillx:1, bgCol:g.theme.bgH, col: g.theme.fgH, c: [ { type:"btn", src:getBackImage, cb:back }, { type:"v", fillx:1, c: [ { type:"txt", font:fontMedium, label:msg.artist, pad:2 }, @@ -214,7 +212,9 @@ function showMessageScroller(msg) { // a function to draw a menu item draw : function(idx, r) { // FIXME: in 2v13 onwards, clearRect(r) will work fine. There's a bug in 2v12 - g.setBgColor(idx=lines.length-2) @@ -270,13 +270,31 @@ function showMessage(msgid) { var title=msg.title, titleFont = fontLarge, lines; if (title) { var w = g.getWidth()-48; - if (g.setFont(titleFont).stringWidth(title) > w) - titleFont = fontMedium; + if (g.setFont(titleFont).stringWidth(title) > w) { + titleFont = fontBig; + if (settings.fontSize!=1 && g.setFont(titleFont).stringWidth(title) > w) + titleFont = fontMedium; + } if (g.setFont(titleFont).stringWidth(title) > w) { lines = g.wrapString(title, w); title = (lines.length>2) ? lines.slice(0,2).join("\n")+"..." : lines.join("\n"); } } + // If body of message is only two lines long w/ large font, use large font. + var body=msg.body, bodyFont = fontLarge; + if (body) { + var w = g.getWidth()-10; + if (g.setFont(bodyFont).stringWidth(body) > w * 2) { + bodyFont = fontBig; + if (settings.fontSize!=1 && g.setFont(bodyFont).stringWidth(body) > w * 3) + bodyFont = fontMedium; + } + if (g.setFont(bodyFont).stringWidth(body) > w) { + lines = g.setFont(bodyFont).wrapString(msg.body, w); + var maxLines = Math.floor((g.getHeight()-110) / g.getFontHeight()); + body = (lines.length>maxLines) ? lines.slice(0,maxLines).join("\n")+"..." : lines.join("\n"); + } + } function goBack() { msg.new = false; saveMessages(); // read mail cancelReloadTimeout(); // don't auto-reload to clock now @@ -303,27 +321,17 @@ function showMessage(msgid) { checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); }}); } - // If body of message is only two lines long w/ large font, use large font. - var body=msg.body, bodyFont = fontLarge, lines; - if (body) { - var w = g.getWidth()-48; - if (g.setFont(bodyFont).stringWidth(body) > w * 2) - bodyFont = fontMedium; - if (g.setFont(bodyFont).stringWidth(body) > w) { - lines = g.setFont(bodyFont).wrapString(msg.body, g.getWidth()-10); - body = (lines.length>4) ? lines.slice(0,4).join("\n")+"..." : lines.join("\n"); - } - } + layout = new Layout({ type:"v", c: [ - {type:"h", fillx:1, bgCol:colBg, c: [ + {type:"h", fillx:1, bgCol:g.theme.bgH, col: g.theme.fgH, c: [ { type:"btn", src:getMessageImage(msg), col:getMessageImageCol(msg), pad: 3, cb:()=>{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, { type:"v", fillx:1, c: [ - {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:colBg, fillx:1, pad:2, halign:1 }, - title?{type:"txt", font:titleFont, label:title, bgCol:colBg, fillx:1, pad:2 }:{}, + {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2, halign:1 }, + title?{type:"txt", font:titleFont, label:title, bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2 }:{}, ]}, ]}, {type:"txt", font:bodyFont, label:body, fillx:1, filly:1, pad:2, cb:()=>{ @@ -374,9 +382,8 @@ function checkMessages(options) { c : Math.max(MESSAGES.length+1,3), // workaround for 2v10.219 firmware (min 3 not needed for 2v11) draw : function(idx, r) {"ram" var msg = MESSAGES[idx-1]; - if (msg && msg.new) g.setBgColor(colBg); - else g.setBgColor((idx&1) ? colSBg1 : colSBg2); - g.clearRect(r.x,r.y,r.x+r.w-1,r.y+r.h-1).setColor(g.theme.fg); + if (msg && msg.new) g.setBgColor(g.theme.bgH).setColor(g.theme.fgH); + else g.setColor(g.theme.fg); if (idx==0) msg = {id:"back", title:"< Back"}; if (!msg) return; var x = r.x+2, title = msg.title, body = msg.body; @@ -391,18 +398,20 @@ function checkMessages(options) { .setColor(fg); // only color the icon x += 50; } - var m = msg.title+"\n"+msg.body; - if (msg.src) g.setFontAlign(1,1).setFont("6x8").drawString(msg.src, r.x+r.w-2, r.y+r.h-2); + var m = msg.title+"\n"+msg.body, longBody=false; if (title) g.setFontAlign(-1,-1).setFont(fontBig).drawString(title, x,r.y+2); if (body) { g.setFontAlign(-1,-1).setFont("6x8"); - var l = g.wrapString(body, r.w-14); + var l = g.wrapString(body, r.w-(x+14)); if (l.length>3) { l = l.slice(0,3); l[l.length-1]+="..."; } + longBody = l.length>2; g.drawString(l.join("\n"), x+10,r.y+20); } + if (!longBody && msg.src) g.setFontAlign(1,1).setFont("6x8").drawString(msg.src, r.x+r.w-2, r.y+r.h-2); + g.setColor("#888").fillRect(r.x,r.y+r.h-1,r.x+r.w-1,r.y+r.h-1); // dividing line between items }, select : idx => { if (idx==0) load(); @@ -422,7 +431,7 @@ g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); setTimeout(() => { - var unreadTimeoutSecs = (require('Storage').readJSON("messages.settings.json", true) || {}).unreadTimeout; + var unreadTimeoutSecs = settings.unreadTimeout; if (unreadTimeoutSecs===undefined) unreadTimeoutSecs=60; if (unreadTimeoutSecs) unreadTimeout = setTimeout(function() { diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index 7488c792e..e8ed83099 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.22", + "version": "0.23", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", diff --git a/apps/messages/screenshot.png b/apps/messages/screenshot.png index a95045400bf4ef49d1e3a6df99cca54b8cb73aff..a64416f7d47d1918e3f1d8928b80517b4bd33f32 100644 GIT binary patch delta 4185 zcmV-f5T@_*7UCd~Fn$>6~4Al33XwTOw9z-BBA>3;A&+b|XVKPiZ zsP+DMJRUdy;|Oeuz}*SFY2@7P69JLH_xt?~RS@gkXO8EZ2*j~k!9(VTAE;N$5uCs) zM75(2S0L~KPl?1;0;7{>R#nGXx#eRd>pti;bde;G4z z6E_xaAI%y8C$Kf5Zf__8I}+GDg&2ys4`zzMZUm0YX(pREQ#9S!a0FH(aBbg|)`HE- zXr)2JfyVHt_<%41yAZg`K}PNPPjfT~qwWpO5ZHylxqk^aoy66Si~T6sj9=Xits*oU zKf0t4aoXT1M0fr*51=7V^Pm|68b3@naVbgDM=76$W`7#3N6;;7=Hg{xS8IdeN?cB( zPvQ`wx&mv%IIiCn2<#_uY7kOtnRU7xL zYdVQn49yguz6rdb@}_qHSK=vLS#r=%0xzt*DSAJp#K>FjBzj%+&hO@Sry-X6D74xFu4FwY&=6n_|1XS5v?|FpE#dU#MOm6gh6jIS4HJ4S&+ z741;mP{)kPulQPNRe_PGw~#h$fJ-(l#;Vz{u+PqQk@js0%qV7S-8bzoDR52sY6k|| zz(^#Lu1n)OfwKtNDsWKJP<4ovwU%!5Qs5kkYqw;HM78S@L8a@`*iK-K!0fXSAAh-Q zX2X`vfiq7WpY0e$M-({yq1~7SrGFR8fYPsx6n+a8A${7W_Ark2nlwf!cR%_`4+rJu zDE-KBoWs|S$AvwFy#gaAak+zJ@(C#_2hODovkA=R%Nhk{$3Pb^>Wg&ONv|vXZO(xq z1%9u#g2r0cfpb8lianFSY+y@j6@LgaI3SWcOJARWl`Alk|022X(#$e;j?7byNB=Nae8F|kL4R9q56ypDo%Q}* z5h(t|z_Rt=TK%^xRBn7l1jHYCS;=Wv-j$-UhA;jzTWiF@y-*@hC$Q3}cXI?rA>afa zg|v^;1py~;7g*isC+kjF9lTsQh%DLR)LvuwPR>}m;92h z*T#(dN_Mnut@a092|Qx*Qt(sN%q4 zsMq9?u~Aj21+12eNVoh`4GJ5=7XNd7TkJ{X?iIt*xUF+(N+FKHOS!D%SPdvP#bAPB zL0~qAldxbHUw?}|1}kYChV07`I1XaEAv*rwGWnGWT$|S@1&-BTyGcX{#l%qSlQf37 z;4~>jY2`61az_Q0z#d6pR<$J}oobm=;?V9>jlG-eNMXaz<~Nyv#* z%gK@iRxJmMud%64N@`{U6?{&|FWJbokMDk^>$w!qYQaeJ)%wI@^Rd8D1!h3#*;Yf| zp8o7=yMLD=j>ZGdfk!*$|)Y*1g357sVl5fklX}-5||Bk$uieh&X{) ziiZ0_Bk&Uh)^7X|b<)~SD;liwG2^!E@=KK$)?b>LUq6(x)&Xd0Dj^#{d8YRBM)EKCgnTl+YH z6MqC*LbB~sQfWve5mQQkP%>)f)=EgW|1tz-^4D~d3<;RFNT4-Ab_Hf>T5i7tfm`x4 zM2&KUksw50yy66wknDSXI)OEc*i(UXaI*`HnG@3%O%2d?nz5xmed+pb-3bgJ?gajS zrLGeg*fgOEg5;>|rpXof9|28z1n7ZjlYi+7EakB1if2@kX{+_GG)BBx)qbT(@`(`u zODs&82^w31z;QrIej_JxOeLe%RyxtDouDD#2Mlv;A#e$^(svD!FXPs*FX4s61>~Zt z*)jxHdB15V^sch$^oF|a1Re_ab1)~c9q3MAJ1ikfPF@HmxRDbWhKg&5;#@fU?gXj76!B6n6~ri z$dCM!1eRcu9;XcbkA25wvBV%G-q$kt$&BH&tRaR zBXCUO9Dc1Evr3a=aQjerxlH^Oee zD*|5xMxScx>ecObvv}a9w||enWPep&d=U6>auwpt^ktP`#S3I+TxP~16^YcBH-W>2 z`=NeEeQkliZxa^Oia4C{n1IDuXMK&k0v`e|V_uvDo&^qa3m)m)$gz;QOX{Ps!Sq=f zkB^0QKK;Ld;+B+ugc7f)G+8_bDe(??9K1MrJ2SsR6rr~g^tO-8k$-73!ru{NFmuke zJ$!r<_?H#<+_XI&%jEvj9>niR&pnze@M~G`pf<4rjqrEG7_Pvr2t)*S1^xt+&VgTV zDpKR9=-;fsqgH9}aeCWF)>)`MBm0pN{xV~vb#r76=^aH=^KQ$56)Q%{?PgUWX6L|% zlDz)_x%g5!aP0dh3xBaaMMHnJ0>>+kU2TXOjjn$(YNPSL)<>gWBm70jNd0G&w54x2 zWZ|n2r4=JZ7EqR7Q{WHf4fp{#Ev3M(YCtjkrTJ8Ngq};#3S3(;5`X{W^Z&!qXdhG! zP0I@5LX)iK1X)r?3!jL)q*tw1HS38E5A1ns?95~H+ zz?>~dDpZMk=X|3SxK(*qSK!z`Mnq5^qXs$-L06qt4Nwq!+b`va==^8o z?5&ufO0318Nq>PqRvMtd)s+eKUqyj~g0hNXrM$Z+Fsj5Xj;0EXs#{Jy;?Iy3*s2DS zuc&=Z{o5kv-BE$1$^^R)Dphi*DunhV?W1413*AtG1DKM6SS#;V3XGl?0P(M#571Qz zNzJ6|E1o=Q6gVbvNgdM9k-LqAUtHos+G^XNn4oj7`G29srR`Y=?Ke0!R^ag6v>Y+x zdTB4^-9mv;<^2W`dv+q?T~if8v$8enJ3?_-wW;N`J#yY%a$w}y2BZzjt>FrsDwC8$ zj#3;|9T-)bh8%C!vmvo)z$bCU2^(}`2i)O@DR61kp}7yMkmw2y?X>o#S|>WcQT{UH zFqmjmRe#ebcPBEfLQv025X!Vl9k}!@;VdzT`LWfV-gr<7Oek-zj$2$*0Dh(lEU8iK zD63428Zau;s=#somie(h_r`S6Lxob{XX6hJ zqI;Xti5=SCRDr{!OKO6ws8ZkFiqqRZtFTi05r6)&V+1AE##z(fR)K+CBb)0jU4`g4 zUkRt)cO+JUC4YNeH&EHpcfR6sSM;%IPG#Ba}BL_R@Ez@ZRF^ zYEsG-SKJJrW{fGR;Yj68eOVEY*r%_b7+6M$2P$taXb7oBw$YZSEPPx_i4$JN+cKme#x~O-IKU=Kj`$Sq0~_ z>Quv4Vl{6(`rd#cZKUP=$bvfhxauB7#4p(K>cgf+kR!jPIdjgyk`xO&pH!xJ6&KRH zMZdn?{2VEO*YWe{rf+{lK^Ob3AMs?`6534|So5NxUAgAK)XH%h;80@|<_F(dS!hxH zL4d7b{;s|_U8Tui!;qZS_o}&z@Mc(KJI!^)N=pF$HnjhAlRH}uhMYh5?(TSbn~j4Y z44EAn2eMX3TVbENsTanatAmxL%`~G?u+kV`@eumd*->!U))+ms%_C^fnC&y@1~Txt zYG`3bV`B8e)#a>Xs6-+_Xl^Y=k z4nK{1kKmY$X}fR|&c3cO+<)NV4DyFjrhEI?M&1lLiG%%c?ZNVyD`x`RpcB%;@(>=m z(rfCa-21%}cym?$ND1wMKaZTUW>RZ7xWxG~=(F4KVRLoT&@wWMjpxh3bTBW?ILg6P zJ5lcfTl1c<796wk*M*g&>Z0j*U38CQ>&gegFWg)Ly3la-Mg0eVmCeMx7-cOO4lz=d zTY$=YUGI^p{H@A*4$*Ptp#|kr)IXD&a|~#q%|Dt-$~V03peIve)D>n7ms*PA7?z=r8O>>rtDl$e8HHgckgH4l zhB4`m?s3#rjt4(j2OHJyn>eCk+TOJIP_xG3!aj)n77uG@S0y++cY-!$-~2muM?*Ut zb%aCH^vCtndQudAax`+TNU1KWsarLj|ArbX$mf4{%8`eWk+~Ys>4DpEAyLDR5w*RG zRu!ftVTp*fiwA3C(QL0|BOx(HkF4yLvS9mdtNjTDq~8|8LU?)FcFyz{x9}0l z?CWHkd-`2p_d8^a#YeuogWn63ZPmL8y8Dc~6nN|{GH<)9#G&e2r~3NYzzfRK?UlJ0 zl2?t|PPxPJpOr`z0th{^#7G#D|MIMz#eoxhM955GXXLz|g^;xrz^=f3%XI>XYD`NB zXF&k*8h)U967Wqokg#@x0NENg7RLnvPi4^~C)@#IS>Ldu6$B`_1U>&hZB>OJeLfm` zYXr0*%K{?$d(Bu#)~#y)qEr6mtC@rJJ%OnCfOJ)3W-!Vn?hQX3pAaLU2W-neOyV~J zrP+l^%;4BUo%b<+CuSyAjq0|QCLe7!jC?XbwRmr$+jM`dyP@K3Pl&?m1H_Q*s0IIf z0pOJ`FNk>KdZzM-Hmo&m(u9Bp(Egt5p5ZAZF>-FJRB4gIJ7}>m3mU2hl2yn3IBE#V zIW3UDR|HX7#R+m*4897a(X!^at9`{bvl#2w=IgncxqH$}W$GzC1LhHEF>Y3<;bYc%k{}p(db zH=%$UY{6AM%#EIB#L3z>rZwNeqq^V63~2g07YP&d>&|O+3IS`i0kKXlmU6z1T$9#| z3s+?cw=^~|g5jS$hu z0%eIkPB7mKy5Zt=G@+XG(0u7##O_OrEN5OgO;`MR)BR~WIxl8RaqjZmnBC)XB%$W^ zZc>C6Kn0d3pVgdaw{J8 zZ96s2wFC5S0A%@G{Bar8WT>Ss8d57=6s1MXeaJqYJMh0@+vKgkiIQ&m2xvY zWBfZJzO{m=Jr5fD&KI~zGSUWL4>4{&4OVhZU7aks6umIl^mWJJK5gI0G)Yruh*OQp zHY*tR|A;kU44sCpIY7)Zs3n_}?AyVZBq^|3(n^X-ne9_RcJyHklVizPSd`n@y-*DR zEFvgryb=JGPd*4L5&~+2d`Nwj0APCek0<2-1HQJXU}$&pA$2i1BZjvf-HLuJ3>tie%GkfOhEroCjtha zE|Y-j0lJVKc)(rZ94iqJV2H3K{c@h7|4G5St3N17(8fF-JT~wu_ImbiDr|+4lBcKAgdoh zti6IGX4|iq-8PK|WQl>(29n1Btf-!mzH)KVZ2&I=sx&<@-|v{b^3zJ!fukI-ddM+G z!BMc9gIY@AO%Z*FHpMb9YPlGU^$FB{W#CwFtQimi+r~QeVJlY*Hjzz_S{^FJsHps# zP7kmdgbyG`L3$V)v)g?b-Ts#HEkJ~Ey^PTO$h#k+OP5f@^SK_FEoW!)Gvb6>x?D3v h0=qG5Oh v?v+"s":/*LANG*/"Off", onchange: v => updateSetting("unreadTimeout", v) }, + /*LANG*/'Min Font': { + value: 0|settings().fontSize, + min: 0, max: 1, + format: v => [/*LANG*/"Small",/*LANG*/"Medium"][v], + onchange: v => updateSetting("fontSize", v) + }, }; E.showMenu(mainmenu); }) From 17b7d85950e4c6339f9250a858cf18e9ad8f057c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 10:45:18 +0000 Subject: [PATCH 141/199] Layout: remove 'fsz' hack as any firmware 2v11+ will support font size in the string now --- modules/Layout.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 1b0bbd47f..4223867a4 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -180,13 +180,6 @@ function Layout(layout, options) { if (l.id) ll[l.id] = l; // fix type up if (!l.type) l.type=""; - // FIXME ':'/fsz not needed in new firmwares - Font:12 is handled internally - // fix fonts for pre-2v11 firmware - if (l.font && l.font.includes(":")) { - var f = l.font.split(":"); - l.font = f[0]; - l.fsz = f[1]; - } if (l.c) l.c.forEach(recurser); } recurser(this._l); @@ -241,13 +234,13 @@ Layout.prototype.render = function (l) { "":function(){}, "txt":function(l){ if (l.wrap) { - g.setFont(l.font,l.fsz).setFontAlign(0,-1); + g.setFont(l.font).setFontAlign(0,-1); var lines = g.wrapString(l.label, l.w); var y = l.y+((l.h-g.getFontHeight()*lines.length)>>1); // TODO: on 2v11 we can just render in a single drawString call lines.forEach((line, i) => g.drawString(line, l.x+(l.w>>1), y+g.getFontHeight()*i)); } else { - g.setFont(l.font,l.fsz).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); + g.setFont(l.font).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); } }, "btn":function(l){ var x = l.x+(0|l.pad), y = l.y+(0|l.pad), @@ -365,7 +358,7 @@ Layout.prototype.update = function() { if (l.wrap) { l._h = l._w = 0; } else { - var m = g.setFont(l.font,l.fsz).stringMetrics(l.label); + var m = g.setFont(l.font).stringMetrics(l.label); l._w = m.width; l._h = m.height; } }, "btn": function(l) { From d79915d67e068bad2e7e2e864367b0edba564313 Mon Sep 17 00:00:00 2001 From: pkkpp <52079346+pkkpp@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:49:19 +0100 Subject: [PATCH 142/199] Update 7x7dotsclock.app.js --- apps/7x7dotsclock/7x7dotsclock.app.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index 53b4c1bd6..aa174b2d2 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -17,22 +17,27 @@ switch(settings.ColorMinutes) { case "blue": var mColor = [0.3,0.3,1]; var sColor = [0,0,1]; + var sbColor = [1,1,1]; break; case "pink": var mColor = [1,0.3,1]; var sColor = [1,0,1]; + var sbColor = [1,1,1]; break; case "green": var mColor = [0.3,1,0.3]; var sColor = [0,1,0]; + var sbColor = [1,1,1]; break; case "yellow": var mColor = [1,1,0.3]; var sColor = [1,1,0]; + var sbColor = [0,0,0]; break; default: var sColor = [0,0,1]; var mColor = [0.3,0.3,1]; + var sbColor = [1,1,1]; } const bColor = [0.3,0.3,0.3]; @@ -134,7 +139,8 @@ var dho = -1, eho = -1, dmo = -1, emo = -1; function drawHSeg(x1,y1,x2,y2,Num,Color,Size) { - //g.setColor(0,0,0); + + g.setColor(g.theme.bg); g.fillRect(x1, y1, x2, y2); for (let i = 1; i < 8; i++) { @@ -172,10 +178,10 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { } -function ShowSecons() { - //g.setColor(bColor[0],bColor[1],bColor[2]); - //g.setColor(0.7,0.7,0.7); - g.setColor(g.theme.fg); +function ShowSeconds() { + + g.setColor(sbColor[0],sbColor[1],sbColor[2]); + g.fillRect((Xe-Xs) / 2 - 14 + Xs -4, (Ye-Ys) / 2 - 7 + Ys -4, (Xe-Xs) / 2 + 14 + Xs +4, @@ -238,7 +244,7 @@ function draw() { emo = em; } - if (!Bangle.isLocked()) ShowSecons(); + if (!Bangle.isLocked()) ShowSeconds(); } From 0ef8ad6d5ec30ff936c0c2bd26876fcf0dd485d5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 12:10:14 +0000 Subject: [PATCH 143/199] add simple interlaced font clock --- apps/intclock/ChangeLog | 12 +++++++ apps/intclock/README.md | 4 +++ apps/intclock/app-icon.js | 1 + apps/intclock/app.js | 60 +++++++++++++++++++++++++++++++++++ apps/intclock/app.png | Bin 0 -> 3480 bytes apps/intclock/metadata.json | 16 ++++++++++ apps/intclock/screenshot.png | Bin 0 -> 2101 bytes 7 files changed, 93 insertions(+) create mode 100644 apps/intclock/ChangeLog create mode 100644 apps/intclock/README.md create mode 100644 apps/intclock/app-icon.js create mode 100644 apps/intclock/app.js create mode 100644 apps/intclock/app.png create mode 100644 apps/intclock/metadata.json create mode 100644 apps/intclock/screenshot.png diff --git a/apps/intclock/ChangeLog b/apps/intclock/ChangeLog new file mode 100644 index 000000000..aa910b6f6 --- /dev/null +++ b/apps/intclock/ChangeLog @@ -0,0 +1,12 @@ +0.02: Modified for use with new bootloader and firmware +0.03: add hour ticks, remove timers +0.04: add day-date display +0.07: make date and face bigger +0.08: make dots bigger and date more readable +0.09: center date, remove box around it, internal refactor to remove redundant code. +0.10: remove debug, refactor seconds to show elapsed secs each time app is displayed +0.11: shift face down for widget area, maximize face size, 0 pad single digit date, use locale for date +0.12: Fix regression after 0.11 +0.13: Fix broken date padding (fix #376) +0.14: Remove hardcoded hour buzz (you can install widchime if you miss it) +0.15: Add color scheme support diff --git a/apps/intclock/README.md b/apps/intclock/README.md new file mode 100644 index 000000000..7d31cdae2 --- /dev/null +++ b/apps/intclock/README.md @@ -0,0 +1,4 @@ +# Analogue Clock + +![](screenshot_analog.png) + diff --git a/apps/intclock/app-icon.js b/apps/intclock/app-icon.js new file mode 100644 index 000000000..8c62a192e --- /dev/null +++ b/apps/intclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgP/AH4Aq+GEkPh4E/BZMAh4LGw/h8MPBZHggIXJ/EB4ALI//h/4LHwk/BagA/ACY=")) diff --git a/apps/intclock/app.js b/apps/intclock/app.js new file mode 100644 index 000000000..1324a422c --- /dev/null +++ b/apps/intclock/app.js @@ -0,0 +1,60 @@ +Graphics.prototype.setFontUndo = function(scale) { + // Actual height 19 (20 - 2) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqKAqooCqigKqKAAAACgAAKAAAoAACgAAAAAAAAACgAAKAAAoAACgAAAAAAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAAAAAKgoAqCgKqKAqooKiioqKKiooqKiioKKqAoqoCgqAKCoAAAACoCgKgKAiCoCIKgKioAqKgACoAAKgACoAAKgACoqAKioCoIgKgiAoCoCgKgAAAAKqgAqqAKqqAqqoKiioqKKiooqKiioKAKAoAoCgCgKAKAAAACgAAKAAAoAACgAAAAAAKqgAqqAKqqAqqoCgCgKAKAAAACgCgKAKAqqoCqqgCqoAKqgAAAACigAKKAAqoACqgAqoACqgAKqAAqoAAqoACqgAKKAAooAAAAAAoAACgAAKAAAoAAqqACqoAKqgAqqAAKAAAoAACgAAKAAAAAAACoAAKgAAqAACoAAAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAAAAACgAAKAAAoAACgAAAAAAoAACgAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAKAAAoAAAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoAAAAKCqAoKoCiqgKKqAoooCiigKKKAoooCqigKqKAKgoAqCgAAAAoAoCgCgKAKAoAoCiigKKKAoooCiigKqqAqqoAqqACqoAAAACqAAKoAAqoACqgAAKAAAoAACgAAKAAqqoCqqgKqqAqqoAAAAKoKAqgoCqigKqKAoooCiigKKKAoooCiqgKKqAoKgCgqAAAAAKqgAqqAKqqAqqoCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKAAAoAACgAAKAAAqqoCqqgCqqAKqoAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCqqgKqqAKqgAqqAAAAAKgAAqAAKqAAqoACigAKKAAooACigAKqqAqqoAqqgCqqAAAACgCgKAKAoAoCgCgAAAAoAqCgCoKAKgoAqAAAAAKAAAoAAKoAAqgAKqgAqqAKgqAqCoCgCgKAKAAAAAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAAAAKAKAoAoCoKgKgqAKqgAqqAAqgACqAACgAAKAAAAACgAAKAAAoAACgAAKKKAoooCiigKKKAqoACqgACoAAKgAAAAACqqAKqoCqqgKqqAoAACgAAKCoAoKgCiqgKKqAoooCiigKqqAqqoAqqACqoAAAAAqqgCqqAqqoCqqgKKAAooACigAKKAAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAoooCiigKKKAoooCqqgKqqAKCgAoKAAAAAKqgAqqAKqqAqqoCgCgKAKAoAoCgCgKAKAoAoCgCgKAKAAAACqqgKqqAqqoCqqgKAKAoAoCoKgKgqAKqgAqqAAqgACqAAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCgCgKAKAoAoCgCgAAAAKqoAqqgKqqAqqoCigAKKAAooACigAKAAAoAACgAAKAAAAAAAqqACqoAqqoCqqgKAKAoAoCiigKKKAoqoCiqgKKqAoqoAAAAKqqAqqoCqqgKqqAAoAACgAAKAAAoACqqgKqqAqqoCqqgAAAAoAoCgCgKAKAoAoCqqgKqqAqqoCqqgKAKAoAoCgCgKAKAAAAAAKAAAoAACoAAKgAAKAAAoAACgAAKAqqoCqqgKqoAqqgAAAAKqqAqqoCqqgKqqACqAAKoACqoAKqgCoKgKgqAoAoCgCgAAAAqqgCqqAKqqAqqoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAKgAAqAAKqqAqqoCqqgKqqAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAqqoCqqgKqqAqqoAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoCigAKKAAooACigAKqAAqoAAqAACoAAAAAAqqACqoAqqoCqqgKAKAoAoCgKgKAqAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAooACigAKKgAoqACqqgKqqAKioAqKgAAAAKgoAqCgKqKAqooCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKqqAqqoCqqgKqqAoAACgAAKAAAoAAAAAAKqoAqqgCqqgKqqAAAoAACgAAKAAAoCqqgKqqAqqgCqqAAAAAqqACqoAKqoAqqgAAKgAAqAACoAAKgKqoAqqgCqoAKqgAAAACqqgKqqAqqoCqqgACoAAKgACoAAKgAAKgAAqAKqqAqqoCqqgKqqAAAACoKgKgqAqqoCqqgAqgACqAAKoAAqgAqqoCqqgKgqAqCoAAAAKoAAqgACqgAKqAAAqoACqgAKqAAqoCqgAKqAAqgACqAAAAAAoCoCgKgKCqAoKoCiqgKKqAqooCqigKoKAqgoCoCgKgKAAAACqqgKqqAqqoCqqgKAKAoAoAAAAKAAAoAACoAAKgAAKgAAqAAAqAACoAACoAAKgAAKgAAqAAAqAACoAACgAAKAAAACgCgKAKAqqoCqqgKqqAqqoAAA"), 32, atob("DQULDw0RDQUHBw0NBQ0FEQ0FDQ0NDQ0NDQ0FBQsNCw0RDQ0NDQ0NDQ0NDQ0NDw0NDQ0NDQ0NDQ8NDQ0HEQc="), 22+(scale<<8)+(1<<16)); + return this; +} + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function draw() { + var x = g.getWidth()/2; + var y = g.getHeight()/2 - 10; + g.reset(); + // work out locale-friendly date/time + var date = new Date(); + var timeStr = require("locale").time(date,1).trim(); + var dateStr = require("locale").date(date).toUpperCase(); + + + // draw time + g.setFontAlign(0,0).setFont("Undo:3"); + g.clearRect(0,y-30,g.getWidth(),y+30); // clear the background + g.drawString(timeStr,x,y); + // draw date + y += 40; + g.setFontAlign(0,0).setFont("Undo"); + g.clearRect(0,y-10,g.getWidth(),y+20); // clear the background + g.drawString(dateStr,x,y); + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/intclock/app.png b/apps/intclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..dacbceb733035cae976a896ffdb648fe7c578234 GIT binary patch literal 3480 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 Bg0lbs literal 0 HcmV?d00001 diff --git a/apps/intclock/metadata.json b/apps/intclock/metadata.json new file mode 100644 index 000000000..fff4c58b0 --- /dev/null +++ b/apps/intclock/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "intclock", + "name": "Interlaced Clock", + "version": "0.01", + "description": "A lightweight digital clock using an 'interlaced' font", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"intclock.app.js","url":"app.js"}, + {"name":"intclock.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/intclock/screenshot.png b/apps/intclock/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..33a459f1f768a3421412409d86188397e04fa723 GIT binary patch literal 2101 zcmeHJ{ZrEU7XBcOAgR|oWmyW9Jw{{qK#xyx622d~C+^H}#*hUvK<>uYmb}u;n=H#n4f8{UfF=s9e(fDZWro)F z)yjt=Lzl7two^eP8dsXZp#JO63*Vm0w&TQ_5>Y2DVI+pWs{8r_Y_R)w2 zUg7Xz)DJXX065UPM9=QOOEA;-Gwz4b!)%!(akiLavx5F06`vpLCOacDb@Z^0nH-zL z!)-x{%8wG>F8EQi^{i-~n>{3MAuY`=2uH{6ak|N4@4eE~zlAlOvs_c1+r)Uj<=Qn` zsmA#1))V{=e%{=WMB--+^qeOEkE*Ln3fzQyi@dVRKq%{eVn1lv39S$>PjE#~u+*uJ z!wM$bEB^HG0BCtO>wZ-2=6TZILcj1^*;c7s+TK$){-#2Q6llB)^(%1*Lhb1 zXP&7F)sClV$4K4ilxR$^51V==SN-K zZ09&F?5#IgK-C9aF$ha*MQZjz!%G_n3Joy1GZFeYYXyp`8Hl??W7 zww;zW;Q##d?ab|&C>XSB7qEoFxe?1~oMbO*4C26rI!Kfc@3sci`f^#LoD~d9Xr8*6 zit1KTOkeE$DsF|WYMNfr9 zkdNYd-~e>+PAe-oar`Xq#?2~+-!+o^(}|Vxa+0Yj--ZxQa0}e=9Y#uAF^BLu_Yavv z0pHj$;Tfiro9kkK7{KXk;lR?CbOb;oF>xMP!v6@`p!n}Q+3L|WhICH0_=_q?j8)f+ zWQI1jgxn*g((8Ih+r2YKJ+_AV?v}h@VGv%RL3eb;NnhiRp-*|X6g9T{D*S}(17U^C<7k_;Tr%c*d#5Q5zU5pvIWplWD`ANlC=D<9=F5nN;=YnWR_SEtv_L&XnSuO6`aT!jhVMC|-xo23Ero+( p7yrH9V889vqjmqs|Eq%$wtH_rNf=6*H2nd<$NQ@jHC|!Y{{!gi${GLw literal 0 HcmV?d00001 From a452887ba6b8bdc1f33fdcc940d1aaf2dfc84227 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:11:34 +0000 Subject: [PATCH 144/199] Fix settings wrapping code for new menu system --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 16 ++++++++-------- apps/alarm/metadata.json | 2 +- apps/hardalarm/ChangeLog | 1 + apps/hardalarm/app.js | 18 +++++++++--------- apps/hardalarm/metadata.json | 2 +- apps/tabata/ChangeLog | 1 + apps/tabata/metadata.json | 2 +- apps/tabata/tabata.js | 19 +++++++++---------- 9 files changed, 32 insertions(+), 30 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index d129e9f9f..4576237a5 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -13,3 +13,4 @@ Widgets now shown on Alarm screen 0.13: Alarm widget state now updates when setting/resetting an alarm 0.14: Order of 'back' menu item +0.15: Fix hour/minute wrapping code for new menu system diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 17062d44a..f7edcd1c4 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -73,12 +73,12 @@ function editAlarm(alarmIndex) { '': { 'title': /*LANG*/'Alarm' }, /*LANG*/'< Back' : showMainMenu, /*LANG*/'Hours': { - value: hrs, - onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' + value: hrs, min : 0, max : 23, wrap : true, + onchange: v => hrs=v; }, /*LANG*/'Minutes': { - value: mins, - onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this' + value: mins, min : 0, max : 59, wrap : true, + onchange: v => mins=v; }, /*LANG*/'Enabled': { value: en, @@ -138,12 +138,12 @@ function editTimer(alarmIndex) { const menu = { '': { 'title': /*LANG*/'Timer' }, /*LANG*/'Hours': { - value: hrs, - onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' + value: hrs, min : 0, max : 23, wrap : true, + onchange: v => hrs=v; }, /*LANG*/'Minutes': { - value: mins, - onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this' + value: mins, min : 0, max : 59, wrap : true, + onchange: v => mins=v; }, /*LANG*/'Enabled': { value: en, diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index 3e109bda9..d29298309 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Default Alarm & Timer", "shortName": "Alarms", - "version": "0.14", + "version": "0.15", "description": "Set and respond to alarms and timers", "icon": "app.png", "tags": "tool,alarm,widget", diff --git a/apps/hardalarm/ChangeLog b/apps/hardalarm/ChangeLog index 7e9b17f2a..dac7d317e 100644 --- a/apps/hardalarm/ChangeLog +++ b/apps/hardalarm/ChangeLog @@ -1,2 +1,3 @@ 0.01: Add a number to match to turn off alarm 0.02: Respect Quiet Mode +0.03: Fix hour/minute wrapping code for new menu system diff --git a/apps/hardalarm/app.js b/apps/hardalarm/app.js index 61467b421..09b73d318 100644 --- a/apps/hardalarm/app.js +++ b/apps/hardalarm/app.js @@ -56,25 +56,25 @@ function editAlarm(alarmIndex) { } const menu = { '': { 'title': 'Alarms' }, - 'Hours': { - value: hrs, - onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' + /*LANG*/'Hours': { + value: hrs, min : 0, max : 23, wrap : true, + onchange: v => hrs=v; }, - 'Minutes': { - value: mins, - onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this' + /*LANG*/'Minutes': { + value: mins, min : 0, max : 59, wrap : true, + onchange: v => mins=v; }, - 'Enabled': { + /*LANG*/'Enabled': { value: en, format: v=>v?"On":"Off", onchange: v=>en=v }, - 'Repeat': { + /*LANG*/'Repeat': { value: en, format: v=>v?"Yes":"No", onchange: v=>repeat=v }, - 'Auto snooze': { + /*LANG*/'Auto snooze': { value: as, format: v=>v?"Yes":"No", onchange: v=>as=v diff --git a/apps/hardalarm/metadata.json b/apps/hardalarm/metadata.json index 13a8fb920..1dab4501d 100644 --- a/apps/hardalarm/metadata.json +++ b/apps/hardalarm/metadata.json @@ -2,7 +2,7 @@ "id": "hardalarm", "name": "Hard Alarm", "shortName": "HardAlarm", - "version": "0.02", + "version": "0.03", "description": "Make sure you wake up! Count to the right number to turn off the alarm", "icon": "app.png", "tags": "tool,alarm,widget", diff --git a/apps/tabata/ChangeLog b/apps/tabata/ChangeLog index 5560f00bc..86faf17a5 100644 --- a/apps/tabata/ChangeLog +++ b/apps/tabata/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Fix settings wrapping code for new menu system diff --git a/apps/tabata/metadata.json b/apps/tabata/metadata.json index 14429090f..a840c9c8b 100644 --- a/apps/tabata/metadata.json +++ b/apps/tabata/metadata.json @@ -2,7 +2,7 @@ "id": "tabata", "name": "Tabata", "shortName": "Tabata - Control High-Intensity Interval Training", - "version": "0.01", + "version": "0.02", "description": "Control high-intensity interval training (according to tabata: https://en.wikipedia.org/wiki/Tabata_method).", "icon": "tabata.png", "tags": "workout,health", diff --git a/apps/tabata/tabata.js b/apps/tabata/tabata.js index 603cf96ee..f6addc35b 100644 --- a/apps/tabata/tabata.js +++ b/apps/tabata/tabata.js @@ -30,18 +30,17 @@ function showMainMenu() { }, 'Pause sec.': { value: settings.pause, - onchange: function(v){ - if (v<0)v=MAX_SECONDS; - if (v>MAX_SECONDS)v=0; + min : 0, max : MAX_SECONDS, wrap : true, + onchange: v => { settings.pause=v; - this.value=v; saveSettingsDebounce(); } }, 'Trainig sec.': { value: settings.training, - onchange: function(v){if (v<0)v=MAX_SECONDS;if (v>MAX_SECONDS)v=0;settings.training=v; - this.value=v; + min : 0, max : MAX_SECONDS, wrap : true, + onchange: v => { + settings.training=v; saveSettingsDebounce(); } }, @@ -61,8 +60,8 @@ function startTabata() { g.clear(); Bangle.setLCDMode("doublebuffered"); g.flip(); - var pause = settings.pause, - training = settings.training, + var pause = settings.pause, + training = settings.training, round = 1, active = true, clearBtn1, clearBtn2, clearBtn3, timer; @@ -86,7 +85,7 @@ function startTabata() { exitTraining(); return; } - + if (active) { drawCountDown(round, training, active); training--; @@ -117,7 +116,7 @@ function drawCountDown(round, count, active) { g.setFontAlign(0,0); g.setFont("6x8", 2); - g.drawString("Round " + round + "/" + settings.rounds,120,6); + g.drawString("Round " + round + "/" + settings.rounds,120,6); g.setFont("6x8", 6); g.drawString("" + count,120,80); From 79e434d0c2ba06fc8da29181da35e08fb7495814 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:22:54 +0000 Subject: [PATCH 145/199] color adjustment - all 'accented' background items are now bg2, only unread messages are bgH --- apps/messages/app.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 0cf13db2c..6feda9494 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -141,8 +141,8 @@ function showMapMessage(msg) { eta = m[2]; } else target=msg.body; layout = new Layout({ type:"v", c: [ - {type:"txt", font:fontMedium, label:target, bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2 }, - {type:"h", bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, c: [ + {type:"txt", font:fontMedium, label:target, bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2 }, + {type:"h", bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, c: [ {type:"txt", font:"6x8", label:"Towards" }, {type:"txt", font:fontLarge, label:street } ]}, @@ -179,7 +179,7 @@ function showMusicMessage(msg) { checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); } layout = new Layout({ type:"v", c: [ - {type:"h", fillx:1, bgCol:g.theme.bgH, col: g.theme.fgH, c: [ + {type:"h", fillx:1, bgCol:g.theme.bg2, col: g.theme.fg2, c: [ { type:"btn", src:getBackImage, cb:back }, { type:"v", fillx:1, c: [ { type:"txt", font:fontMedium, label:msg.artist, pad:2 }, @@ -212,8 +212,8 @@ function showMessageScroller(msg) { // a function to draw a menu item draw : function(idx, r) { // FIXME: in 2v13 onwards, clearRect(r) will work fine. There's a bug in 2v12 - g.setBgColor(idx{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, { type:"v", fillx:1, c: [ - {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2, halign:1 }, - title?{type:"txt", font:titleFont, label:title, bgCol:g.theme.bgH, col: g.theme.fgH, fillx:1, pad:2 }:{}, + {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2, halign:1 }, + title?{type:"txt", font:titleFont, label:title, bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2 }:{}, ]}, ]}, {type:"txt", font:bodyFont, label:body, fillx:1, filly:1, pad:2, cb:()=>{ From 75694c9be12cb414dec7f11e74359d9577f16f42 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:29:06 +0000 Subject: [PATCH 146/199] change default background for dark theme to something a bit less extreme --- apps/setting/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 09d95934f..f74c94db0 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -226,7 +226,7 @@ function showThemeMenu() { /*LANG*/'Dark BW': ()=>{ upd({ fg:cl("#fff"), bg:cl("#000"), - fg2:cl("#0ff"), bg2:cl("#000"), + fg2:cl("#fff"), bg2:cl("#004"), fgH:cl("#fff"), bgH:cl("#00f"), dark:true }); From d811398a59c7e38f6a90b2b1513853aaa2080986 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:36:25 +0000 Subject: [PATCH 147/199] oops - fix errors in prev commit --- apps/alarm/app.js | 8 ++++---- apps/hardalarm/app.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index f7edcd1c4..56184edf1 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -74,11 +74,11 @@ function editAlarm(alarmIndex) { /*LANG*/'< Back' : showMainMenu, /*LANG*/'Hours': { value: hrs, min : 0, max : 23, wrap : true, - onchange: v => hrs=v; + onchange: v => hrs=v }, /*LANG*/'Minutes': { value: mins, min : 0, max : 59, wrap : true, - onchange: v => mins=v; + onchange: v => mins=v }, /*LANG*/'Enabled': { value: en, @@ -139,11 +139,11 @@ function editTimer(alarmIndex) { '': { 'title': /*LANG*/'Timer' }, /*LANG*/'Hours': { value: hrs, min : 0, max : 23, wrap : true, - onchange: v => hrs=v; + onchange: v => hrs=v }, /*LANG*/'Minutes': { value: mins, min : 0, max : 59, wrap : true, - onchange: v => mins=v; + onchange: v => mins=v }, /*LANG*/'Enabled': { value: en, diff --git a/apps/hardalarm/app.js b/apps/hardalarm/app.js index 09b73d318..0c72a2c8f 100644 --- a/apps/hardalarm/app.js +++ b/apps/hardalarm/app.js @@ -58,11 +58,11 @@ function editAlarm(alarmIndex) { '': { 'title': 'Alarms' }, /*LANG*/'Hours': { value: hrs, min : 0, max : 23, wrap : true, - onchange: v => hrs=v; + onchange: v => hrs=v }, /*LANG*/'Minutes': { value: mins, min : 0, max : 59, wrap : true, - onchange: v => mins=v; + onchange: v => mins=v }, /*LANG*/'Enabled': { value: en, From 582b00e08bc47c1fde66e0b4acd4b15bc6f48832 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:37:01 +0000 Subject: [PATCH 148/199] copy/paste error --- apps/intclock/ChangeLog | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/intclock/ChangeLog b/apps/intclock/ChangeLog index aa910b6f6..2ad07562f 100644 --- a/apps/intclock/ChangeLog +++ b/apps/intclock/ChangeLog @@ -1,12 +1 @@ -0.02: Modified for use with new bootloader and firmware -0.03: add hour ticks, remove timers -0.04: add day-date display -0.07: make date and face bigger -0.08: make dots bigger and date more readable -0.09: center date, remove box around it, internal refactor to remove redundant code. -0.10: remove debug, refactor seconds to show elapsed secs each time app is displayed -0.11: shift face down for widget area, maximize face size, 0 pad single digit date, use locale for date -0.12: Fix regression after 0.11 -0.13: Fix broken date padding (fix #376) -0.14: Remove hardcoded hour buzz (you can install widchime if you miss it) -0.15: Add color scheme support +0.01: Initial commit From 597d1172be39b9692485eb1a70b40c955a4166e6 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Feb 2022 16:38:26 +0000 Subject: [PATCH 149/199] changelog tweak --- apps/speedalt2/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/speedalt2/ChangeLog b/apps/speedalt2/ChangeLog index 602147856..73e9bfc40 100644 --- a/apps/speedalt2/ChangeLog +++ b/apps/speedalt2/ChangeLog @@ -12,4 +12,4 @@ 1.10: Adds Kalman filter. 1.14: Add VMG and coordinates screens 1.43: Adds mirroring of the watch face to an Android device. See README.md -1.48: Droidscript mirroring prog automatically uses last connection address. Auto connects when run. +1.49: Droidscript mirroring prog automatically uses last connection address. Auto connects when run. From 54ca2eed97906fc9362fcdc1b25294ffb1b4c91a Mon Sep 17 00:00:00 2001 From: copoer Date: Wed, 23 Feb 2022 12:57:22 -0400 Subject: [PATCH 150/199] Fix step count --- modules/exstats.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exstats.js b/modules/exstats.js index 8a726a5de..b72ee6584 100644 --- a/modules/exstats.js +++ b/modules/exstats.js @@ -119,6 +119,7 @@ Bangle.on("GPS", function(fix) { Bangle.on("step", function(steps) { if (!state.active) return; if (stats["step"]) stats["step"].emit("changed",stats["step"]); + state.stepHistory[0] += steps-state.lastStepCount; state.lastStepCount = steps; }); Bangle.on("HRM", function(h) { From 792d9a316681c31657b69aaf5f947ee3340924b6 Mon Sep 17 00:00:00 2001 From: copoer Date: Wed, 23 Feb 2022 13:18:12 -0400 Subject: [PATCH 151/199] Local for time in contour clock --- apps/contourclock/lib.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/contourclock/lib.js b/apps/contourclock/lib.js index 65a4622f4..aa83fca26 100644 --- a/apps/contourclock/lib.js +++ b/apps/contourclock/lib.js @@ -13,13 +13,15 @@ exports.drawClock = function(fontIndex) { if (n!=10) return (false); //font file seems to be invalid var x=0; var y = g.getHeight()/2-digits[0].height/2; - var date = new Date(); + var date = require('locale').time(new Date(),1); + var hours = date.split(":")[0]; + var minutes = date.split(":")[1]; g.clearRect(0,38,g.getWidth()-1,138); - d1=parseInt(date.getHours()/10); - d2=parseInt(date.getHours()%10); + d1=parseInt(hours/10); + d2=parseInt(hours%10); d3=10; - d4=parseInt(date.getMinutes()/10); - d5=parseInt(date.getMinutes()%10); + d4=parseInt(minutes/10); + d5=parseInt(minutes%10); w1=digits[d1].width; w2=digits[d2].width; w3=digits[d3].width; From da25e418058e5b85c6dfd85d91847d34ecdf7acc Mon Sep 17 00:00:00 2001 From: copoer Date: Wed, 23 Feb 2022 13:24:59 -0400 Subject: [PATCH 152/199] Change log --- apps/contourclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/contourclock/ChangeLog b/apps/contourclock/ChangeLog index 9c62e637b..aed7baf64 100644 --- a/apps/contourclock/ChangeLog +++ b/apps/contourclock/ChangeLog @@ -5,3 +5,4 @@ 0.23: Customizer! Unused fonts no longer take up precious memory. 0.24: Added previews to the customizer. 0.25: Fixed a bug that would let widgets change the color of the clock. +0.26: Time now works with locale formatting From e3b558b1f037bee198334536dc368ee134650b1f Mon Sep 17 00:00:00 2001 From: Marco H Date: Wed, 23 Feb 2022 20:29:29 +0100 Subject: [PATCH 153/199] Threema icon and color --- apps/messages/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/messages/app.js b/apps/messages/app.js index 6feda9494..512659c40 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -92,6 +92,7 @@ function getMessageImage(msg) { if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); if (s=="sms message") return getNotificationImage(); + if (s=="threema") return atob("ICCDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//+AAAAAAAAAAAP/////wAAAAAAAAB//////+AAAAAAAAP///////wAAAAAAB////////+AAAAAAP///wAP///wAAAAAP/////////wAAAAAP//+P/x///wAAAAAP//+P/x///+AAAAB///+AAB///+AAAAAP//+AAB///+AAAAAP//+AAB///wAAAAAP//+AAB///wAAAAAB/////////wAAAAAB////////+AAAAAAB////////wAAAAAAB///////+AAAAAAAP//////+AAAAAAAAP+AAP/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEkAAkAAkgAAAAAAAEkAEkgAkgAAAAAAAEkAAkAAkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); @@ -120,6 +121,7 @@ function getMessageImageCol(msg,def) { "outlook mail": "#0072c6", "skype": "#00aff0", "slack": "#e51670", + "threema": "#000", "telegram": "#0088cc", "twitter": "#1da1f2", "whatsapp": "#4fce5d", From b53289492da91b2291828f2dbdba8850a413e75f Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:45:11 -0800 Subject: [PATCH 154/199] Create metadata.json --- apps/aptsciclk/metadata.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 apps/aptsciclk/metadata.json diff --git a/apps/aptsciclk/metadata.json b/apps/aptsciclk/metadata.json new file mode 100644 index 000000000..8ee53956b --- /dev/null +++ b/apps/aptsciclk/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "aptsciclk", + "name": "Apeture Science Clock", + "shortName":"AptSci Clock", + "version": "0.08", + "description": "A clock based on the portal series", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": "BANGLEJS2", + "allow_emulator": false, + "storage": [ + {"name":"aptsciclkquotes.txt","url":"quotes.txt"}, + {"name":"aptsciclk.app.js","url":"app.js"}, + {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} + ] +} From 944560b123dcbc8cb94319bcb7907fb3fc66498a Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:46:14 -0800 Subject: [PATCH 155/199] added README.md --- apps/aptsciclk/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/aptsciclk/metadata.json b/apps/aptsciclk/metadata.json index 8ee53956b..15d8ec4e3 100644 --- a/apps/aptsciclk/metadata.json +++ b/apps/aptsciclk/metadata.json @@ -9,6 +9,7 @@ "tags": "clock", "supports": "BANGLEJS2", "allow_emulator": false, + "readme":"README.md", "storage": [ {"name":"aptsciclkquotes.txt","url":"quotes.txt"}, {"name":"aptsciclk.app.js","url":"app.js"}, From f716f6fe40bb10c096300aee845dba769c95e7df Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:57:30 -0800 Subject: [PATCH 156/199] Create README.md --- apps/aptsciclk/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 apps/aptsciclk/README.md diff --git a/apps/aptsciclk/README.md b/apps/aptsciclk/README.md new file mode 100644 index 000000000..e56b36f09 --- /dev/null +++ b/apps/aptsciclk/README.md @@ -0,0 +1,7 @@ +#Description +This is a simple clock based on the Portal Series. + +#Features +The button in the center of the screen is interactable and the warning image will change when it is pressed. +Potato GLaDOS in the bottom left corner is interactable and will display a quote when tapped. (You can add more quotes by editing the `aptsciclkquotes.txt` file seperating each quote with a `^`) +When the app loads the Apeture Science Logo is displayed. From f1fe1b4fe350f34410731847166073d43d598066 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:58:24 -0800 Subject: [PATCH 157/199] Update README.md --- apps/aptsciclk/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/aptsciclk/README.md b/apps/aptsciclk/README.md index e56b36f09..68f132a1f 100644 --- a/apps/aptsciclk/README.md +++ b/apps/aptsciclk/README.md @@ -1,7 +1,9 @@ #Description + This is a simple clock based on the Portal Series. #Features + The button in the center of the screen is interactable and the warning image will change when it is pressed. Potato GLaDOS in the bottom left corner is interactable and will display a quote when tapped. (You can add more quotes by editing the `aptsciclkquotes.txt` file seperating each quote with a `^`) When the app loads the Apeture Science Logo is displayed. From 7ce25c8774d6846d2430f2bb6a22625d444578a9 Mon Sep 17 00:00:00 2001 From: Sven Klomp Date: Wed, 23 Feb 2022 20:50:45 +0100 Subject: [PATCH 158/199] Initial commit of widcw widcw is a widget to display the current calendar week. --- apps/widcw/ChangeLog | 1 + apps/widcw/logo.svg | 62 +++++++++++++++++++++++++++++++++++++++ apps/widcw/metadata.json | 13 ++++++++ apps/widcw/widget.js | 48 ++++++++++++++++++++++++++++++ apps/widcw/widget.png | Bin 0 -> 884 bytes apps/widcw/widget.svg | 55 ++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 apps/widcw/ChangeLog create mode 100644 apps/widcw/logo.svg create mode 100644 apps/widcw/metadata.json create mode 100644 apps/widcw/widget.js create mode 100644 apps/widcw/widget.png create mode 100644 apps/widcw/widget.svg diff --git a/apps/widcw/ChangeLog b/apps/widcw/ChangeLog new file mode 100644 index 000000000..a4bc24d1a --- /dev/null +++ b/apps/widcw/ChangeLog @@ -0,0 +1 @@ +0.01: First version \ No newline at end of file diff --git a/apps/widcw/logo.svg b/apps/widcw/logo.svg new file mode 100644 index 000000000..e093414d5 --- /dev/null +++ b/apps/widcw/logo.svg @@ -0,0 +1,62 @@ + + + + + + + + CW + + diff --git a/apps/widcw/metadata.json b/apps/widcw/metadata.json new file mode 100644 index 000000000..653b093ec --- /dev/null +++ b/apps/widcw/metadata.json @@ -0,0 +1,13 @@ +{ + "id": "widcw", + "name": "Calendar Week Widget", + "version": "0.01", + "description": "Widget which shows the current calendar week", + "icon": "widget.png", + "type": "widget", + "tags": "widget,calendar", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widcw.wid.js","url":"widget.js"} + ] +} diff --git a/apps/widcw/widget.js b/apps/widcw/widget.js new file mode 100644 index 000000000..ef43a4551 --- /dev/null +++ b/apps/widcw/widget.js @@ -0,0 +1,48 @@ +(function() { + var width = 22; // width of the widget + + function draw() { + const x = this.x, y = this.y, x2 = x+21, y2 = y+23; + + var date = new Date(); + + // Calculate calendar week (https://stackoverflow.com/a/6117889) + getCW= function(date){ + var d=new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var dayNum = d.getDay() || 7; + d.setDate(d.getDate() + 4 - dayNum); + var yearStart = new Date(d.getFullYear(),0,1); + return Math.ceil((((d - yearStart) / 86400000) + 1)/7); + }; + + g.reset().setFontAlign(0, 0) // center all text + // header + .setBgColor("#f00").setColor("#fff") + .clearRect(x, y, x2, y+8).setFont("4x6").drawString("CW", (x+x2)/2+1, y+5) + // date + .setBgColor("#fff").setColor("#000") + .clearRect(x, y+9, x2, y2).setFont("Vector:16").drawString(getCW(date), (x+x2)/2+2, y+17); + + if (!g.theme.dark) { + // black border around date for light themes + g.setColor("#000").drawPoly([ + x, y+9, + x, y2, + x2, y2, + x2, y+9 + ]); + } + + // redraw when date changes + setTimeout(()=>WIDGETS["widcw"].draw(), (86401 - Math.floor(date/1000) % 86400)*1000); + + } + + // add your widget + WIDGETS["widcw"]={ + area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right) + width: width, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout + draw:draw // called to draw the widget + }; + +})(); diff --git a/apps/widcw/widget.png b/apps/widcw/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..c73d40c5a60b0f618d12a23276b14d53325b23df GIT binary patch literal 884 zcmV-)1B?8LP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10|7}y zK~!jg?bknuT}2ef@lTRXRxvSa5rwF+Q;VpmiBV9|R&BIV5MpDRlvXMTf+>R9st}UY zR)T`WuvQU-z#@o$hzg1r5DA<86L;V4Gx1r>T=u+q_r?37<$PgaXXZC|&Y3yyoLMTB zN~Kb%R4SFqHL|IrZVC_L0Cr(J7Vtej$70almo<^IxD@&~j%9;p@VIp1(?Pd@-;2$5XZ<4fO5sbzPjf ztuSC9B?M9!M#Cd!8)aJmTWvpw#i<~L?Jt;IU=YAij@tJfJq-1cY#jZIiDn@8?;5VaA?CoUo zFsFlIq?3QiMyl*dPR1LU#=&C$_57{QJnO&zh)Ln{XYrlb*0aHzY-FOgwunb3abTy> zLUXk=dLuqCoJNf?Y%To#bYZk5vKq>s5s zTSaZcVkYROIyyQr+wiLNzF8`q8TXuyOy&9c&=&Ahi}uU>y{Ii69ieM}-+~A55N?q& z&b$<#DwRs*|KT5a_e&ZbqWHf60000< KMNUMnLSTZK%c`yb literal 0 HcmV?d00001 diff --git a/apps/widcw/widget.svg b/apps/widcw/widget.svg new file mode 100644 index 000000000..d3e567286 --- /dev/null +++ b/apps/widcw/widget.svg @@ -0,0 +1,55 @@ + + + + + + + + CW + + From 32671875c3cc7d6136bffe4fb8cc17451557b096 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 23 Feb 2022 23:20:57 +0000 Subject: [PATCH 159/199] Daisy - added settings menu --- apps/daisy/ChangeLog | 1 + apps/daisy/README.md | 1 - apps/daisy/app.js | 24 ++++++++++++------- apps/daisy/metadata.json | 8 ++++--- apps/daisy/settings.js | 51 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 apps/daisy/settings.js diff --git a/apps/daisy/ChangeLog b/apps/daisy/ChangeLog index 9db0e26c5..4fdf333e4 100644 --- a/apps/daisy/ChangeLog +++ b/apps/daisy/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: added settings menu to change color diff --git a/apps/daisy/README.md b/apps/daisy/README.md index f6c0014be..3f22f5dd9 100644 --- a/apps/daisy/README.md +++ b/apps/daisy/README.md @@ -16,7 +16,6 @@ Forum](http://forum.espruino.com/microcosms/1424/) * Uses the [BloggerSansLight](https://www.1001fonts.com/rounded-fonts.html?page=3) font, which if free for commercial use ## Future Development -* Add settings menu to change primary clock color * Add a heart rate option in the information line that turns on when selected * Use mini icons in the information line rather that text * Add weather icons as per Pastel clock diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 5490d0740..38b839138 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -1,7 +1,7 @@ var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); const storage = require('Storage'); const locale = require("locale"); -const SETTINGS_FILE = "pastel.json"; // XXX +const SETTINGS_FILE = "daisy.json"; const LOCATION_FILE = "mylocation.json"; const h = g.getHeight(); const w = g.getWidth(); @@ -14,13 +14,10 @@ let warned = 0; let idle = false; let IDLE_MINUTES = 26; -// palette for 0-40% -const pal1 = new Uint16Array([g.theme.bg, g.toColor("#020"), g.toColor("#0f0"), g.toColor("#00f")]); -// palette for 50-100% -const pal2 = new Uint16Array([g.theme.bg, g.toColor("#0f0"), g.toColor("#020"), g.toColor("#00f")]); +var pal1; // palette for 0-40% +var pal2; // palette for 50-100% const infoWidth = 50; const infoHeight = 14; - var drawingSteps = false; function log_debug(o) { @@ -40,6 +37,13 @@ Graphics.prototype.setFontRoboto20 = function(scale) { return this; } +function assignPalettes() { + // palette for 0-40% + pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.color), g.toColor("#00f")]); + // palette for 50-100% + pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.color), g.toColor(settings.gy), g.toColor("#00f")]); +} + function setSmallFont20() { g.setFontRoboto20(); } @@ -67,9 +71,11 @@ function getSteps() { function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; - settings.grid = settings.grid||false; - settings.font = settings.font||"Lato"; + settings.color = settings.color||'Green'; + settings.gy = settings.gy||'gy'; + settings.bg = settings.bg||'#0f0'; settings.idle_check = settings.idle_check||true; + assignPalettes(); } // requires the myLocation app @@ -266,7 +272,7 @@ function drawClock() { g.drawImage(getGaugeImage(p_steps), 0, 0); setLargeFont(); - g.setColor('#0f0'); + g.setColor(settings.color); g.setFontAlign(1,0); // right aligned g.drawString(hh, (w/2) - 1, h/2); diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index fe66683a7..f2624a0f3 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -1,6 +1,6 @@ { "id": "daisy", "name": "Daisy", - "version":"0.01", + "version":"0.02", "dependencies": {"mylocation":"app"}, "description": "A clock based on the Pastel clock with large ring guage for steps", "icon": "app.png", @@ -10,6 +10,8 @@ "readme": "README.md", "storage": [ {"name":"daisy.app.js","url":"app.js"}, - {"name":"daisy.img","url":"app-icon.js","evaluate":true} - ] + {"name":"daisy.img","url":"app-icon.js","evaluate":true}, + {"name":"daisy.settings.js","url":"daisy.settings.js"} + ], + "data": [{"name":"daisy.json"}] } diff --git a/apps/daisy/settings.js b/apps/daisy/settings.js new file mode 100644 index 000000000..6df083fff --- /dev/null +++ b/apps/daisy/settings.js @@ -0,0 +1,51 @@ +(function(back) { + const SETTINGS_FILE = "daisy.json"; + + // initialize with default settings... + let s = {'gy' : '#020', + 'bg' : '#0f0', + 'color': 'Green', + 'check_idle' : true}; + + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage') + let settings = storage.readJSON(SETTINGS_FILE, 1) || s; + const saved = settings || {} + for (const key in saved) { + s[key] = saved[key] + } + + function save() { + settings = s + storage.write(SETTINGS_FILE, settings) + } + + var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; + var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; + var gy_code = ['#020','#220','#022','#202','#200','#002']; + + E.showMenu({ + '': { 'title': 'Daisy Clock' }, + '< Back': back, + 'Colour': { + value: 0 | color_options.indexOf(s.color), + min: 0, max: 5, + format: v => color_options[v], + onchange: v => { + s.color = color_options[v]; + s.bg = bg_code[v]; + s.gy = gy_code[v]; + save(); + }, + }, + 'Idle Warning': { + value: !!s.idle_check, + format: v => v ? /*LANG*/"Yes":/*LANG*/"No", + onchange: v => { + s.idle_check = v; + save(); + }, + } + }); +}) From 48d2a08e83ff45ac850b6d7d8769c54550476718 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 23 Feb 2022 23:50:49 +0000 Subject: [PATCH 160/199] Daisy - added settings menu --- apps/daisy/app.js | 13 ++++++------- apps/daisy/settings.js | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 38b839138..2717f94db 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -35,13 +35,13 @@ Graphics.prototype.setFontRoboto20 = function(scale) { // Actual height 21 (20 - 0) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAH/zA/+YAAAAAAAHwAAwAAHwAA+AAAAAAAAAAAQACDAAYbADP4B/8A/zAGYZADH4A/+A/7AHYYADCAAAAAAAQAeHgH4eBzgwMMHnhw88GGBw4wHj+AcPgAAAAAAAAAAB4AA/gAGMAAwhwGMcAfuABzgABzgAc+AOMYBhBAAMYAB/AAHwAAAAAHwD5+A/8YGPDAw8YGPzA/HYD4fAADwAB/AAOYAABAAAAHwAA4AAAAAAAAAAH/gD//B8A+cAA7AADAAAAAAAYAAbwAHHgHwf/4A/8AAAAEAABiAAGwAA8AA/AAH+AAGwAByAAEAAAAAAAMAABgAAMAABgAH/wA/+AAMAABgAAMAABgAAAAAAAIAAfAADwAAAABgAAMAABgAAMAABgAAAAAAAAAAAAADAAAYAAAAAAAAADgAB8AB+AA+AA+AA/AAHAAAgAAAAAAB8AB/8Af/wHAHAwAYGADAwAYHAHAf/wB/8AAAAAAAAAAABgAAcAADAAAYAAH//A//4AAAAAAAAAAAAAAAAAAAAABwDAeA4HAPAwHYGBzAwcYHHDAfwYB8DAAAYAAAAAAABgOAcBwHADAwwYGGDAwwYHPHAf/wB58AAAAAAAAADAAB4AAfAAPYAHjAB4YA8DAH//A//4AAYAADAAAAAAAAAEMA/xwH+HAxgYGMDAxgYGODAw/4GD+AAHAAAAAAAAAf8AP/wD2HA5wYGMDAxgYGOHAA/wAD8AAAAAAAAAAAGAAAwAAGADAwB4GB+Aw+AGfAA/gAHwAAwAAAAAAADAB5+Af/wHPDAwwYGGDAwwYHPHAfvwB58AAAAAAAAAAAB+AAf4AHDjAwMYGBjAwM4HDOAf/gB/4AAAAAAAAAAAAYDADAYAAAAAAAAAAYDAfAYHwAAAABAAAcAADgAA+AAGwAB3AAMYABjgAYMAAAAAAAAAAAAAAABmAAMwABmAAMwABmAAMwABmAAMwAAiAAAAAAAAAYMADjgAMYAB3AAGwAA2AADgAAcAABAAAAAAAAAMAADgAA4AAGBzAweYGHAA/wAD8AAEAAAAwAB/4A/PwOAGDgAYYPxmH/Mw4ZmMDMxgZmM+Mx/5mHDAYAIDgDAPBwAf8AAMAAAAAAAYAAfAAPwAP4AH+AH4wA8GAH4wAP2AAPwAAfwAAfAAAYAAAAAAAAAAA//4H//AwwYGGDAwwYGGDAwwYH/HAf/wB58AAAAADAAH/AD/+AcBwHADAwAYGADAwAYGADA4A4DweAODgAAAAAAAAAAAAAAH//A//4GADAwAYGADAwAYGADAYAwD4+AP/gAfwAAAAAAAAAAAH//A//4GDDAwYYGDDAwYYGDDAwYYGCDAgAYAAAAAAAH//A//4GDAAwYAGDAAwYAGDAAwYAGAAAAAAAAAAH/AD/8AcBwHAHAwAYGADAwYYGDDA4YYDz/AOfwAAAAAAAAAAA//4H//A//4ADAAAYAADAAAYAADAAAYAADAA//4H//AAAAAAAAAAAAAAA//4H//AAAAAAAAABAAAeAAB4AADAAAYAADAAAYAAHA//wH/8AAAAAAAAAAAAAAA//4H//AAcAAPAAD4AA/wAOPADg8A4B4GAHAgAYAAAAAAAH//A//4AADAAAYAADAAAYAADAAAYAADAAAAAAAA//4H//A+AAB+AAD8AAD8AAH4AAPAAH4AH4AD8AD8AA+AAH//A//4AAAAAAAH//A//4H//AeAAB8AADwAAPgAAeAAA8AADwH//A//4AAAAAAAAAAAH/AB/8AeDwHAHAwAYGADAwAYGADA4A4DweAP/gA/4AAAAAAAAAAAH//A//4GBgAwMAGBgAwMAGBgAwcAH/AAfwAA8AAAAAA/4AP/gDgOA4A4GADAwAYGADAwAYHAHgeD+B/8wD+GAAAAAAAAAAA//4H//AwYAGDAAwYAGDgAweAHH8Afz4B8HAAAIAAYAPDwD8OA5w4GGDAwwYGHDAwYYHDnAePwBw8AAAAGAAAwAAGAAAwAAGAAA//4H//AwAAGAAAwAAGAAAwAAAAAAAAAH/4A//wAAPAAAYAADAAAYAADAAAYAAPA//wH/8AAAAAAAAgAAHAAA/AAB/AAD+AAD+AAD4AAfAAfwAfwAfwAH4AA4AAEAAA+AAH/AAH/gAD/AAD4AD+AH+AH8AA+AAH+AAD+AAD/AAD4AH/AP/AH+AA8AAAAAAAAAGADA4A4HweAPPgA/wAB8AAfwAPvgDweA8B4GADAAAIGAAA4AAHwAAPgAAfAAA/4AH/AD4AB8AA+AAHgAAwAAAAAAAAAGADAwB4GAfAwPYGDzAx4YGeDA/AYHwDA4AYGADAAAAAAAA///3//+wAA2AAGAAAGAAA+AAD8AAD8AAD4AAH4AAHgAAMAAAAwAA2AAG///3//+AAAAAAAAAAAOAAHwAD4AA8AAD8AADwAAGAAAAAAABgAAMAABgAAMAABgAAMAABgAAMAABgAAAEAAAwAADAAAIAAAAAAAAAAEeABn4Ad3ADMYAZjADMYAZmAB/4AP/AAAAAAAA//4H//ABgwAYDADAYAYDADg4AP+AA/gABwAAAAAAAAA/gAP+ADg4AYDADAYAYDADAYAOOABxwAAAAAEAAH8AB/wAcHADAYAYDADAYAcDA//4H//AAAAAAAAAAAAH8AB/wAdnADMYAZjADMYAZjAB84AHmAAMAAMAABgAB//gf/8HMAAxgAGIAAAAAAH8IB/zAcHMDAZgYDMDAZgcHcD//Af/wAAAAAAAAAAH//A//4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAGf/Az/4AAAAAAAAAAMz//mf/4AAAAAAAAAAH//A//4ABwAAeAAH4ABzwAcPACAYAABAAAAAAAA//4H//AAAAAAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/ABgAAYAADAAAYAADgAAP/AA/4AAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAAH8AB/wAcHADAYAYDADAYAYDADx4AP+AA/gAAAAAAAAf/8D//gYDADAYAYDADAYAcHAB/wAH8AAEAAAAAAEAAH8AB/wAcHADAYAYDADAYAYDAD//gf/8AAAAAAAAAAAf/AD/4AcAADAAAYAACAAAAEAB5wAfnADMYAZjADGYAYzADn4AOeAAAAAAAADAAAYAAf/wD//ADAYAYDAAAAAAAAD/gAf/AAA4AADAAAYAADAAAwAf/AD/4AAAAAAAAYAAD4AAP4AAP4AAPAAH4AH4AD8AAcAAAAAAQAADwAAf4AAf4AAPAAP4AP4ADwAAfgAA/gAA/AAD4AH+AD+AAeAAAAAAAAACAYAcHADzwAH8AAfAAH8ADx4AcHACAIAcAMD4BgP4MAP/AAPwAP4AP4AD4AAcAAAAAAAAADAYAYHADD4AY7ADOYAfjADwYAcDADAYAAAAADAAA4AH//B/v8cABzAACAAAH//w//+AAAAAAACAACcAAx/n+H//AA4AAHAAAAAAAAAAAAAOAADgAAYAADAAAcAABgAAGAAAwAAGAADwAAcAAAAA"), 32, atob("BQUHDQwPDQQHBwkMBAYGCQwMDAwMDAwMDAwFBAsMCwoTDg0ODgwMDg8GDA0LEg8ODQ4NDA0ODRMNDQ0GCQYJCQYLDAsMCwcMDAUFCwUSDAwMDAcLBwwKEAoKCgcFBw4A"), 21+(scale<<8)+(1<<16)); return this; -} +}; function assignPalettes() { // palette for 0-40% - pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.color), g.toColor("#00f")]); + pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.fg), g.toColor("#00f")]); // palette for 50-100% - pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.color), g.toColor(settings.gy), g.toColor("#00f")]); + pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.toColor(settings.gy), g.toColor("#00f")]); } function setSmallFont20() { @@ -71,9 +71,8 @@ function getSteps() { function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; - settings.color = settings.color||'Green'; - settings.gy = settings.gy||'gy'; - settings.bg = settings.bg||'#0f0'; + settings.gy = settings.gy||'#020'; + settings.fg = settings.fg||'#0f0'; settings.idle_check = settings.idle_check||true; assignPalettes(); } @@ -272,7 +271,7 @@ function drawClock() { g.drawImage(getGaugeImage(p_steps), 0, 0); setLargeFont(); - g.setColor(settings.color); + g.setColor(settings.fg); g.setFontAlign(1,0); // right aligned g.drawString(hh, (w/2) - 1, h/2); diff --git a/apps/daisy/settings.js b/apps/daisy/settings.js index 6df083fff..044eee0d1 100644 --- a/apps/daisy/settings.js +++ b/apps/daisy/settings.js @@ -3,7 +3,7 @@ // initialize with default settings... let s = {'gy' : '#020', - 'bg' : '#0f0', + 'fg' : '#0f0', 'color': 'Green', 'check_idle' : true}; @@ -22,7 +22,7 @@ } var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; - var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; + var fg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; var gy_code = ['#020','#220','#022','#202','#200','#002']; E.showMenu({ @@ -34,7 +34,7 @@ format: v => color_options[v], onchange: v => { s.color = color_options[v]; - s.bg = bg_code[v]; + s.fg = fg_code[v]; s.gy = gy_code[v]; save(); }, From c0ca33388e17791eaaf124c33800056069032cec Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 16:07:51 -0800 Subject: [PATCH 161/199] Update apps.json --- apps.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7d547a554..b88bd8165 100644 --- a/apps.json +++ b/apps.json @@ -1,7 +1,8 @@ [ { "id": "aptsciclk", - "name": "Apeture Sci Clock", + "name": "Apeture Science Clock", + "shortName":"AptSci Clock", "version": "0.08", "description": "A clock based on the portal series", "icon": "app.png", @@ -9,6 +10,7 @@ "tags": "clock", "supports": "BANGLEJS2", "allow_emulator": false, + "readme":"README.md", "storage": [ {"name":"aptsciclkquotes.txt","url":"quotes.txt"}, {"name":"aptsciclk.app.js","url":"app.js"}, From 6d8cecc92b0a1935d9771f1ca4efb916b41edd13 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 16:20:42 -0800 Subject: [PATCH 162/199] Update README.md --- apps/aptsciclk/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/aptsciclk/README.md b/apps/aptsciclk/README.md index 68f132a1f..975892076 100644 --- a/apps/aptsciclk/README.md +++ b/apps/aptsciclk/README.md @@ -5,5 +5,7 @@ This is a simple clock based on the Portal Series. #Features The button in the center of the screen is interactable and the warning image will change when it is pressed. + Potato GLaDOS in the bottom left corner is interactable and will display a quote when tapped. (You can add more quotes by editing the `aptsciclkquotes.txt` file seperating each quote with a `^`) + When the app loads the Apeture Science Logo is displayed. From a1e3db238e5dac82ac68b02ce4e7a9b87b48d74f Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 16:35:18 -0800 Subject: [PATCH 163/199] Update README.md --- apps/aptsciclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/aptsciclk/README.md b/apps/aptsciclk/README.md index 975892076..718e3d408 100644 --- a/apps/aptsciclk/README.md +++ b/apps/aptsciclk/README.md @@ -1,8 +1,8 @@ -#Description +# Description This is a simple clock based on the Portal Series. -#Features +# Features The button in the center of the screen is interactable and the warning image will change when it is pressed. From 343f2f55e34edbbb874b4bf5724e9a7be6170ba9 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 19:31:37 -0800 Subject: [PATCH 164/199] Update apps.json --- apps.json | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index b88bd8165..537a4f697 100644 --- a/apps.json +++ b/apps.json @@ -1,20 +1,38 @@ +--- +# ================================================================= +# ALL THE INFORMATION INSIDE APPS.JSON HAS NOW BEEN MOVED +# +# You'll find it inside a file called apps/yourapp/metadata.json +# +# Otherwise nothing has changed. GitHub Pages will automatically +# create apps.json as your site is hosted, or if you're hosting +# yourself you can run bin/create_apps_json.sh +# +# If you serve the store from localhost for development/testing, +# the loader looks for apps.local.json instead, you can run +# `bin/create_apps_json.sh apps.local.json` to create that file. +# ================================================================= + +# Uncomment the following line if you only want explicitly listed +# apps to be available on your site + +# restricted: ["boot", "launch", "antonclk", "health", "setting", "about", "widbat", "widbt", "widlock", "widid"] +--- +{%- if page.restricted == nil -%} + {%- assign apps = site.static_files | where: "name", "metadata.json" | map: "path" -%} +{%- else -%} + {%- capture temp -%} + {%- for app in page.restricted %} /apps/{{app}}/metadata.json {%- endfor -%} + {%- endcapture -%} + {%- assign apps = temp | strip | split: " " -%} +{%- endif -%} + [ -{ - "id": "aptsciclk", - "name": "Apeture Science Clock", - "shortName":"AptSci Clock", - "version": "0.08", - "description": "A clock based on the portal series", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports": "BANGLEJS2", - "allow_emulator": false, - "readme":"README.md", - "storage": [ - {"name":"aptsciclkquotes.txt","url":"quotes.txt"}, - {"name":"aptsciclk.app.js","url":"app.js"}, - {"name":"aptsciclk.img","url":"app-icon.js","evaluate":true} - ] -} + +{%- include_relative {{ apps.first }} -%} + +{%- for app in apps offset:1 -%} +,{%- include_relative {{ app }} -%} +{%- endfor -%} + ] From c3aeb22d49772625fc80b368d77d11baa4379f58 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Wed, 23 Feb 2022 20:25:59 -0800 Subject: [PATCH 165/199] reverted to original Reverted to when it was forked --- apps.json | 5100 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 5064 insertions(+), 36 deletions(-) diff --git a/apps.json b/apps.json index 537a4f697..e5e9f8f02 100644 --- a/apps.json +++ b/apps.json @@ -1,38 +1,5066 @@ ---- -# ================================================================= -# ALL THE INFORMATION INSIDE APPS.JSON HAS NOW BEEN MOVED -# -# You'll find it inside a file called apps/yourapp/metadata.json -# -# Otherwise nothing has changed. GitHub Pages will automatically -# create apps.json as your site is hosted, or if you're hosting -# yourself you can run bin/create_apps_json.sh -# -# If you serve the store from localhost for development/testing, -# the loader looks for apps.local.json instead, you can run -# `bin/create_apps_json.sh apps.local.json` to create that file. -# ================================================================= - -# Uncomment the following line if you only want explicitly listed -# apps to be available on your site - -# restricted: ["boot", "launch", "antonclk", "health", "setting", "about", "widbat", "widbt", "widlock", "widid"] ---- -{%- if page.restricted == nil -%} - {%- assign apps = site.static_files | where: "name", "metadata.json" | map: "path" -%} -{%- else -%} - {%- capture temp -%} - {%- for app in page.restricted %} /apps/{{app}}/metadata.json {%- endfor -%} - {%- endcapture -%} - {%- assign apps = temp | strip | split: " " -%} -{%- endif -%} - [ - -{%- include_relative {{ apps.first }} -%} - -{%- for app in apps offset:1 -%} -,{%- include_relative {{ app }} -%} -{%- endfor -%} - + { + "id": "fwupdate", + "name": "Firmware Update", + "version": "0.02", + "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", + "icon": "app.png", + "type": "RAM", + "tags": "tools,system", + "supports": ["BANGLEJS2"], + "custom": "custom.html", + "customConnect": true, + "storage": [], + "sortorder": 20 + }, + { + "id": "boot", + "name": "Bootloader", + "version": "0.39", + "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", + "icon": "bootloader.png", + "type": "bootloader", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":".boot0","url":"boot0.js"}, + {"name":".bootcde","url":"bootloader.js"}, + {"name":"bootupdate.js","url":"bootupdate.js"} + ], + "sortorder": -10 + }, + { + "id": "hebrew_calendar", + "name": "Hebrew Calendar", + "shortName": "HebCal", + "version": "0.04", + "description": "lists the date according to the hebrew calendar", + "icon": "app.png", + "allow_emulator": false, + "tags": "tool,locale", + "supports": [ + "BANGLEJS", + "BANGLEJS2" + ], + "readme": "README.md", + "storage": [ + { + "name": "hebrew_calendar.app.js", + "url": "app.js" + }, + { + "name": "hebrewDate", + "url": "hebrewDate.js" + }, + { + "name": "hebrew_calendar.img", + "url": "app-icon.js", + "evaluate": true + } + ] + }, + { "id": "golfscore", + "name": "Golf Score", + "shortName":"golfscore", + "version":"0.02", + "description": "keeps track of strokes during a golf game", + "icon": "app.png", + "tags": "outdoors", + "allow_emulator": true, + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"golfscore.app.js","url":"app.js"}, + {"name":"golfscore.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "messages", + "name": "Messages", + "version": "0.14", + "description": "App to display notifications from iOS and Gadgetbridge", + "icon": "app.png", + "type": "app", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"messages.app.js","url":"app.js"}, + {"name":"messages.settings.js","url":"settings.js"}, + {"name":"messages.img","url":"app-icon.js","evaluate":true}, + {"name":"messages.wid.js","url":"widget.js"}, + {"name":"messages","url":"lib.js"} + ], + "data": [{"name":"messages.json"},{"name":"messages.settings.json"}], + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot-notify.gif"}], + "sortorder": -9 + }, + { + "id": "android", + "name": "Android Integration", + "shortName": "Android", + "version": "0.05", + "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", + "icon": "app.png", + "tags": "tool,system,messages,notifications", + "dependencies": {"messages":"app"}, + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"android.app.js","url":"app.js"}, + {"name":"android.settings.js","url":"settings.js"}, + {"name":"android.img","url":"app-icon.js","evaluate":true}, + {"name":"android.boot.js","url":"boot.js"} + ], + "sortorder": -8 + }, + { + "id": "ios", + "name": "iOS Integration", + "version": "0.07", + "description": "Display notifications/music/etc from iOS devices", + "icon": "app.png", + "tags": "tool,system,ios,apple,messages,notifications", + "dependencies": {"messages":"app"}, + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"ios.app.js","url":"app.js"}, + {"name":"ios.img","url":"app-icon.js","evaluate":true}, + {"name":"ios.boot.js","url":"boot.js"} + ], + "sortorder": -8 + }, + { + "id": "health", + "name": "Health Tracking", + "version": "0.09", + "description": "Logs health data and provides an app to view it (requires firmware 2v10.100 or later)", + "icon": "app.png", + "tags": "tool,system,health", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"health.app.js","url":"app.js"}, + {"name":"health.img","url":"app-icon.js","evaluate":true}, + {"name":"health.boot.js","url":"boot.js"}, + {"name":"health","url":"lib.js"} + ] + }, + { + "id": "launch", + "name": "Launcher", + "shortName": "Launcher", + "version": "0.10", + "description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", + "icon": "app.png", + "type": "launch", + "tags": "tool,system,launcher", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"launch.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]}, + {"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]}, + {"name":"launch.settings.js","url":"settings.js","supports":["BANGLEJS2"]} + ], + "data": [{"name":"launch.json"}], + "sortorder": -10 + }, + { + "id": "setting", + "name": "Settings", + "version": "0.38", + "description": "A menu for setting up Bangle.js", + "icon": "settings.png", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"setting.app.js","url":"settings.js"}, + {"name":"setting.img","url":"settings-icon.js","evaluate":true} + ], + "data": [{"name":"setting.json","url":"settings.min.json","evaluate":true}], + "sortorder": -5 + }, + { + "id": "about", + "name": "About", + "version": "0.12", + "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", + "icon": "app.png", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"bangle1-about-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"about.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, + {"name":"about.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, + {"name":"about.img","url":"app-icon.js","evaluate":true} + ], + "sortorder": -4 + }, + { + "id": "alarm", + "name": "Default Alarm & Timer", + "shortName": "Alarms", + "version": "0.14", + "description": "Set and respond to alarms and timers", + "icon": "app.png", + "tags": "tool,alarm,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"alarm.app.js","url":"app.js"}, + {"name":"alarm.boot.js","url":"boot.js"}, + {"name":"alarm.js","url":"alarm.js"}, + {"name":"alarm.img","url":"app-icon.js","evaluate":true}, + {"name":"alarm.wid.js","url":"widget.js"} + ], + "data": [{"name":"alarm.json"}] + }, + { + "id": "locale", + "name": "Languages", + "version": "0.14", + "description": "Translations for different countries", + "icon": "locale.png", + "type": "locale", + "tags": "tool,system,locale,translate", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "custom": "locale.html", + "storage": [ + {"name":"locale"} + ], + "sortorder": -10 + }, + { + "id": "notify", + "name": "Notifications (default)", + "shortName": "Notifications", + "version": "0.11", + "description": "Provides the default `notify` module used by applications to display notifications in a bar at the top of the screen. This module is installed by default by client applications such as the Gadgetbridge app. Installing `Fullscreen Notifications` replaces this module with a version that displays the notifications using the full screen", + "icon": "notify.png", + "type": "notify", + "tags": "widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"notify","url":"notify.js"} + ] + }, + { + "id": "notifyfs", + "name": "Fullscreen Notifications", + "shortName": "Notifications", + "version": "0.12", + "description": "Provides a replacement for the `Notifications (default)` `notify` module. This version is used by applications to display notifications fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notify module.", + "icon": "notify.png", + "type": "notify", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"notify","url":"notify.js"} + ] + }, + { + "id": "welcome", + "name": "Welcome", + "shortName": "Welcome", + "version": "0.14", + "description": "Appears at first boot and explains how to use Bangle.js", + "icon": "app.png", + "screenshots": [{"url":"screenshot_welcome.png"}], + "tags": "start,welcome", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"welcome.boot.js","url":"boot.js"}, + {"name":"welcome.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, + {"name":"welcome.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, + {"name":"welcome.settings.js","url":"settings.js"}, + {"name":"welcome.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"welcome.json"}] + }, + { + "id": "mywelcome", + "name": "Customised Welcome", + "shortName": "My Welcome", + "version": "0.13", + "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", + "icon": "app.png", + "tags": "start,welcome", + "supports": ["BANGLEJS","BANGLEJS2"], + "custom": "custom.html", + "screenshots": [{"url":"bangle1-customized-welcome-screenshot.png"}], + "storage": [ + {"name":"mywelcome.boot.js","url":"boot.js"}, + {"name":"mywelcome.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, + {"name":"mywelcome.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, + {"name":"mywelcome.settings.js","url":"settings.js"}, + {"name":"mywelcome.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"mywelcome.json"}] + }, + { + "id": "gbridge", + "name": "Gadgetbridge", + "version": "0.25", + "description": "(NOT RECOMMENDED) Displays Gadgetbridge notifications from Android. Please use the 'Android' Bangle.js app instead.", + "icon": "app.png", + "type": "widget", + "tags": "tool,system,android,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "dependencies": {"notify":"type"}, + "readme": "README.md", + "storage": [ + {"name":"gbridge.settings.js","url":"settings.js"}, + {"name":"gbridge.img","url":"app-icon.js","evaluate":true}, + {"name":"gbridge.wid.js","url":"widget.js"} + ], + "data": [{"name":"gbridge.json"}] + }, + { "id": "gbdebug", + "name": "Gadgetbridge Debug", + "shortName":"GB Debug", + "version":"0.01", + "description": "Debug info for Gadgetbridge. Run this app and when Gadgetbridge messages arrive they are displayed on-screen.", + "icon": "app.png", + "tags": "", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"gbdebug.app.js","url":"app.js"}, + {"name":"gbdebug.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "mclock", + "name": "Morphing Clock", + "version": "0.07", + "description": "7 segment clock that morphs between minutes and hours", + "icon": "clock-morphing.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-morphing-clock-screenshot.png"}], + "storage": [ + {"name":"mclock.app.js","url":"clock-morphing.js"}, + {"name":"mclock.img","url":"clock-morphing-icon.js","evaluate":true} + ], + "sortorder": -9 + }, + { + "id": "moonphase", + "name": "Moonphase", + "version": "0.02", + "description": "Shows current moon phase. Now with GPS function.", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-moon-phase-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"moonphase.app.js","url":"app.js"}, + {"name":"moonphase.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "daysl", + "name": "Days left", + "version": "0.03", + "description": "Shows you the days left until a certain date. Date can be set with a settings app and is written to a file.", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "allow_emulator": false, + "storage": [ + {"name":"daysl.app.js","url":"app.js"}, + {"name":"daysl.img","url":"app-icon.js","evaluate":true}, + {"name":"daysl.wid.js","url":"widget.js"} + ] + }, + { + "id": "wclock", + "name": "Word Clock", + "version": "0.03", + "description": "Display Time as Text", + "icon": "clock-word.png", + "screenshots": [{"url":"screenshot_word.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"wclock.app.js","url":"clock-word.js"}, + {"name":"wclock.img","url":"clock-word-icon.js","evaluate":true} + ] + }, + { + "id": "fontclock", + "name": "Font Clock", + "version": "0.01", + "description": "Choose the font and design of clock face from a library of available designs", + "icon": "fontclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "custom": "custom.html", + "allow_emulator": false, + "storage": [ + {"name":"fontclock.app.js","url":"fontclock.js"}, + {"name":"fontclock.img","url":"fontclock-icon.js","evaluate":true}, + {"name":"fontclock.hand.js","url":"fontclock.hand.js"}, + {"name":"fontclock.thinhand.js","url":"fontclock.thinhand.js"}, + {"name":"fontclock.thickhand.js","url":"fontclock.thickhand.js"}, + {"name":"fontclock.hourscriber.js","url":"fontclock.hourscriber.js"}, + {"name":"fontclock.font.js","url":"fontclock.font.js"}, + {"name":"fontclock.font.abril_ff50.js","url":"fontclock.font.abril_ff50.js"}, + {"name":"fontclock.font.cpstc58.js","url":"fontclock.font.cpstc58.js"}, + {"name":"fontclock.font.mntn25.js","url":"fontclock.font.mntn25.js"}, + {"name":"fontclock.font.mntn50.js","url":"fontclock.font.mntn50.js"}, + {"name":"fontclock.font.vector25.js","url":"fontclock.font.vector25.js"}, + {"name":"fontclock.font.vector50.js","url":"fontclock.font.vector50.js"} + ] + }, + { + "id": "slidingtext", + "name": "Sliding Clock", + "version": "0.07", + "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported", + "icon": "slidingtext.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "custom": "custom.html", + "allow_emulator": false, + "storage": [ + {"name":"slidingtext.app.js","url":"slidingtext.js"}, + {"name":"slidingtext.img","url":"slidingtext-icon.js","evaluate":true}, + {"name":"slidingtext.locale.en.js","url":"slidingtext.locale.en.js"}, + {"name":"slidingtext.locale.en2.js","url":"slidingtext.locale.en2.js"}, + {"name":"slidingtext.utils.en.js","url":"slidingtext.utils.en.js"}, + {"name":"slidingtext.locale.es.js","url":"slidingtext.locale.es.js"}, + {"name":"slidingtext.locale.fr.js","url":"slidingtext.locale.fr.js"}, + {"name":"slidingtext.locale.jp.js","url":"slidingtext.locale.jp.js"}, + {"name":"slidingtext.locale.de.js","url":"slidingtext.locale.de.js"}, + {"name":"slidingtext.dtfmt.js","url":"slidingtext.dtfmt.js"} + ] + }, + { + "id": "solarclock", + "name": "Solar Clock", + "version": "0.02", + "description": "Using your current or chosen location the solar watch face shows the Sun's sky position, time and date. Also allows you to wind backwards and forwards in time to see the sun's position", + "icon": "solar_clock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "custom": "custom.html", + "allow_emulator": false, + "storage": [ + {"name":"solarclock.app.js","url":"solar_clock.js"}, + {"name":"solarclock.img","url":"solar_clock-icon.js","evaluate":true}, + {"name":"solar_colors.js","url":"solar_colors.js"}, + {"name":"solar_controller.js","url":"solar_controller.js"}, + {"name":"solar_date_utils.js","url":"solar_date_utils.js"}, + {"name":"solar_graphic_utils.js","url":"solar_graphic_utils.js"}, + {"name":"solar_location.js","url":"solar_location.js"}, + {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, + {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, + {"name":"solar_loc.Hong_Kong.json","url":"solar_loc.Hong_Kong.json"}, + {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, + {"name":"solar_loc.Rio.json","url":"solar_loc.Rio.json"}, + {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, + {"name":"solar_loc.Seoul.json","url":"solar_loc.Seoul.json"} + ] + }, + { + "id": "sweepclock", + "name": "Sweep Clock", + "version": "0.04", + "description": "Smooth sweep secondhand with single hour numeral. Use button 1 to toggle the numeral font, button 3 to change the colour theme and button 4 to change the date placement", + "icon": "sweepclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-sweep-clock-screenshot.png"}], + "storage": [ + {"name":"sweepclock.app.js","url":"sweepclock.js"}, + {"name":"sweepclock.img","url":"sweepclock-icon.js","evaluate":true} + ] + }, + { + "id": "matrixclock", + "name": "Matrix Clock", + "version": "0.02", + "description": "inspired by The Matrix, a clock of the same style", + "icon": "matrixclock.png", + "screenshots": [{"url":"screenshot_matrix.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"matrixclock.app.js","url":"matrixclock.js"}, + {"name":"matrixclock.img","url":"matrixclock-icon.js","evaluate":true} + ] + }, + { + "id": "mandelbrotclock", + "name": "Mandelbrot Clock", + "version": "0.01", + "description": "A mandelbrot set themed clock cool", + "icon": "mandelbrotclock.png", + "screenshots": [{ "url": "screenshot_mandelbrotclock.png" }], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + { "name": "mandelbrotclock.app.js", "url": "mandelbrotclock.js" }, + { + "name": "mandelbrotclock.img", + "url": "mandelbrotclock-icon.js", + "evaluate": true + } + ] + }, + { + "id": "imgclock", + "name": "Image background clock", + "shortName": "Image Clock", + "version": "0.08", + "description": "A clock with an image as a background", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "custom": "custom.html", + "storage": [ + {"name":"imgclock.app.js","url":"app.js"}, + {"name":"imgclock.img","url":"app-icon.js","evaluate":true}, + {"name":"imgclock.face.img"}, + {"name":"imgclock.face.json"}, + {"name":"imgclock.face.bg","content":""} + ] + }, + { + "id": "impwclock", + "name": "Imprecise Word Clock", + "version": "0.04", + "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", + "icon": "clock-impword.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"impwclock.app.js","url":"clock-impword.js"}, + {"name":"impwclock.img","url":"clock-impword-icon.js","evaluate":true} + ] + }, + { + "id": "aclock", + "name": "Analog Clock", + "version": "0.15", + "description": "An Analog Clock", + "icon": "clock-analog.png", + "screenshots": [{"url":"screenshot_analog.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"aclock.app.js","url":"clock-analog.js"}, + {"name":"aclock.img","url":"clock-analog-icon.js","evaluate":true} + ] + }, + { + "id": "clock2x3", + "name": "2x3 Pixel Clock", + "version": "0.05", + "description": "This is a simple clock using minimalist 2x3 pixel numerical digits", + "icon": "clock2x3.png", + "screenshots": [{"url":"screenshot_pixel.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"clock2x3.app.js","url":"clock2x3-app.js"}, + {"name":"clock2x3.img","url":"clock2x3-icon.js","evaluate":true} + ] + }, + { + "id": "geissclk", + "name": "Geiss Clock", + "version": "0.03", + "description": "7 segment clock with animated background in the style of Ryan Geiss' music visualisation. NOTE: The first run will take ~1 minute to do some precalculation", + "icon": "clock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"geissclk.app.js","url":"clock.js"}, + {"name":"geissclk.precompute.js","url":"precompute.js"}, + {"name":"geissclk.img","url":"clock-icon.js","evaluate":true} + ], + "data": [{"name":"geissclk.0.map"},{"name":"geissclk.1.map"},{"name":"geissclk.2.map"},{"name":"geissclk.3.map"},{"name":"geissclk.4.map"},{"name":"geissclk.5.map"},{"name":"geissclk.0.pal"},{"name":"geissclk.1.pal"},{"name":"geissclk.2.pal"}] + }, + { + "id": "trex", + "name": "T-Rex", + "version": "0.04", + "description": "T-Rex game in the style of Chrome's offline game", + "icon": "trex.png", + "screenshots": [{"url":"screenshot_trex.png"}], + "tags": "game", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"trex.app.js","url":"trex.js"}, + {"name":"trex.img","url":"trex-icon.js","evaluate":true}, + {"name":"trex.settings.js","url":"settings.js"} + ], + "data": [{"name":"trex.score","storageFile":true}] + }, + { + "id": "cubescramble", + "name": "Cube Scramble", + "version":"0.04", + "description": "A random scramble generator for the 3x3 Rubik's cube with a basic timer", + "icon": "cube-scramble.png", + "tags": "", + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle2-cube-scramble-screenshot.png"},{"url":"bangle1-cube-scramble-screenshot.png"}], + "storage": [ + {"name":"cubescramble.app.js","url":"cube-scramble.js"}, + {"name":"cubescramble.img","url":"cube-scramble-icon.js","evaluate":true} + ] + }, + { + "id": "astroid", + "name": "Asteroids!", + "version": "0.03", + "description": "Retro asteroids game", + "icon": "asteroids.png", + "screenshots": [{"url":"screenshot_asteroids.png"}], + "tags": "game", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"astroid.app.js","url":"asteroids.js"}, + {"name":"astroid.img","url":"asteroids-icon.js","evaluate":true} + ] + }, + { + "id": "clickms", + "name": "Click Master", + "version": "0.01", + "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", + "icon": "click-master.png", + "tags": "game", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"clickms.app.js","url":"click-master.js"}, + {"name":"clickms.img","url":"click-master-icon.js","evaluate":true} + ] + }, + { + "id": "horsey", + "name": "Horse Race!", + "version": "0.01", + "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", + "icon": "horse-race.png", + "tags": "game", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"horsey.app.js","url":"horse-race.js"}, + {"name":"horsey.img","url":"horse-race-icon.js","evaluate":true} + ] + }, + { + "id": "compass", + "name": "Compass", + "version": "0.05", + "description": "Simple compass that points North", + "icon": "compass.png", + "screenshots": [{"url":"screenshot_compass.png"}], + "tags": "tool,outdoors", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"compass.app.js","url":"compass.js"}, + {"name":"compass.img","url":"compass-icon.js","evaluate":true} + ] + }, + { + "id": "gpstime", + "name": "GPS Time", + "version": "0.05", + "description": "Update the Bangle.js's clock based on the time from the GPS receiver", + "icon": "gpstime.png", + "tags": "tool,gps", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"gpstime.app.js","url":"gpstime.js"}, + {"name":"gpstime.img","url":"gpstime-icon.js","evaluate":true} + ] + }, + { + "id": "openloc", + "name": "Open Location / Plus Codes", + "shortName": "Open Location", + "version": "0.01", + "description": "Convert your current GPS location to a series of characters", + "icon": "app.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"openloc.app.js","url":"app.js"}, + {"name":"openloc.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "speedo", + "name": "Speedo", + "version": "0.05", + "description": "Show the current speed according to the GPS", + "icon": "speedo.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"speedo.app.js","url":"speedo.js"}, + {"name":"speedo.img","url":"speedo-icon.js","evaluate":true} + ] + }, + { + "id": "gpsrec", + "name": "GPS Recorder", + "version": "0.27", + "description": "Application that allows you to record a GPS track. Can run in background", + "icon": "app.png", + "tags": "tool,outdoors,gps,widget", + "screenshots": [{"url":"screenshot.png"}], + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"gpsrec.app.js","url":"app.js"}, + {"name":"gpsrec.img","url":"app-icon.js","evaluate":true}, + {"name":"gpsrec.wid.js","url":"widget.js"}, + {"name":"gpsrec.settings.js","url":"settings.js"} + ], + "data": [{"name":"gpsrec.json"},{"wildcard":".gpsrc?","storageFile":true}] + }, + { + "id": "recorder", + "name": "Recorder (BETA)", + "shortName": "Recorder", + "version": "0.04", + "description": "Record GPS position, heart rate and more in the background, then download to your PC.", + "icon": "app.png", + "tags": "tool,outdoors,gps,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"recorder.app.js","url":"app.js"}, + {"name":"recorder.img","url":"app-icon.js","evaluate":true}, + {"name":"recorder.wid.js","url":"widget.js"}, + {"name":"recorder.settings.js","url":"settings.js"} + ], + "data": [{"name":"recorder.json"},{"wildcard":"recorder.log?.csv","storageFile":true}] + }, + { + "id": "gpsnav", + "name": "GPS Navigation", + "version": "0.05", + "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording, now with waypoint editor", + "icon": "icon.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "waypoints.html", + "storage": [ + {"name":"gpsnav.app.js","url":"app.min.js"}, + {"name":"gpsnav.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"waypoints.json","url":"waypoints.json"}] + }, + { + "id": "heart", + "name": "Heart Rate Recorder", + "shortName": "HRM Record", + "version": "0.07", + "description": "Application that allows you to record your heart rate. Can run in background", + "icon": "app.png", + "tags": "tool,health,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "interface": "interface.html", + "storage": [ + {"name":"heart.app.js","url":"app.js"}, + {"name":"heart.img","url":"app-icon.js","evaluate":true}, + {"name":"heart.wid.js","url":"widget.js"} + ], + "data": [{"name":"heart.json"},{"wildcard":".heart?","storageFile":true}] + }, + { + "id": "slevel", + "name": "Spirit Level", + "version": "0.02", + "description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat", + "icon": "spiritlevel.png", + "tags": "tool", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"slevel.app.js","url":"spiritlevel.js"}, + {"name":"slevel.img","url":"spiritlevel-icon.js","evaluate":true} + ] + }, + { + "id": "files", + "name": "App Manager", + "version": "0.07", + "description": "Show currently installed apps, free space, and allow their deletion from the watch", + "icon": "files.png", + "tags": "tool,system,files", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"files.app.js","url":"files.js"}, + {"name":"files.img","url":"files-icon.js","evaluate":true} + ] + }, + { + "id": "weather", + "name": "Weather", + "version": "0.13", + "description": "Show Gadgetbridge weather report", + "icon": "icon.png", + "screenshots": [{"url":"screenshot.png"}], + "tags": "widget,outdoors", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "readme.md", + "storage": [ + {"name":"weather.app.js","url":"app.js"}, + {"name":"weather.wid.js","url":"widget.js"}, + {"name":"weather","url":"lib.js"}, + {"name":"weather.img","url":"icon.js","evaluate":true}, + {"name":"weather.settings.js","url":"settings.js"} + ], + "data": [{"name":"weather.json"}] + }, + { + "id": "chargeanim", + "name": "Charge Animation", + "version": "0.02", + "description": "When charging, show a sideways charging animation and keep the screen on. When removed from the charger load the clock again.", + "icon": "icon.png", + "tags": "battery", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-charge-animation-screenshot.png"},{"url":"bangle-charge-animation-screenshot.png"}], + "storage": [ + {"name":"chargeanim.app.js","url":"app.js"}, + {"name":"chargeanim.boot.js","url":"boot.js"}, + {"name":"chargeanim.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "bluetoothdock", + "name": "Bluetooth Dock", + "shortName": "Dock", + "version": "0.01", + "description": "When charging shows the time, scans Bluetooth for known devices (eg temperature) and shows them on the screen", + "icon": "app.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"bluetoothdock.app.js","url":"app.js"}, + {"name":"bluetoothdock.boot.js","url":"boot.js"}, + {"name":"bluetoothdock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widbat", + "name": "Battery Level Widget", + "version": "0.09", + "description": "Show the current battery level and charging status in the top right of the clock", + "icon": "widget.png", + "type": "widget", + "tags": "widget,battery", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widbat.wid.js","url":"widget.js"} + ] + }, + { + "id": "widbatv", + "name": "Battery Level Widget (Vertical)", + "version": "0.01", + "description": "Slim, vertical battery widget that only takes up 14px", + "icon": "widget.png", + "type": "widget", + "tags": "widget,battery", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widbatv.wid.js","url":"widget.js"} + ] + }, + { + "id": "widlock", + "name": "Lock Widget", + "version": "0.03", + "description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked", + "icon": "widget.png", + "type": "widget", + "tags": "widget,lock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widlock.wid.js","url":"widget.js"} + ] + }, + { + "id": "widbatpc", + "name": "Battery Level Widget (with percentage)", + "shortName": "Battery Widget", + "version": "0.14", + "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", + "icon": "widget.png", + "type": "widget", + "tags": "widget,battery", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"widbatpc.wid.js","url":"widget.js"}, + {"name":"widbatpc.settings.js","url":"settings.js"} + ], + "data": [{"name":"widbatpc.json"}] + }, + { + "id": "widbatwarn", + "name": "Battery Warning", + "shortName": "Battery Warning", + "version": "0.02", + "description": "Show a warning when the battery runs low.", + "icon": "widget.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "widget", + "tags": "tool,battery", + "supports": ["BANGLEJS"], + "dependencies": {"notify":"type"}, + "readme": "README.md", + "storage": [ + {"name":"widbatwarn.wid.js","url":"widget.js"}, + {"name":"widbatwarn.settings.js","url":"settings.js"} + ], + "data": [{"name":"widbatwarn.json"}] + }, + { + "id": "widbt", + "name": "Bluetooth Widget", + "version": "0.07", + "description": "Show the current Bluetooth connection status in the top right of the clock", + "icon": "widget.png", + "type": "widget", + "tags": "widget,bluetooth", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widbt.wid.js","url":"widget.js"} + ] + }, + { + "id": "widchime", + "name": "Hour Chime", + "version": "0.02", + "description": "Buzz or beep on every whole hour.", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widchime.wid.js","url":"widget.js"}, + {"name":"widchime.settings.js","url":"settings.js"} + ], + "data": [{"name":"widchime.json"}] + }, + { + "id": "widram", + "name": "RAM Widget", + "shortName": "RAM Widget", + "version": "0.01", + "description": "Display your Bangle's available RAM percentage in a widget", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widram.wid.js","url":"widget.js"} + ] + }, + { + "id": "hrm", + "name": "Heart Rate Monitor", + "version": "0.06", + "description": "Measure your heart rate and see live sensor data", + "icon": "heartrate.png", + "tags": "health", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"hrm.app.js","url":"heartrate.js"}, + {"name":"hrm.img","url":"heartrate-icon.js","evaluate":true} + ] + }, + { + "id": "widhrm", + "name": "Simple Heart Rate widget", + "version": "0.05", + "description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.", + "icon": "widget.png", + "type": "widget", + "tags": "health,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widhrm.wid.js","url":"widget.js"} + ] + }, + { + "id": "bthrm", + "name": "Bluetooth Heart Rate Monitor", + "shortName": "BT HRM", + "version": "0.01", + "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", + "icon": "app.png", + "type": "boot", + "tags": "health,bluetooth", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"bthrm.boot.js","url":"boot.js"}, + {"name":"bthrm.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "stetho", + "name": "Stethoscope", + "version": "0.01", + "description": "Hear your heart rate", + "icon": "stetho.png", + "tags": "health", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"stetho.app.js","url":"stetho.js"}, + {"name":"stetho.img","url":"stetho-icon.js","evaluate":true} + ] + }, + { + "id": "swatch", + "name": "Stopwatch", + "version": "0.07", + "description": "Simple stopwatch with Lap Time logging to a JSON file", + "icon": "stopwatch.png", + "tags": "health", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "interface.html", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-stopwatch-screenshot.png"}], + "storage": [ + {"name":"swatch.app.js","url":"stopwatch.js"}, + {"name":"swatch.img","url":"stopwatch-icon.js","evaluate":true} + ] + }, + { + "id": "hidmsic", + "name": "Bluetooth Music Controls", + "shortName": "Music Control", + "version": "0.02", + "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", + "icon": "hid-music.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"hidmsic.app.js","url":"hid-music.js"}, + {"name":"hidmsic.img","url":"hid-music-icon.js","evaluate":true} + ] + }, + { + "id": "hidkbd", + "name": "Bluetooth Keyboard", + "shortName": "Bluetooth Kbd", + "version": "0.02", + "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", + "icon": "hid-keyboard.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"hidkbd.app.js","url":"hid-keyboard.js"}, + {"name":"hidkbd.img","url":"hid-keyboard-icon.js","evaluate":true} + ] + }, + { + "id": "hidbkbd", + "name": "Binary Bluetooth Keyboard", + "shortName": "Binary BT Kbd", + "version": "0.02", + "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", + "icon": "hid-binary-keyboard.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"hidbkbd.app.js","url":"hid-binary-keyboard.js"}, + {"name":"hidbkbd.img","url":"hid-binary-keyboard-icon.js","evaluate":true} + ] + }, + { + "id": "animals", + "name": "Animals Game", + "version": "0.01", + "description": "Simple toddler's game - displays a different number of animals each time the screen is pressed", + "icon": "animals.png", + "tags": "game", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"animals.app.js","url":"animals.js"}, + {"name":"animals.img","url":"animals-icon.js","evaluate":true}, + {"name":"animals-snake.img","url":"animals-snake.js","evaluate":true}, + {"name":"animals-duck.img","url":"animals-duck.js","evaluate":true}, + {"name":"animals-swan.img","url":"animals-swan.js","evaluate":true}, + {"name":"animals-fox.img","url":"animals-fox.js","evaluate":true}, + {"name":"animals-camel.img","url":"animals-camel.js","evaluate":true}, + {"name":"animals-pig.img","url":"animals-pig.js","evaluate":true}, + {"name":"animals-sheep.img","url":"animals-sheep.js","evaluate":true}, + {"name":"animals-mouse.img","url":"animals-mouse.js","evaluate":true} + ] + }, + { + "id": "qrcode", + "name": "Custom QR Code", + "version": "0.04", + "description": "Use this to upload a customised QR code to Bangle.js", + "icon": "app.png", + "tags": "qrcode", + "supports": ["BANGLEJS","BANGLEJS2"], + "custom": "custom.html", + "customConnect": true, + "storage": [ + {"name":"qrcode.app.js"}, + {"name":"qrcode.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "beer", + "name": "Beer Compass", + "version": "0.01", + "description": "Uploads all the pubs in an area onto your watch, so it can always point you at the nearest one", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "custom": "custom.html", + "storage": [ + {"name":"beer.app.js"}, + {"name":"beer.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "route", + "name": "Route Viewer", + "version": "0.02", + "description": "Upload a KML file of a route, and have your watch display a map with how far around it you are", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "custom": "custom.html", + "storage": [ + {"name":"route.app.js"}, + {"name":"route.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "ncstart", + "name": "NCEU Startup", + "version": "0.06", + "description": "NodeConfEU 2019 'First Start' Sequence", + "icon": "start.png", + "tags": "start,welcome", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"ncstart.app.js","url":"start.js"}, + {"name":"ncstart.boot.js","url":"boot.js"}, + {"name":"ncstart.settings.js","url":"settings.js"}, + {"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}, + {"name":"nc-nfr.img","url":"start-nfr.js","evaluate":true}, + {"name":"nc-nodew.img","url":"start-nodew.js","evaluate":true}, + {"name":"nc-tf.img","url":"start-tf.js","evaluate":true} + ], + "data": [{"name":"ncstart.json"}] + }, + { + "id": "ncfrun", + "name": "NCEU 5K Fun Run", + "version": "0.01", + "description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it", + "icon": "nceu-funrun.png", + "tags": "health", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"ncfrun.app.js","url":"nceu-funrun.js"}, + {"name":"ncfrun.img","url":"nceu-funrun-icon.js","evaluate":true} + ] + }, + { + "id": "widnceu", + "name": "NCEU Logo Widget", + "version": "0.02", + "description": "Show the NodeConf EU logo in the top left", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"widnceu.wid.js","url":"widget.js"} + ] + }, + { + "id": "sclock", + "name": "Simple Clock", + "version": "0.07", + "description": "A Simple Digital Clock", + "icon": "clock-simple.png", + "screenshots": [{"url":"screenshot_simplec.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"sclock.app.js","url":"clock-simple.js"}, + {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} + ] + }, + { + "id": "s7clk", + "name": "Simple 7 segment Clock", + "version": "0.03", + "description": "A simple 7 segment Clock with date", + "icon": "icon.png", + "screenshots": [{"url":"screenshot_s7segment.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"s7clk.app.js","url":"app.js"}, + {"name":"s7clk.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "vibrclock", + "name": "Vibrate Clock", + "version": "0.03", + "description": "When BTN1 is pressed, vibrate out the time as a series of buzzes, one digit at a time. Hours, then Minutes. Zero is signified by one long buzz. Otherwise a simple digital clock.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-vibrate-clock-screenshot.png"}], + "storage": [ + {"name":"vibrclock.app.js","url":"app.js"}, + {"name":"vibrclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "svclock", + "name": "Simple V-Clock", + "version": "0.04", + "description": "Modification of Simple Clock 0.04 to use Vectorfont", + "icon": "vclock-simple.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-simple-v-clock-screenshot.png"}], + "storage": [ + {"name":"svclock.app.js","url":"vclock-simple.js"}, + {"name":"svclock.img","url":"vclock-simple-icon.js","evaluate":true} + ] + }, + { + "id": "dclock", + "name": "Dev Clock", + "version": "0.10", + "description": "A Digital Clock including timestamp (tst), beats(@), days in current month (dm) and days since new moon (l)", + "icon": "clock-dev.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-dev-clock-screenshot.png"},{"url":"bangle1-dev-clock-screenshot.png"}], + "storage": [ + {"name":"dclock.app.js","url":"clock-dev.js"}, + {"name":"dclock.img","url":"clock-dev-icon.js","evaluate":true} + ] + }, + { + "id": "gesture", + "name": "Gesture Test", + "version": "0.01", + "description": "BETA! Uploads a basic Tensorflow Gesture model, and then outputs each gesture as a message", + "icon": "gesture.png", + "type": "app", + "tags": "gesture,ai", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"gesture.app.js","url":"gesture.js"}, + {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, + {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, + {"name":"gesture.img","url":"gesture-icon.js","evaluate":true} + ] + }, + { + "id": "pparrot", + "name": "Party Parrot", + "version": "0.01", + "description": "Party with a parrot on your wrist", + "icon": "party-parrot.png", + "type": "app", + "tags": "party,parrot,lol", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-party-parrot-screenshot.png"}], + "storage": [ + {"name":"pparrot.app.js","url":"party-parrot.js"}, + {"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true} + ] + }, + { + "id": "hrings", + "name": "Hypno Rings", + "version": "0.01", + "description": "Experiment with trippy rings, press buttons for change", + "icon": "hypno-rings.png", + "type": "app", + "tags": "rings,hypnosis,psychadelic", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-hypno-rings-screenshot.png"}], + "storage": [ + {"name":"hrings.app.js","url":"hypno-rings.js"}, + {"name":"hrings.img","url":"hypno-rings-icon.js","evaluate":true} + ] + }, + { + "id": "morse", + "name": "Morse Code", + "version": "0.01", + "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", + "icon": "morse-code.png", + "type": "app", + "tags": "morse,sound,visual,input", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"morse.app.js","url":"morse-code.js"}, + {"name":"morse.img","url":"morse-code-icon.js","evaluate":true} + ] + }, + { + "id": "blescan", + "name": "BLE Scanner", + "version": "0.01", + "description": "Scan for advertising BLE devices", + "icon": "blescan.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"blescan.app.js","url":"blescan.js"}, + {"name":"blescan.img","url":"blescan-icon.js","evaluate":true} + ] + }, + { + "id": "mmonday", + "name": "Manic Monday Tone", + "version": "0.02", + "description": "The Bangles make a comeback", + "icon": "manic-monday-icon.png", + "tags": "sound", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"mmonday.app.js","url":"manic-monday.js"}, + {"name":"mmonday.img","url":"manic-monday-icon.js","evaluate":true} + ] + }, + { + "id": "jbells", + "name": "Jingle Bells", + "version": "0.01", + "description": "Play Jingle Bells", + "icon": "jbells.png", + "type": "app", + "tags": "sound", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"jbells.app.js","url":"jbells.js"}, + {"name":"jbells.img","url":"jbells-icon.js","evaluate":true} + ] + }, + { + "id": "scolor", + "name": "Show Color", + "version": "0.01", + "description": "Display all available Colors and Names", + "icon": "show-color.png", + "type": "app", + "tags": "tool", + "screenshots": [{"url":"bangle1-view-color-screenshot.png"}], + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"scolor.app.js","url":"show-color.js"}, + {"name":"scolor.img","url":"show-color-icon.js","evaluate":true} + ] + }, + { + "id": "miclock", + "name": "Mixed Clock", + "version": "0.05", + "description": "A mix of analog and digital Clock", + "icon": "clock-mixed.png", + "type": "clock", + "tags": "clock", + "screenshots": [{"url":"bangle1-mixed-clock-screenshot.png"}], + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"miclock.app.js","url":"clock-mixed.js"}, + {"name":"miclock.img","url":"clock-mixed-icon.js","evaluate":true} + ] + }, + { + "id": "bclock", + "name": "Binary Clock", + "version": "0.03", + "description": "A simple binary clock watch face", + "icon": "clock-binary.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-binary-clock-screenshot.png"}], + "storage": [ + {"name":"bclock.app.js","url":"clock-binary.js"}, + {"name":"bclock.img","url":"clock-binary-icon.js","evaluate":true} + ] + }, + { + "id": "clotris", + "name": "Clock-Tris", + "version": "0.01", + "description": "A fully functional clone of a classic game of falling blocks", + "icon": "clock-tris.png", + "tags": "game", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-clock-tris-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"clotris.app.js","url":"clock-tris.js"}, + {"name":"clotris.img","url":"clock-tris-icon.js","evaluate":true}, + {"name":".trishig","url":"clock-tris-high"} + ] + }, + { + "id": "flappy", + "name": "Flappy Bird", + "version": "0.05", + "description": "A Flappy Bird game clone", + "icon": "app.png", + "screenshots": [{"url":"screenshot1_flappy.png"},{"url":"screenshot2_flappy.png"}], + "tags": "game", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"flappy.app.js","url":"app.js"}, + {"name":"flappy.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "gpsinfo", + "name": "GPS Info", + "version": "0.05", + "description": "An application that displays information about altitude, lat/lon, satellites and time", + "icon": "gps-info.png", + "type": "app", + "tags": "gps", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"gpsinfo.app.js","url":"gps-info.js"}, + {"name":"gpsinfo.img","url":"gps-info-icon.js","evaluate":true} + ] + }, + { + "id": "assistedgps", + "name": "Assisted GPS Update (AGPS)", + "version": "0.01", + "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", + "icon": "app.png", + "type": "RAM", + "tags": "tool,outdoors,agps", + "supports": ["BANGLEJS"], + "custom": "custom.html", + "storage": [] + }, + { + "id": "pomodo", + "name": "Pomodoro", + "version": "0.02", + "description": "A simple pomodoro timer.", + "icon": "pomodoro.png", + "type": "app", + "tags": "pomodoro,cooking,tools", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-pomodoro-screenshot.png"}], + "storage": [ + {"name":"pomodo.app.js","url":"pomodoro.js"}, + {"name":"pomodo.img","url":"pomodoro-icon.js","evaluate":true} + ] + }, + { + "id": "blobclk", + "name": "Large Digit Blob Clock", + "shortName": "Blob Clock", + "version": "0.06", + "description": "A clock with big digits", + "icon": "clock-blob.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-large-digit-blob-clock-screenshot.png"},{"url":"bangle1-large-digit-blob-clock-screenshot.png"}], + "storage": [ + {"name":"blobclk.app.js","url":"clock-blob.js"}, + {"name":"blobclk.img","url":"clock-blob-icon.js","evaluate":true} + ] + }, + { + "id": "boldclk", + "name": "Bold Clock", + "version": "0.05", + "description": "Simple, readable and practical clock", + "icon": "bold_clock.png", + "screenshots": [{"url":"screenshot_bold.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"boldclk.app.js","url":"bold_clock.js"}, + {"name":"boldclk.img","url":"bold_clock-icon.js","evaluate":true} + ] + }, + { + "id": "widclk", + "name": "Digital clock widget", + "version": "0.06", + "description": "A simple digital clock widget", + "icon": "widget.png", + "type": "widget", + "tags": "widget,clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widclk.wid.js","url":"widget.js"} + ] + }, + { + "id": "widpedom", + "name": "Pedometer widget", + "version": "0.20", + "description": "Daily pedometer widget", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widpedom.wid.js","url":"widget.js"}, + {"name":"widpedom.settings.js","url":"settings.js"} + ] + }, + { + "id": "berlinc", + "name": "Berlin Clock", + "version": "0.05", + "description": "Berlin Clock (see https://en.wikipedia.org/wiki/Mengenlehreuhr)", + "icon": "berlin-clock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"berlin-clock-screenshot.png"}], + "storage": [ + {"name":"berlinc.app.js","url":"berlin-clock.js"}, + {"name":"berlinc.img","url":"berlin-clock-icon.js","evaluate":true} + ] + }, + { + "id": "ctrclk", + "name": "Centerclock", + "version": "0.03", + "description": "Watch-centered digital 24h clock with date in dd.mm.yyyy format.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-center-clock-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"ctrclk.app.js","url":"app.js"}, + {"name":"ctrclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "demoapp", + "name": "Demo Loop", + "version": "0.02", + "description": "Simple demo app - displays Bangle.js, JS logo, graphics, and Bangle.js information", + "icon": "app.png", + "type": "app", + "tags": "", + "screenshots": [{"url":"bangle1-demo-loop-screenshot1.png"},{"url":"bangle1-demo-loop-screenshot2.png"},{"url":"bangle1-demo-loop-screenshot3.png"},{"url":"bangle1-demo-loop-screenshot4.png"}], + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"demoapp.app.js","url":"app.js"}, + {"name":"demoapp.img","url":"app-icon.js","evaluate":true} + ], + "sortorder": -9 + }, + { + "id": "flagrse", + "name": "Espruino Flag Raiser", + "version": "0.01", + "description": "App to send a command to another Espruino to cause it to raise a flag", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"flagrse.app.js","url":"app.js"}, + {"name":"flagrse.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "pipboy", + "name": "Pipboy", + "version": "0.04", + "description": "Pipboy themed clock", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-pipboy-themed-clock-screenshot.png"}], + "storage": [ + {"name":"pipboy.app.js","url":"app.js"}, + {"name":"pipboy.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "torch", + "name": "Torch", + "shortName": "Torch", + "version": "0.02", + "description": "Turns screen white to help you see in the dark. Select from the launcher or press BTN1,BTN3,BTN1,BTN3 quickly to start when in any app that shows widgets", + "icon": "app.png", + "tags": "tool,torch", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"torch.app.js","url":"app.js"}, + {"name":"torch.wid.js","url":"widget.js"}, + {"name":"torch.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "rtorch", + "name": "Red Torch", + "shortName": "RedTorch", + "version": "0.02", + "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or on Bangle 1 press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", + "icon": "app.png", + "tags": "tool,torch", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"rtorch.app.js","url":"app.js"}, + {"name":"rtorch.wid.js","url":"widget.js", "supports": ["BANGLEJS"]}, + {"name":"rtorch.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "wohrm", + "name": "Workout HRM", + "version": "0.08", + "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", + "icon": "app.png", + "type": "app", + "tags": "hrm,workout", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], + "storage": [ + {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widid", + "name": "Bluetooth ID Widget", + "version": "0.03", + "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", + "icon": "widget.png", + "type": "widget", + "tags": "widget,address,mac", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widid.wid.js","url":"widget.js"} + ] + }, + { + "id": "grocery", + "name": "Grocery", + "version": "0.02", + "description": "Simple grocery (shopping) list - Display a list of product and track if you already put them in your cart.", + "icon": "grocery.png", + "type": "app", + "tags": "tool,outdoors,shopping,list", + "supports": ["BANGLEJS"], + "custom": "grocery.html", + "storage": [ + {"name":"grocery.app.js","url":"app.js"}, + {"name":"grocery.img","url":"grocery-icon.js","evaluate":true} + ] + }, + { + "id": "marioclock", + "name": "Mario Clock", + "version": "0.15", + "description": "Animated retro Mario clock, with Gameboy style 8-bit grey-scale graphics.", + "icon": "marioclock.png", + "type": "clock", + "tags": "clock,mario,retro", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": false, + "screenshots": [{"url":"bangle1-mario-clock-screenshot.png"}], + "storage": [ + {"name":"marioclock.app.js","url":"marioclock-app.js"}, + {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} + ] + }, + { + "id": "cliock", + "name": "Commandline-Clock", + "shortName": "CLI-Clock", + "version": "0.15", + "description": "Simple CLI-Styled Clock", + "icon": "app.png", + "screenshots": [{"url":"screenshot_cli.png"}], + "type": "clock", + "tags": "clock,cli,command,bash,shell", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"cliock.app.js","url":"app.js"}, + {"name":"cliock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widver", + "name": "Firmware Version Widget", + "version": "0.03", + "description": "Display the version of the installed firmware in the top widget section.", + "icon": "widget.png", + "type": "widget", + "tags": "widget,tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widver.wid.js","url":"widget.js"} + ] + }, + { + "id": "barclock", + "name": "Bar Clock", + "version": "0.09", + "description": "A simple digital clock showing seconds as a bar", + "icon": "clock-bar.png", + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"barclock.app.js","url":"clock-bar.js"}, + {"name":"barclock.img","url":"clock-bar-icon.js","evaluate":true} + ] + }, + { + "id": "dotclock", + "name": "Dot Clock", + "version": "0.03", + "description": "A Minimal Dot Analog Clock", + "icon": "clock-dot.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle2-dot-clcok-screenshot.png"},{"url":"bangle1-dot-clock-screenshot.png"}], + "storage": [ + {"name":"dotclock.app.js","url":"clock-dot.js"}, + {"name":"dotclock.img","url":"clock-dot-icon.js","evaluate":true} + ] + }, + { + "id": "widtbat", + "name": "Tiny Battery Widget", + "version": "0.02", + "description": "Tiny blueish battery widget, vibs and changes level color when charging", + "icon": "widget.png", + "type": "widget", + "tags": "widget,tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widtbat.wid.js","url":"widget.js"} + ] + }, + { + "id": "chrono", + "name": "Chrono", + "shortName": "Chrono", + "version": "0.01", + "description": "Single click BTN1 to add 5 minutes. Single click BTN2 to add 30 seconds. Single click BTN3 to add 5 seconds. Tap to pause or play to timer. Double click BTN1 to reset. When timer finishes the watch vibrates.", + "icon": "chrono.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"chrono.app.js","url":"chrono.js"}, + {"name":"chrono.img","url":"chrono-icon.js","evaluate":true} + ] + }, + { + "id": "astrocalc", + "name": "Astrocalc", + "version": "0.02", + "description": "Calculates interesting information on the sun and moon cycles for the current day based on your location.", + "icon": "astrocalc.png", + "tags": "app,sun,moon,cycles,tool,outdoors", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"astrocalc.app.js","url":"astrocalc-app.js"}, + {"name":"suncalc.js","url":"suncalc.js"}, + {"name":"astrocalc.img","url":"astrocalc-icon.js","evaluate":true}, + {"name":"first-quarter.img","url":"first-quarter-icon.js","evaluate":true}, + {"name":"last-quarter.img","url":"last-quarter-icon.js","evaluate":true}, + {"name":"waning-crescent.img","url":"waning-crescent-icon.js","evaluate":true}, + {"name":"waning-gibbous.img","url":"waning-gibbous-icon.js","evaluate":true}, + {"name":"full.img","url":"full-icon.js","evaluate":true}, + {"name":"new.img","url":"new-icon.js","evaluate":true}, + {"name":"waxing-gibbous.img","url":"waxing-gibbous-icon.js","evaluate":true}, + {"name":"waxing-crescent.img","url":"waxing-crescent-icon.js","evaluate":true} + ] + }, + { + "id": "widhwt", + "name": "Hand Wash Timer", + "version": "0.01", + "description": "Swipe your wrist over the watch face to start your personal Bangle.js hand wash timer for 35 sec. Start washing after the short buzz and stop after the long buzz.", + "icon": "widget.png", + "type": "widget", + "tags": "widget,tool", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"widhwt.wid.js","url":"widget.js"} + ] + }, + { + "id": "toucher", + "name": "Touch Launcher", + "shortName": "Toucher", + "version": "0.07", + "description": "Touch enable left to right launcher.", + "icon": "app.png", + "type": "launch", + "tags": "tool,system,launcher", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"toucher.app.js","url":"app.js"}, + {"name":"toucher.settings.js","url":"settings.js"} + ], + "data": [{"name":"toucher.json"}] + }, + { + "id": "balltastic", + "name": "Balltastic", + "version": "0.02", + "description": "Simple but fun ball eats dots game.", + "icon": "app.png", + "type": "app", + "tags": "game,fun", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"balltastic.app.js","url":"app.js"}, + {"name":"balltastic.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "rpgdice", + "name": "RPG dice", + "version": "0.02", + "description": "Simple RPG dice rolling app.", + "icon": "rpgdice.png", + "type": "app", + "tags": "game,fun", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-rpg-dice-screenshot.png"}], + "storage": [ + {"name":"rpgdice.app.js","url":"app.js"}, + {"name":"rpgdice.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widmp", + "name": "Moon Phase Widget", + "version": "0.02", + "description": "Display the current moon phase in blueish for the northern hemisphere in eight phases", + "icon": "widget.png", + "type": "widget", + "tags": "widget,tools", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widmp.wid.js","url":"widget.js"} + ] + }, + { + "id": "widmpsh", + "name": "Moon Phase Widget Southern Hemisphere", + "version": "0.01", + "description": "Display the current moon phase in blueish for the southern hemisphere in eight phases", + "icon": "widget.png", + "type": "widget", + "tags": "widget,tools", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widmpsh.wid.js","url":"widget.js"} + ] + }, + { + "id": "minionclk", + "name": "Minion clock", + "version": "0.05", + "description": "Minion themed clock.", + "icon": "minionclk.png", + "type": "clock", + "tags": "clock,minion", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-minion-clock-screenshot.png"}], + "storage": [ + {"name":"minionclk.app.js","url":"app.js"}, + {"name":"minionclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "openstmap", + "name": "OpenStreetMap", + "shortName": "OpenStMap", + "version": "0.11", + "description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps", + "icon": "app.png", + "tags": "outdoors,gps,osm", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "custom": "custom.html", + "customConnect": true, + "storage": [ + {"name":"openstmap","url":"openstmap.js"}, + {"name":"openstmap.app.js","url":"app.js"}, + {"name":"openstmap.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "activepedom", + "name": "Active Pedometer", + "shortName": "Active Pedometer", + "version": "0.09", + "description": "Pedometer that filters out arm movement and displays a step goal progress. Steps are saved to a daily file and can be viewed as graph.", + "icon": "app.png", + "tags": "outdoors,widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"activepedom.wid.js","url":"widget.js"}, + {"name":"activepedom.settings.js","url":"settings.js"}, + {"name":"activepedom.img","url":"app-icon.js","evaluate":true}, + {"name":"activepedom.app.js","url":"app.js"} + ] + }, + { + "id": "chronowid", + "name": "Chrono Widget", + "shortName": "Chrono Widget", + "version": "0.04", + "description": "Chronometer (timer) which runs as widget.", + "icon": "app.png", + "tags": "tool,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"chronowid.wid.js","url":"widget.js"}, + {"name":"chronowid.app.js","url":"app.js"}, + {"name":"chronowid.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "tabata", + "name": "Tabata", + "shortName": "Tabata - Control High-Intensity Interval Training", + "version": "0.01", + "description": "Control high-intensity interval training (according to tabata: https://en.wikipedia.org/wiki/Tabata_method).", + "icon": "tabata.png", + "tags": "workout,health", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"tabata.app.js","url":"tabata.js"}, + {"name":"tabata.img","url":"tabata-icon.js","evaluate":true} + ] + }, + { + "id": "custom", + "name": "Custom Boot Code ", + "version": "0.01", + "description": "Add code you want to run at boot time", + "icon": "custom.png", + "type": "bootloader", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "custom": "custom.html", + "storage": [ + {"name":"custom"} + ] + }, + { + "id": "devstopwatch", + "name": "Dev Stopwatch", + "shortName": "Dev Stopwatch", + "version": "0.03", + "description": "Stopwatch with 5 laps supported (cyclically replaced)", + "icon": "app.png", + "tags": "stopwatch,chrono,timer,chronometer", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"devstopwatch.app.js","url":"app.js"}, + {"name":"devstopwatch.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "batchart", + "name": "Battery Chart", + "shortName": "Battery Chart", + "version": "0.10", + "description": "A widget and an app for recording and visualizing battery percentage over time.", + "icon": "app.png", + "tags": "app,widget,battery,time,record,chart,tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"batchart.wid.js","url":"widget.js"}, + {"name":"batchart.app.js","url":"app.js"}, + {"name":"batchart.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "nato", + "name": "NATO Alphabet", + "shortName": "NATOAlphabet", + "version": "0.01", + "description": "Learn the NATO Phonetic alphabet plus some numbers.", + "icon": "nato.png", + "type": "app", + "tags": "app,learn,visual", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-NATO-alphabet-screenshot.png"},{"url":"bangle1-NATO-alphabet-screenshot2.png"}], + "storage": [ + {"name":"nato.app.js","url":"nato.js"}, + {"name":"nato.img","url":"nato-icon.js","evaluate":true} + ] + }, + { + "id": "numerals", + "name": "Numerals Clock", + "shortName": "Numerals Clock", + "version": "0.10", + "description": "A simple big numerals clock", + "icon": "numerals.png", + "type": "clock", + "tags": "numerals,clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-numerals-screenshot.png"}], + "storage": [ + {"name":"numerals.app.js","url":"numerals.app.js"}, + {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, + {"name":"numerals.settings.js","url":"numerals.settings.js"} + ], + "data": [{"name":"numerals.json"}] + }, + { + "id": "bledetect", + "name": "BLE Detector", + "shortName": "BLE Detector", + "version": "0.03", + "description": "Detect BLE devices and show some informations.", + "icon": "bledetect.png", + "tags": "app,bluetooth,tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"bledetect.app.js","url":"bledetect.js"}, + {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} + ] + }, + { + "id": "snake", + "name": "Snake", + "shortName": "Snake", + "version": "0.02", + "description": "The classic snake game. Eat apples and don't bite your tail.", + "icon": "snake.png", + "tags": "game,fun", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"snake.app.js","url":"snake.js"}, + {"name":"snake.img","url":"snake-icon.js","evaluate":true} + ] + }, + { "id": "snek", + "name": "The snek game", + "shortName":"Snek", + "version": "0.02", + "description": "A snek game where you control a snek to eat all the apples!", + "screenshots": [{"url":"screenshot_snek.png"}], + "icon": "snek.png", + "supports": ["BANGLEJS2"], + "tags": "game,fun", + "storage": [ + {"name":"snek.app.js","url":"snek.js"}, + {"name":"snek.img","url":"snek.icon.js","evaluate":true} + ] + }, + { + "id": "calculator", + "name": "Calculator", + "shortName": "Calculator", + "version": "0.04", + "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", + "icon": "calculator.png", + "screenshots": [{"url":"screenshot_calculator.png"}], + "tags": "app,tool", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"calculator.app.js","url":"app.js"}, + {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} + ] + }, + { + "id": "dane", + "name": "Digital Assistant, not EDITH", + "shortName": "DANE", + "version": "0.16", + "description": "A Watchface inspired by Tony Stark's EDITH and based on https://arwes.dev/", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"dane.app.js","url":"app.js"}, + {"name":"dane.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "dane_tcr", + "name": "DANE Touch Launcher", + "shortName": "DANE Toucher", + "version": "0.07", + "description": "Touch enable left to right launcher in the style of the DANE Watchface", + "icon": "app.png", + "type": "launch", + "tags": "tool,system,launcher", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"dane_tcr.app.js","url":"app.js"}, + {"name":"dane_tcr.settings.js","url":"settings.js"} + ], + "data": [{"name":"dane_tcr.json"}] + }, + { + "id": "buffgym", + "name": "BuffGym", + "version": "0.02", + "description": "BuffGym is the famous 5x5 workout program for the BangleJS", + "icon": "buffgym.png", + "type": "app", + "tags": "tool,outdoors,gym,exercise", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "buffgym.html", + "allow_emulator": false, + "storage": [ + {"name":"buffgym.app.js","url":"buffgym.app.js"}, + {"name":"buffgym-set.js","url":"buffgym-set.js"}, + {"name":"buffgym-exercise.js","url":"buffgym-exercise.js"}, + {"name":"buffgym-workout.js","url":"buffgym-workout.js"}, + {"name":"buffgym-workout-a.json","url":"buffgym-workout-a.json"}, + {"name":"buffgym-workout-b.json","url":"buffgym-workout-b.json"}, + {"name":"buffgym-workout-index.json","url":"buffgym-workout-index.json"}, + {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} + ] + }, + { + "id": "banglerun", + "name": "BangleRun", + "shortName": "BangleRun", + "version": "0.10", + "description": "An app for running sessions. Displays info and logs your run for later viewing.", + "icon": "banglerun.png", + "tags": "run,running,fitness,outdoors", + "supports": ["BANGLEJS"], + "interface": "interface.html", + "allow_emulator": false, + "storage": [ + {"name":"banglerun.app.js","url":"app.js"}, + {"name":"banglerun.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "metronome", + "name": "Metronome", + "version": "0.07", + "readme": "README.md", + "description": "Makes the watch blinking and vibrating with a given rate", + "icon": "metronome_icon.png", + "tags": "tool", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-metronome-screenshot.png"}], + "storage": [ + {"name":"metronome.app.js","url":"metronome.js"}, + {"name":"metronome.img","url":"metronome-icon.js","evaluate":true}, + {"name":"metronome.settings.js","url":"settings.js"} + ] + }, + { + "id": "blackjack", + "name": "Black Jack game", + "shortName": "Black Jack game", + "version": "0.02", + "description": "Simple implementation of card game Black Jack", + "icon": "blackjack.png", + "tags": "game", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-black-jack-game-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"blackjack.app.js","url":"blackjack.app.js"}, + {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} + ] + }, + { + "id": "hidcam", + "name": "Camera shutter", + "shortName": "Cam shutter", + "version": "0.03", + "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", + "icon": "app.png", + "tags": "bluetooth,tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"hidcam.app.js","url":"app.js"}, + {"name":"hidcam.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "swlclk", + "name": "SWL Clock / Short Wave Listner Clock", + "shortName": "SWL Clock", + "version": "0.02", + "description": "Display Local, UTC time and some programs on the shorts waves along the day, with the frequencies", + "icon": "swlclk.png", + "type": "clock", + "tags": "tool,clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-SWL-clock-screenshot.png"}], + "storage": [ + {"name":"swlclk.app.js","url":"app.js"}, + {"name":"swlclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "rclock", + "name": "Round clock with seconds, minutes and date", + "shortName": "Round Clock", + "version": "0.06", + "description": "Designed round clock with ticks for minutes and seconds and heart rate indication", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"rclock.app.js","url":"rclock.app.js"}, + {"name":"rclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "fclock", + "name": "fclock", + "shortName": "F Clock", + "version": "0.02", + "description": "Simple design of a digital clock", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"fclock.app.js","url":"fclock.app.js"}, + {"name":"fclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "hamloc", + "name": "QTH Locator / Maidenhead Locator System", + "shortName": "QTH Locator", + "version": "0.01", + "description": "Convert your current GPS location to the Maidenhead locator system used by HAM amateur radio operators", + "icon": "app.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"hamloc.app.js","url":"app.js"}, + {"name":"hamloc.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "osmpoi", + "name": "POI Compass", + "version": "0.03", + "description": "Uploads all the points of interest in an area onto your watch, same as Beer Compass with more p.o.i.", + "icon": "app.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "custom": "custom.html", + "storage": [ + {"name":"osmpoi.app.js"}, + {"name":"osmpoi.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "pong", + "name": "Pong", + "shortName": "Pong", + "version": "0.03", + "description": "A clone of the Atari game Pong", + "icon": "pong.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-pong-screenshot.png"}], + "storage": [ + {"name":"pong.app.js","url":"app.js"}, + {"name":"pong.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "ballmaze", + "name": "Ball Maze", + "version": "0.02", + "description": "Navigate a ball through a maze by tilting your watch.", + "icon": "icon.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"ballmaze.app.js","url":"app.js"}, + {"name":"ballmaze.img","url":"icon.js","evaluate":true} + ], + "data": [{"name":"ballmaze.json"}] + }, + { + "id": "calendar", + "name": "Calendar", + "version": "0.04", + "description": "Simple calendar", + "icon": "calendar.png", + "screenshots": [{"url":"screenshot_calendar.png"}], + "tags": "calendar", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"calendar.app.js","url":"calendar.js"}, + {"name":"calendar.settings.js","url":"settings.js"}, + {"name":"calendar.img","url":"calendar-icon.js","evaluate":true} + ], + "data": [{"name":"calendar.json"}] + }, + { + "id": "hidjoystick", + "name": "Bluetooth Joystick", + "shortName": "Joystick", + "version": "0.01", + "description": "Emulates a 2 axis/5 button Joystick using the accelerometer as stick input and buttons 1-3, touch left as button 4 and touch right as button 5.", + "icon": "app.png", + "tags": "bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"hidjoystick.app.js","url":"app.js"}, + {"name":"hidjoystick.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "largeclock", + "name": "Large Clock", + "version": "0.10", + "description": "A readable and informational digital watch, with date, seconds and moon phase", + "icon": "largeclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-large-clock-screenshot.png"}], + "storage": [ + {"name":"largeclock.app.js","url":"largeclock.js"}, + {"name":"largeclock.img","url":"largeclock-icon.js","evaluate":true}, + {"name":"largeclock.settings.js","url":"settings.js"} + ], + "data": [{"name":"largeclock.json"}] + }, + { + "id": "smtswch", + "name": "Smart Switch", + "shortName": "Smart Switch", + "version": "0.01", + "description": "Using EspruinoHub, control your smart devices on and off via Bluetooth Low Energy!", + "icon": "app.png", + "type": "app", + "tags": "bluetooth,btle,smart,switch", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"smtswch.app.js","url":"app.js"}, + {"name":"smtswch.img","url":"app-icon.js","evaluate":true}, + {"name":"light-on.img","url":"light-on.js","evaluate":true}, + {"name":"light-off.img","url":"light-off.js","evaluate":true}, + {"name":"switch-on.img","url":"switch-on.js","evaluate":true}, + {"name":"switch-off.img","url":"switch-off.js","evaluate":true} + ] + }, + { + "id": "miplant", + "name": "Xiaomi Plant Sensor", + "shortName": "Mi Plant", + "version": "0.02", + "description": "Reads and displays data from Xiaomi bluetooth plant moisture sensors", + "icon": "app.png", + "tags": "xiaomi,mi,plant,ble,bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"miplant.app.js","url":"app.js"}, + {"name":"miplant.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "simpletimer", + "name": "Timer", + "version": "0.07", + "description": "Simple timer, useful when playing board games or cooking", + "icon": "app.png", + "tags": "timer", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-timer-screenshot.png"}], + "storage": [ + {"name":"simpletimer.app.js","url":"app.js"}, + {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, + {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, + {"name":"simpletimer.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"simpletimer.json"}] + }, + { + "id": "beebclock", + "name": "Beeb Clock", + "version": "0.05", + "description": "Clock face that may be coincidentally familiar to BBC viewers", + "icon": "beebclock.png", + "type": "clock", + "tags": "clock", + "screenshots": [{"url":"bangle1-beeb-clock-screenshot.png"}], + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"beebclock.app.js","url":"beebclock.js"}, + {"name":"beebclock.img","url":"beebclock-icon.js","evaluate":true} + ] + }, + { + "id": "findphone", + "name": "Find Phone", + "shortName": "Find Phone", + "version": "0.03", + "description": "Find your phone via Gadgetbridge. Click any button to let your phone ring. 📳 Note: The functionality is available even without this app, just go to Settings, App Settings, Gadgetbridge, Find Phone.", + "icon": "app.png", + "tags": "tool,android", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"findphone.app.js","url":"app.js"}, + {"name":"findphone.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "getup", + "name": "Get Up", + "shortName": "Get Up", + "version": "0.01", + "description": "Reminds you to getup every x minutes. Sitting to long is dangerous!", + "icon": "app.png", + "tags": "tools,health", + "supports": ["BANGLEJS"], + "readme": "README.md", + "screenshots": [{"url":"bangle1-get-up-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"getup.app.js","url":"app.js"}, + {"name":"getup.settings.js","url":"settings.js"}, + {"name":"getup.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "gallifr", + "name": "Time Traveller's Chronometer", + "shortName": "Time Travel Clock", + "version": "0.02", + "description": "A clock for time travellers. The light pie segment shows the minutes, the black circle, the hour. The dial itself reads 'time' just in case you forget.", + "icon": "gallifr.png", + "screenshots": [{"url":"screenshot_time.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"gallifr.app.js","url":"app.js"}, + {"name":"gallifr.img","url":"app-icon.js","evaluate":true}, + {"name":"gallifr.settings.js","url":"settings.js"} + ], + "data": [{"name":"gallifr.json"}] + }, + { + "id": "rndmclk", + "name": "Random Clock Loader", + "version": "0.03", + "description": "Load a different clock whenever the LCD is switched on.", + "icon": "rndmclk.png", + "type": "widget", + "tags": "widget,clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"rndmclk.wid.js","url":"widget.js"} + ] + }, + { + "id": "dotmatrixclock", + "name": "Dotmatrix Clock", + "version": "0.01", + "description": "A clear white-on-blue dotmatrix simulated clock", + "icon": "dotmatrixclock.png", + "type": "clock", + "tags": "clock,dotmatrix,retro", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"dotmatrixclock.app.js","url":"app.js"}, + {"name":"dotmatrixclock.img","url":"dotmatrixclock-icon.js","evaluate":true} + ] + }, + { + "id": "jbm8b", + "name": "Magic 8 Ball", + "shortName": "Magic 8 Ball", + "version": "0.03", + "description": "A simple fortune telling app", + "icon": "app.png", + "tags": "game", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"jbm8b.app.js","url":"app.js"}, + {"name":"jbm8b.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "jbm8b_IT", + "name": "Magic 8 Ball Italiano", + "shortName": "Magic 8 Ball IT", + "version": "0.01", + "description": "La palla predice il futuro", + "icon": "app.png", + "screenshots": [{"url":"bangle1-magic-8-ball-italiano-screenshot.png"}], + "tags": "game", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"jbm8b_IT.app.js","url":"app.js"}, + {"name":"jbm8b_IT.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "BLEcontroller", + "name": "BLE Customisable Controller with Joystick", + "shortName": "BLE Controller", + "version": "0.01", + "description": "A configurable controller for BLE devices and robots, with a basic four direction joystick. Designed to be easy to customise so you can add your own menus.", + "icon": "BLEcontroller.png", + "tags": "tool,bluetooth", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": false, + "storage": [ + {"name":"BLEcontroller.app.js","url":"app.js"}, + {"name":"BLEcontroller.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widviz", + "name": "Widget Visibility Widget", + "shortName": "Viz Widget", + "version": "0.03", + "description": "Swipe left to hide top bar widgets, swipe right to redisplay.", + "icon": "eye.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widviz.wid.js","url":"widget.js"} + ] + }, + { + "id": "binclock", + "name": "Binary Clock", + "shortName": "Binary Clock", + "version": "0.03", + "description": "A binary clock with hours and minutes. BTN1 toggles a digital clock.", + "icon": "app.png", + "type": "clock", + "tags": "clock,binary", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"binclock.app.js","url":"app.js"}, + {"name":"binclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "pizzatimer", + "name": "Pizza Timer", + "shortName": "Pizza Timer", + "version": "0.01", + "description": "A timer app for when you cook Pizza. Some say it can also time other things", + "icon": "pizza.png", + "tags": "timer,tool,pizza", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"pizzatimer.app.js","url":"app.js"}, + {"name":"pizzatimer.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "animclk", + "name": "Animated Clock", + "shortName": "Anim Clock", + "version": "0.03", + "description": "An animated clock face using Mark Ferrari's amazing 8 bit game art and palette cycling: http://www.markferrari.com/art/8bit-game-art", + "icon": "app.png", + "type": "clock", + "tags": "clock,animated", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"animclk.app.js","url":"app.js"}, + {"name":"animclk.pixels1","url":"animclk.pixels1"}, + {"name":"animclk.pixels2","url":"animclk.pixels2"}, + {"name":"animclk.pal","url":"animclk.pal"}, + {"name":"animclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "analogimgclk", + "name": "Analog Clock (Image background)", + "shortName": "Analog Clock", + "version": "0.03", + "description": "An analog clock with an image background", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"analogimgclk.app.js","url":"app.js"}, + {"name":"analogimgclk.bg.img","url":"bg.img"}, + {"name":"analogimgclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "verticalface", + "name": "Vertical watch face", + "shortName": "Vertical Face", + "version": "0.09", + "description": "A simple vertical watch face with the date. Heart rate monitor is toggled with BTN1", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "allow_emulator": true, + "screenshots": [{"url":"bangle1-vertical-watch-face-screenshot.png"}], + "storage": [ + {"name":"verticalface.app.js","url":"app.js"}, + {"name":"verticalface.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "sleepphasealarm", + "name": "SleepPhaseAlarm", + "shortName": "SleepPhaseAlarm", + "version": "0.02", + "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", + "icon": "app.png", + "tags": "alarm", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"sleepphasealarm.app.js","url":"app.js"}, + {"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "life", + "name": "Game of Life", + "version": "0.04", + "description": "Conway's Game of Life - 16x16 board", + "icon": "life.png", + "tags": "game", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-game-of-life-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"life.app.js","url":"life.min.js"}, + {"name":"life.img","url":"life-icon.js","evaluate":true} + ] + }, + { + "id": "magnav", + "name": "Navigation Compass", + "version": "0.05", + "description": "Compass with linear display as for GPSNAV. Has Tilt compensation and remembers calibration.", + "screenshots": [{"url":"screenshot-b2.png"},{"url":"screenshot-light-b2.png"}], + "icon": "magnav.png", + "tags": "tool,outdoors", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"magnav.app.js","url":"magnav_b1.js","supports":["BANGLEJS"]}, + {"name":"magnav.app.js","url":"magnav_b2.js","supports":["BANGLEJS2"]}, + {"name":"magnav.img","url":"magnav-icon.js","evaluate":true} + ], + "data": [{"name":"magnav.json"}] + }, + { + "id": "gpspoilog", + "name": "GPS POI Logger", + "shortName": "GPS POI Log", + "version": "0.01", + "description": "A simple app to log points of interest with their GPS coordinates and read them back onto your PC. Based on the https://www.espruino.com/Bangle.js+Storage tutorial", + "icon": "app.png", + "tags": "outdoors", + "supports": ["BANGLEJS"], + "interface": "interface.html", + "storage": [ + {"name":"gpspoilog.app.js","url":"app.js"}, + {"name":"gpspoilog.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "miclock2", + "name": "Mixed Clock 2", + "version": "0.01", + "description": "White color variant of the Mixed Clock with thicker clock hands for better readability in the bright sunlight, extra space under the clock for widgets and seconds in the digital clock.", + "icon": "clock-mixed.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-mixed-clock-2-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"miclock2.app.js","url":"clock-mixed.js"}, + {"name":"miclock2.img","url":"clock-mixed-icon.js","evaluate":true} + ] + }, + { + "id": "1button", + "name": "One-Button-Tracker", + "version": "0.01", + "description": "A widget that turns BTN1 into a tracker, records time of button press/release.", + "icon": "widget.png", + "type": "widget", + "tags": "tool,quantifiedself,widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"1button.wid.js","url":"widget.js"} + ], + "data": [{"name":"one_button_presses.csv","storageFile":true}] + }, + { + "id": "gpsautotime", + "name": "GPS auto time", + "shortName": "GPS auto time", + "version": "0.01", + "description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.", + "icon": "widget.png", + "type": "widget", + "tags": "widget,gps", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"gpsautotime.wid.js","url":"widget.js"} + ] + }, + { + "id": "espruinoctrl", + "name": "Espruino Control", + "shortName": "Espruino Ctrl", + "version": "0.01", + "description": "Send commands to other Espruino devices via the Bluetooth UART interface. Customisable commands!", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "custom": "custom.html", + "storage": [ + {"name":"espruinoctrl.app.js"}, + {"name":"espruinoctrl.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "multiclock", + "name": "Multi Clock", + "version": "0.09", + "description": "Clock with multiple faces. Switch between faces with BTN1 & BTN3 (Bangle 2 touch top-right, bottom right). For best display set theme Background 2 to cyan or some other bright colour in settings.", + "screenshots": [{"url":"screen-ana.png"},{"url":"screen-big.png"},{"url":"screen-td.png"},{"url":"screen-nifty.png"},{"url":"screen-word.png"},{"url":"screen-sec.png"}], + "icon": "multiclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"multiclock.app.js","url":"multiclock.app.js"}, + {"name":"big.face.js","url":"big.face.js"}, + {"name":"ana.face.js","url":"ana.face.js"}, + {"name":"digi.face.js","url":"digi.face.js"}, + {"name":"txt.face.js","url":"txt.face.js"}, + {"name":"dk.face.js","url":"dk.face.js"}, + {"name":"nifty.face.js","url":"nifty.face.js"}, + {"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true} + ] + }, + { + "id": "widancs", + "name": "Apple Notification Widget", + "shortName": "ANCS Widget", + "version": "0.07", + "description": "Displays call, message etc notifications from a paired iPhone. Read README before installation as it only works with compatible apps", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"widancs.wid.js","url":"ancs.min.js"}, + {"name":"widancs.settings.js","url":"settings.js"} + ] + }, + { + "id": "accelrec", + "name": "Acceleration Recorder", + "shortName": "Accel Rec", + "version": "0.02", + "description": "This app puts the Bangle's accelerometer into 100Hz mode and reads 2 seconds worth of data after movement starts. The data can then be exported back to the PC.", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"accelrec.app.js","url":"app.js"}, + {"name":"accelrec.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"wildcard":"accelrec.?.csv"}] + }, + { + "id": "accellog", + "name": "Acceleration Logger", + "shortName": "Accel Log", + "version": "0.03", + "description": "Logs XYZ acceleration data to a CSV file that can be downloaded to your PC", + "icon": "app.png", + "tags": "outdoor", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"accellog.app.js","url":"app.js"}, + {"name":"accellog.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"wildcard":"accellog.?.csv"}] + }, + { + "id": "cprassist", + "name": "CPR Assist", + "version": "0.01", + "description": "Provides assistance while performing a CPR", + "icon": "cprassist-icon.png", + "tags": "tool,firstaid", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-CPR-assist-screenshot.png"}], + "storage": [ + {"name":"cprassist.app.js","url":"cprassist.js"}, + {"name":"cprassist.img","url":"cprassist-icon.js","evaluate":true}, + {"name":"cprassist.settings.js","url":"settings.js"} + ] + }, + { + "id": "osgridref", + "name": "Ordnance Survey Grid Reference", + "shortName": "OS Grid ref", + "version": "0.01", + "description": "Displays the UK Ordnance Survey grid reference of your current GPS location. Useful when in the United Kingdom with an Ordnance Survey map", + "icon": "app.png", + "tags": "outdoors,gps", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"osgridref.app.js","url":"app.js"}, + {"name":"osgridref.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "openseizure", + "name": "OpenSeizureDetector Widget", + "shortName": "Short Name", + "version": "0.01", + "description": "[BETA!] A widget to work alongside [OpenSeizureDetector](https://www.openseizuredetector.org.uk/)", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"openseizure.wid.js","url":"widget.js"} + ] + }, + { + "id": "counter", + "name": "Counter", + "version": "0.03", + "description": "Simple counter", + "icon": "counter_icon.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-counter-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"counter.app.js","url":"counter.js"}, + {"name":"counter.img","url":"counter-icon.js","evaluate":true} + ] + }, + { + "id": "bootgattbat", + "name": "BLE GATT Battery Service", + "shortName": "BLE Battery Service", + "version": "0.01", + "description": "Adds the GATT Battery Service to advertise the percentage of battery currently remaining over Bluetooth.\n", + "icon": "bluetooth.png", + "type": "bootloader", + "tags": "battery,ble,bluetooth,gatt", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"gattbat.boot.js","url":"boot.js"} + ] + }, + { + "id": "viewstl", + "name": "STL file viewer", + "shortName": "ViewSTL", + "version": "0.02", + "description": "This app allows you to view STL 3D models on your watch", + "icon": "icons8-octahedron-48.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"viewstl.app.js","url":"viewstl.min.js"}, + {"name":"viewstl.img","url":"viewstl-icon.js","evaluate":true}, + {"name":"tetra.stl","url":"tetra.stl"}, + {"name":"cube.stl","url":"cube.stl"}, + {"name":"icosa.stl","url":"icosa.stl"} + ] + }, + { + "id": "cscsensor", + "name": "Cycling speed sensor", + "shortName": "CSCSensor", + "version": "0.06", + "description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch", + "icon": "icons8-cycling-48.png", + "tags": "outdoors,exercise,ble,bluetooth", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"cscsensor.app.js","url":"cscsensor.app.js"}, + {"name":"cscsensor.settings.js","url":"settings.js"}, + {"name":"cscsensor.img","url":"cscsensor-icon.js","evaluate":true} + ] + }, + { + "id": "fileman", + "name": "File manager", + "shortName": "FileManager", + "version": "0.03", + "description": "Simple file manager, allows user to examine watch storage and display, load or delete individual files", + "icon": "icons8-filing-cabinet-48.png", + "tags": "tools", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"fileman.app.js","url":"fileman.app.js"}, + {"name":"fileman.img","url":"fileman-icon.js","evaluate":true} + ] + }, + { + "id": "worldclock", + "name": "World Clock - 4 time zones", + "shortName": "World Clock", + "version": "0.05", + "description": "Current time zone plus up to four others", + "icon": "app.png", + "screenshots": [{"url":"screenshot_world.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "custom": "custom.html", + "storage": [ + {"name":"worldclock.app.js","url":"app.js"}, + {"name":"worldclock.img","url":"worldclock-icon.js","evaluate":true} + ], + "data": [{"name":"worldclock.settings.json"}] + }, + { + "id": "digiclock", + "name": "Digital Clock Face", + "shortName": "Digi Clock", + "version": "0.02", + "description": "A simple digital clock with the time, day, month, and year", + "icon": "digiclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"digiclock.app.js","url":"digiclock.js"}, + {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} + ] + }, + { + "id": "dsdrelay", + "name": "DSD BLE Relay controller", + "shortName": "DSDRelay", + "version": "0.01", + "description": "Control BLE relay board from the watch", + "icon": "icons8-relay-48.png", + "tags": "ble,bluetooth", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"dsdrelay.app.js","url":"dsdrelay.app.js"}, + {"name":"dsdrelay.img","url":"dsdrelay-icon.js","evaluate":true} + ] + }, + { + "id": "mandel", + "name": "Mandelbrot", + "shortName": "Mandel", + "version": "0.01", + "description": "Draw a zoomable Mandelbrot set", + "icon": "mandel.png", + "tags": "game", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"mandel.app.js","url":"mandel.min.js"}, + {"name":"mandel.img","url":"mandel-icon.js","evaluate":true} + ] + }, + { + "id": "petrock", + "name": "Pet rock", + "version": "0.02", + "description": "A virtual pet rock with wobbly eyes", + "icon": "petrock.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"petrock.app.js","url":"app.js"}, + {"name":"petrock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "smartibot", + "name": "Smartibot controller", + "shortName": "Smartibot", + "version": "0.01", + "description": "Control a [Smartibot Robot](https://thecraftyrobot.net/) straight from your Bangle.js", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"smartibot.app.js","url":"app.js"}, + {"name":"smartibot.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widncr", + "name": "NCR Logo Widget", + "version": "0.01", + "description": "Show the NodeConf Remote logo in the top left", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"widncr.wid.js","url":"widget.js"} + ] + }, + { + "id": "ncrclk", + "name": "NCR Clock", + "shortName": "NCR Clock", + "version": "0.02", + "description": "NodeConf Remote clock", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"ncrclk.app.js","url":"app.js"}, + {"name":"ncrclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "isoclock", + "name": "ISO Compliant Clock Face", + "shortName": "ISO Clock", + "version": "0.02", + "description": "Tweaked fork of digiclock for ISO date and time", + "icon": "isoclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"isoclock.app.js","url":"isoclock.js"}, + {"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true} + ] + }, + { + "id": "gpstimeserver", + "name": "GPS Time Server", + "version": "0.01", + "description": "A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server.", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"gpstimeserver.wid.js","url":"widget.js"} + ] + }, + { + "id": "tilthydro", + "name": "Tilt Hydrometer Display", + "shortName": "Tilt Hydro", + "version": "0.01", + "description": "A display for the [Tilt Hydrometer](https://tilthydrometer.com/) - [more info here](http://www.espruino.com/Tilt+Hydrometer+Display)", + "icon": "app.png", + "tags": "tools,bluetooth", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"tilthydro.app.js","url":"app.js"}, + {"name":"tilthydro.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "supmariodark", + "name": "Super mario clock night mode", + "shortName": "supmariodark", + "version": "0.01", + "description": "Super mario clock in night mode", + "icon": "supmariodark.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"supmariodark.app.js","url":"supmariodark.js"}, + {"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true}, + {"name":"supmario30x24.bin","url":"supmario30x24.bin.js"}, + {"name":"supmario30x24.wdt","url":"supmario30x24.wdt.js"}, + {"name":"banner-up.img","url":"banner-up.js","evaluate":true}, + {"name":"banner-down.img","url":"banner-down.js","evaluate":true}, + {"name":"brick2.img","url":"brick2.js","evaluate":true}, + {"name":"enemy.img","url":"enemy.js","evaluate":true}, + {"name":"flower.img","url":"flower.js","evaluate":true}, + {"name":"flower_b.img","url":"flower_b.js","evaluate":true}, + {"name":"mario_wh.img","url":"mario_wh.js","evaluate":true}, + {"name":"pipe.img","url":"pipe.js","evaluate":true} + ] + }, + { + "id": "gmeter", + "name": "G-Meter", + "shortName": "G-Meter", + "version": "0.01", + "description": "Simple G-Meter", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"gmeter.app.js","url":"app.js"}, + {"name":"gmeter.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "dtlaunch", + "name": "Desktop Launcher", + "version": "0.07", + "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", + "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], + "icon": "icon.png", + "type": "launch", + "tags": "tool,system,launcher", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"dtlaunch.app.js","url":"app-b1.js", "supports": ["BANGLEJS"]}, + {"name":"dtlaunch.app.js","url":"app-b2.js", "supports": ["BANGLEJS2"]}, + {"name":"dtlaunch.settings.js","url":"settings-b1.js", "supports": ["BANGLEJS"]}, + {"name":"dtlaunch.settings.js","url":"settings-b2.js", "supports": ["BANGLEJS2"]}, + {"name":"dtlaunch.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"dtlaunch.json"}] + }, + { + "id": "HRV", + "name": "Heart Rate Variability monitor", + "shortName": "HRV monitor", + "version": "0.04", + "description": "Heart Rate Variability monitor, see Readme for more info", + "icon": "hrv.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"HRV.app.js","url":"app.js"}, + {"name":"HRV.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "hardalarm", + "name": "Hard Alarm", + "shortName": "HardAlarm", + "version": "0.02", + "description": "Make sure you wake up! Count to the right number to turn off the alarm", + "icon": "app.png", + "tags": "tool,alarm,widget", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"hardalarm.app.js","url":"app.js"}, + {"name":"hardalarm.boot.js","url":"boot.js"}, + {"name":"hardalarm.js","url":"hardalarm.js"}, + {"name":"hardalarm.img","url":"app-icon.js","evaluate":true}, + {"name":"hardalarm.wid.js","url":"widget.js"} + ], + "data": [{"name":"hardalarm.json"}] + }, + { + "id": "edisonsball", + "name": "Edison's Ball", + "shortName": "Edison's Ball", + "version": "0.01", + "description": "Hypnagogia/Micro-Sleep alarm for experimental use in exploring sleep transition and combating drowsiness", + "icon": "app-icon.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"edisonsball.app.js","url":"app.js"}, + {"name":"edisonsball.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "hrrawexp", + "name": "HRM Data Exporter", + "shortName": "HRM Data Exporter", + "version": "0.01", + "description": "export raw hrm signal data to a csv file", + "icon": "app-icon.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"hrrawexp.app.js","url":"app.js"}, + {"name":"hrrawexp.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "breath", + "name": "Breathing App", + "shortName": "Breathing App", + "version": "0.01", + "description": "app to aid relaxation and train breath syncronicity using haptics and visualisation, also displays HR", + "icon": "app-icon.png", + "tags": "tools,health", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"breath.app.js","url":"app.js"}, + {"name":"breath.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"breath.settings.json","url":"settings.json"}] + }, + { + "id": "lazyclock", + "name": "Lazy Clock", + "version": "0.03", + "description": "Tells the time, roughly", + "icon": "lazyclock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "screenshots": [{"url":"bangle1-lazy-clock-screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"lazyclock.app.js","url":"lazyclock-app.js"}, + {"name":"lazyclock.img","url":"lazyclock-icon.js","evaluate":true} + ] + }, + { + "id": "astral", + "name": "Astral Clock", + "version": "0.03", + "description": "Clock that calculates and displays Alt Az positions of all planets, Sun as well as several other astronomy targets (customizable) and current Moon phase. Coordinates are calculated by GPS & time and onscreen compass assists orienting. See Readme before using.", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"astral.app.js","url":"app.js"}, + {"name":"astral.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "alpinenav", + "name": "Alpine Nav", + "version": "0.01", + "description": "App that performs GPS monitoring to track and display position relative to a given origin in realtime", + "icon": "app-icon.png", + "tags": "outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"alpinenav.app.js","url":"app.js"}, + {"name":"alpinenav.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "lifeclk", + "name": "Game of Life Clock", + "shortName": "Conway's Clock", + "version": "0.06", + "description": "Modification and clockification of Conway's Game of Life", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"lifeclk.app.js","url":"app.min.js"}, + {"name":"lifeclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "speedalt", + "name": "GPS Adventure Sports", + "shortName": "GPS Adv Sport", + "version": "1.02", + "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", + "tags": "tool,outdoors", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"speedalt.app.js","url":"app.js"}, + {"name":"speedalt.img","url":"app-icon.js","evaluate":true}, + {"name":"speedalt.settings.js","url":"settings.js"} + ], + "data": [{"name":"speedalt.json"}] + }, + { + "id": "speedalt2", + "name": "GPS Adventure Sports II", + "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", + "tags": "tool,outdoors", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"speedalt2.app.js","url":"app.js"}, + {"name":"speedalt2.img","url":"app-icon.js","evaluate":true}, + {"name":"speedalt2.settings.js","url":"settings.js"} + ], + "data": [{"name":"speedalt2.json"}] + }, + { + "id": "slomoclock", + "name": "SloMo Clock", + "shortName": "SloMo Clock", + "version": "0.10", + "description": "Simple 24h clock face with large digits, hour above minute. Uses Layout library.", + "icon": "watch.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-slow-mo-clock-screenshot.png"}], + "storage": [ + {"name":"slomoclock.app.js","url":"app.js"}, + {"name":"slomoclock.img","url":"app-icon.js","evaluate":true}, + {"name":"slomoclock.settings.js","url":"settings.js"} + ], + "data": [{"name":"slomoclock.json"}] + }, + { + "id": "de-stress", + "name": "De-Stress", + "shortName": "De-Stress", + "version": "0.02", + "description": "Simple haptic heartbeat", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"de-stress.app.js","url":"app.js"}, + {"name":"de-stress.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "mclockplus", + "name": "Morph Clock+", + "shortName": "Morph Clock+", + "version": "0.02", + "description": "Morphing Clock with more readable seconds and date and additional stopwatch", + "icon": "mclockplus.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"mclockplus.app.js","url":"mclockplus.app.js"}, + {"name":"mclockplus.img","url":"mclockplus-icon.js","evaluate":true} + ] + }, + { + "id": "intervals", + "name": "Intervals App", + "shortName": "Intervals", + "version": "0.01", + "description": "Intervals for training. It is possible to configure work time and rest time and number of sets.", + "icon": "intervals.png", + "tags": "", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"intervals.app.js","url":"intervals.app.js"}, + {"name":"intervals.img","url":"intervals-icon.js","evaluate":true} + ] + }, + { + "id": "planetarium", + "name": "Planetarium", + "shortName": "Planetarium", + "version": "0.03", + "description": "Planetarium showing up to 500 stars using the watch location and time", + "icon": "planetarium.png", + "tags": "", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"planetarium.app.js","url":"planetarium.app.js"}, + {"name":"planetarium.data.csv","url":"planetarium.data.csv"}, + {"name":"planetarium.const.csv","url":"planetarium.const.csv"}, + {"name":"planetarium.extra.csv","url":"planetarium.extra.csv"}, + {"name":"planetarium.settings.js","url":"settings.js"}, + {"name":"planetarium.img","url":"planetarium-icon.js","evaluate":true} + ], + "data": [{"name":"planetarium.json"}] + }, + { + "id": "tapelauncher", + "name": "Tape Launcher", + "version": "0.02", + "description": "An App launcher, icons displayed in a horizontal tape, swipe or use buttons", + "icon": "icon.png", + "type": "launch", + "tags": "tool,system,launcher", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"tapelauncher.app.js","url":"app.js"}, + {"name":"tapelauncher.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "oblique", + "name": "Oblique Strategies", + "version": "0.01", + "description": "Oblique Strategies for creativity. Copied from Brian Eno.", + "icon": "eno.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"oblique.app.js","url":"app.js"}, + {"name":"oblique.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "testuserinput", + "name": "Test User Input", + "shortName": "Test User Input", + "version": "0.06", + "description": "App to test the bangle.js input interface. It displays the user action in text, circle buttons or on/off switch UI elements.", + "icon": "app.png", + "tags": "input,interface,buttons,touch,UI", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"testuserinput.app.js","url":"app.js"}, + {"name":"testuserinput.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "gpssetup", + "name": "GPS Setup", + "shortName": "GPS Setup", + "version": "0.02", + "description": "Configure the GPS power options and store them in the GPS nvram", + "icon": "gpssetup.png", + "tags": "gps,tools,outdoors", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"gpssetup","url":"gpssetup.js"}, + {"name":"gpssetup.settings.js","url":"settings.js"}, + {"name":"gpssetup.app.js","url":"app.js"}, + {"name":"gpssetup.img","url":"icon.js","evaluate":true} + ], + "data": [{"name":"gpssetup.settings.json","url":"settings.json"}] + }, + { + "id": "walkersclock", + "name": "Walkers Clock", + "shortName": "Walkers Clock", + "version": "0.04", + "description": "A large font watch, displays steps, can switch GPS on/off, displays grid reference", + "icon": "walkersclock48.png", + "type": "clock", + "tags": "clock,gps,tools,outdoors", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"walkersclock.app.js","url":"app.js"}, + {"name":"walkersclock.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "widgps", + "name": "GPS Widget", + "version": "0.03", + "description": "Tiny widget to show the power on/off status of the GPS", + "icon": "widget.png", + "type": "widget", + "tags": "widget,gps", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"widgps.wid.js","url":"widget.js"} + ] + }, + { + "id": "widhrt", + "name": "HRM Widget", + "version": "0.03", + "description": "Tiny widget to show the power on/off status of the Heart Rate Monitor", + "icon": "widget.png", + "type": "widget", + "tags": "widget,hrm", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"widhrt.wid.js","url":"widget.js"} + ] + }, + { + "id": "countdowntimer", + "name": "Countdown Timer", + "version": "0.01", + "description": "A simple countdown timer with a focus on usability", + "icon": "countdowntimer.png", + "tags": "timer,tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"countdowntimer.app.js","url":"countdowntimer.js"}, + {"name":"countdowntimer.img","url":"countdowntimer-icon.js","evaluate":true} + ] + }, + { + "id": "helloworld", + "name": "hello, world!", + "shortName": "hello world", + "version": "0.02", + "description": "A cross cultural hello world!/hola mundo! app with colors and languages", + "icon": "app.png", + "tags": "input,interface,buttons,touch", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"helloworld.app.js","url":"app.js"}, + {"name":"helloworld.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widcom", + "name": "Compass Widget", + "version": "0.02", + "description": "Tiny widget to show the power on/off status of the Compass", + "icon": "widget.png", + "type": "widget", + "tags": "widget,compass", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"widcom.wid.js","url":"widget.js"} + ] + }, + { + "id": "arrow", + "name": "Arrow Compass", + "version": "0.05", + "description": "Moving arrow compass that points North, shows heading, with tilt correction. Based on jeffmer's Navigation Compass", + "icon": "arrow.png", + "type": "app", + "tags": "tool,outdoors", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"arrow.app.js","url":"app.js"}, + {"name":"arrow.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "waypointer", + "name": "Way Pointer", + "version": "0.01", + "description": "Navigate to a waypoint using the GPS for bearing and compass to point way, uses the same waypoint interface as GPS Navigation", + "icon": "waypointer.png", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "waypoints.html", + "storage": [ + {"name":"waypointer.app.js","url":"app.js"}, + {"name":"waypointer.img","url":"icon.js","evaluate":true} + ], + "data": [{"name":"waypoints.json","url":"waypoints.json"}] + }, + { + "id": "color_catalog", + "name": "Colors Catalog", + "shortName": "Colors Catalog", + "version": "0.01", + "description": "Displays RGB565 and RGB888 colors, its name and code in screen.", + "icon": "app.png", + "tags": "Color,input,buttons,touch,UI", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"color_catalog.app.js","url":"app.js"}, + {"name":"color_catalog.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "UI4swatch", + "name": "UI 4 swatch", + "shortName": "UI 4 swatch", + "version": "0.01", + "description": "A UI/UX for espruino smartwatches, displays dinamically calc. x,y coordinates.", + "icon": "app.png", + "tags": "Color,input,buttons,touch,UI", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"UI4swatch.app.js","url":"app.js"}, + {"name":"UI4swatch.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "simplest", + "name": "Simplest Clock", + "version": "0.03", + "description": "The simplest working clock, acts as a tutorial piece", + "icon": "simplest.png", + "screenshots": [{"url":"screenshot_simplest.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"simplest.app.js","url":"app.js"}, + {"name":"simplest.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "stepo", + "name": "Stepometer Clock", + "version": "0.03", + "description": "A large font watch, displays step count in a doughnut guage and warns of low battery, requires one of the steps widgets to be installed", + "icon": "stepo.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"stepo.app.js","url":"app.js"}, + {"name":"stepo.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "gbmusic", + "name": "Gadgetbridge Music Controls", + "shortName": "Music Controls", + "version": "0.08", + "description": "Control the music on your Gadgetbridge-connected phone", + "icon": "icon.png", + "screenshots": [{"url":"screenshot_v1.png"},{"url":"screenshot_v2.png"}], + "type": "app", + "tags": "tools,bluetooth,gadgetbridge,music", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"gbmusic.app.js","url":"app.js"}, + {"name":"gbmusic.settings.js","url":"settings.js"}, + {"name":"gbmusic.wid.js","url":"widget.js"}, + {"name":"gbmusic.img","url":"icon.js","evaluate":true} + ], + "data": [{"name":"gbmusic.json"},{"name":"gbmusic.load.json"}] + }, + { + "id": "battleship", + "name": "Battleship", + "version": "0.01", + "description": "The classic game of battleship", + "icon": "battleship-icon.png", + "tags": "game", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-battle-ship-screenshot.png"}], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"battleship.app.js","url":"battleship.js"}, + {"name":"battleship.img","url":"battleship-icon.js","evaluate":true} + ] + }, + { + "id": "kitchen", + "name": "Kitchen Combo", + "version": "0.13", + "description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'", + "icon": "kitchen.png", + "type": "clock", + "tags": "tool,outdoors,gps", + "supports": ["BANGLEJS"], + "readme": "README.md", + "interface": "waypoints.html", + "storage": [ + {"name":"kitchen.app.js","url":"kitchen.app.js"}, + {"name":"stepo2.kit.js","url":"stepo2.kit.js"}, + {"name":"swatch.kit.js","url":"swatch.kit.js"}, + {"name":"gps.kit.js","url":"gps.kit.js"}, + {"name":"compass.kit.js","url":"compass.kit.js"}, + {"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true} + ], + "data": [{"name":"waypoints.json","url":"waypoints.json"}] + }, + { + "id": "banglebridge", + "name": "BangleBridge", + "shortName": "BangleBridge", + "version": "0.01", + "description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"banglebridge.wid.js","url":"widget.js"}, + {"name":"banglebridge.watch.img","url":"watch.img"}, + {"name":"banglebridge.heart.img","url":"heart.img"} + ] + }, + { + "id": "qmsched", + "name": "Quiet Mode Schedule and Widget", + "shortName": "Quiet Mode", + "version": "0.06", + "description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", + "icon": "app.png", + "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, + {"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}], + "tags": "tool,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"qmsched","url":"lib.js"}, + {"name":"qmsched.app.js","url":"app.js"}, + {"name":"qmsched.boot.js","url":"boot.js"}, + {"name":"qmsched.img","url":"icon.js","evaluate":true}, + {"name":"qmsched.wid.js","url":"widget.js"} + ], + "data": [{"name":"qmsched.json"}] + }, + { + "id": "hourstrike", + "name": "Hour Strike", + "shortName": "Hour Strike", + "version": "0.08", + "description": "Strike the clock on the hour. A great tool to remind you an hour has passed!", + "icon": "app-icon.png", + "tags": "tool,alarm", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"hourstrike.app.js","url":"app.js"}, + {"name":"hourstrike.boot.js","url":"boot.js"}, + {"name":"hourstrike.img","url":"app-icon.js","evaluate":true}, + {"name":"hourstrike.json","url":"hourstrike.json"} + ] + }, + { + "id": "whereworld", + "name": "Where in the World?", + "shortName": "Where World", + "version": "0.01", + "description": "Shows your current location on the world map", + "icon": "app.png", + "tags": "gps", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"whereworld.app.js","url":"app.js"}, + {"name":"whereworld.img","url":"app-icon.js","evaluate":true}, + {"name":"whereworld.worldmap","url":"worldmap"} + ] + }, + { + "id": "omnitrix", + "name": "Omnitrix", + "version": "0.01", + "description": "An Omnitrix Showpiece", + "icon": "omnitrix.png", + "screenshots": [{"url":"screenshot.png"}], + "tags": "game", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"omnitrix.app.js","url":"omnitrix.app.js"}, + {"name":"omnitrix.img","url":"omnitrix.icon.js","evaluate":true} + ] + }, + { + "id": "batclock", + "name": "Bat Clock", + "shortName": "Bat Clock", + "version": "0.02", + "description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.", + "icon": "bat-clock.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"batclock.app.js","url":"bat-clock.app.js"}, + {"name":"batclock.img","url":"bat-clock.icon.js","evaluate":true} + ] + }, + { + "id": "doztime", + "name": "Dozenal Time", + "shortName": "Dozenal Time", + "version": "0.04", + "description": "A dozenal Holocene calendar and dozenal diurnal clock", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"doztime.app.js","url":"app.js"}, + {"name":"doztime.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "gbtwist", + "name": "Gadgetbridge Twist Control", + "shortName": "Twist Control", + "version": "0.01", + "description": "Shake your wrist to control your music app via Gadgetbridge", + "icon": "app.png", + "type": "app", + "tags": "tools,bluetooth,gadgetbridge,music", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": false, + "storage": [ + {"name":"gbtwist.app.js","url":"app.js"}, + {"name":"gbtwist.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "thermom", + "name": "Thermometer", + "version": "0.05", + "description": "Displays the current temperature in degree Celsius/Fahrenheit (depending on locale), updates every 10 seconds with average of last 5 readings.", + "icon": "app.png", + "tags": "tool", + "supports": ["BANGLEJS", "BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "allow_emulator": true, + "storage": [ + {"name":"thermom.app.js","url":"app.js"}, + {"name":"thermom.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "mysticdock", + "name": "Mystic Dock", + "version": "1.00", + "description": "A retro-inspired dockface that displays the current time and battery charge while plugged in, and which features an interactive mode that shows the time, date, and a rotating data display line.", + "icon": "mystic-dock.png", + "type": "dock", + "tags": "dock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"mysticdock.app.js","url":"mystic-dock-app.js"}, + {"name":"mysticdock.boot.js","url":"mystic-dock-boot.js"}, + {"name":"mysticdock.settings.js","url":"mystic-dock-settings.js"}, + {"name":"mysticdock.img","url":"mystic-dock-icon.js","evaluate":true} + ] + }, + { + "id": "mysticclock", + "name": "Mystic Clock", + "version": "1.01", + "description": "A retro-inspired watchface featuring time, date, and an interactive data display line.", + "icon": "mystic-clock.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"bangle1-mystic-clock-screenshot.png"}], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"mysticclock.app.js","url":"mystic-clock-app.js"}, + {"name":"mysticclock.settings.js","url":"mystic-clock-settings.js"}, + {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} + ] + }, + { + "id": "hcclock", + "name": "Hi-Contrast Clock", + "version": "0.02", + "description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", + "icon": "hcclock-icon.png", + "type": "clock", + "tags": "clock", + "screenshots": [{"url":"bangle1-high-contrast-clock-screenshot.png"}], + "supports": ["BANGLEJS"], + "allow_emulator": true, + "storage": [ + {"name":"hcclock.app.js","url":"hcclock.app.js"}, + {"name":"hcclock.img","url":"hcclock-icon.js","evaluate":true} + ] + }, + { + "id": "thermomF", + "name": "Fahrenheit Temp", + "version": "0.01", + "description": "[NOT RECOMMENDED] A modification of the Thermometer App to display temprature in Fahrenheit. Please use the 'Thermometer App' and install 'Languages' to get the temperature in the correct format for your locale.", + "icon": "thermf.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"thermomF.app.js","url":"app.js"}, + {"name":"thermomF.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "nixie", + "name": "Nixie Clock", + "shortName": "Nixie", + "version": "0.01", + "description": "A nixie tube clock for both Bangle 1 and 2.", + "icon": "nixie.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"nixie.app.js","url":"app.js"}, + {"name":"nixie.img","url":"app-icon.js","evaluate":true}, + {"name":"m_vatch.js","url":"m_vatch.js"} + ] + }, + { + "id": "carcrazy", + "name": "Car Crazy", + "shortName": "Car Crazy", + "version": "0.03", + "description": "A simple car game where you try to avoid the other cars by tilting your wrist left and right. Hold down button 2 to start.", + "icon": "carcrash.png", + "tags": "game", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"carcrazy.app.js","url":"app.js"}, + {"name":"carcrazy.img","url":"app-icon.js","evaluate":true}, + {"name":"carcrazy.settings.js","url":"settings.js"} + ], + "data": [{"name":"CarCrazy.csv"}] + }, + { + "id": "shortcuts", + "name": "Shortcuts", + "shortName": "Shortcuts", + "version": "0.01", + "description": "Quickly load your favourite apps from (almost) any watch face.", + "icon": "app.png", + "type": "bootloader", + "tags": "tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"shortcuts.boot.js","url":"boot.js"}, + {"name":"shortcuts.settings.js","url":"settings.js"} + ], + "data": [{"name":"shortcuts.json"}] + }, + { + "id": "vectorclock", + "name": "Vector Clock", + "version": "0.03", + "description": "A digital clock that uses the built-in vector font.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "screenshots": [ + {"url":"bangle2-vector-clock-screenshot.png"}, + {"url":"bangle1-vector-clock-screenshot.png"} + ], + "storage": [ + {"name":"vectorclock.app.js","url":"app.js"}, + {"name":"vectorclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "fd6fdetect", + "name": "fd6fdetect", + "shortName": "fd6fdetect", + "version": "0.2", + "description": "Allows you to see 0xFD6F beacons near you.", + "icon": "app.png", + "tags": "tool", + "readme": "README.md", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"fd6fdetect.app.js","url":"app.js"}, + {"name":"fd6fdetect.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "choozi", + "name": "Choozi", + "version": "0.01", + "description": "Choose people or things at random using Bangle.js.", + "icon": "app.png", + "tags": "tool", + "supports": ["BANGLEJS"], + "readme": "README.md", + "allow_emulator": true, + "screenshots": [{"url":"bangle1-choozi-screenshot1.png"},{"url":"bangle1-choozi-screenshot2.png"}], + "storage": [ + {"name":"choozi.app.js","url":"app.js"}, + {"name":"choozi.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widclkbttm", + "name": "Digital clock (Bottom) widget", + "shortName": "Digital clock Bottom Widget", + "version": "0.03", + "description": "Displays time in the bottom area.", + "icon": "widclkbttm.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"widclkbttm.wid.js","url":"widclkbttm.wid.js"} + ] + }, + { + "id": "pastel", + "name": "Pastel Clock", + "shortName": "Pastel", + "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"}, + "screenshots": [{"url":"screenshot_pastel.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"f_architect","url":"f_architect.js"}, + {"name":"f_gochihand","url":"f_gochihand.js"}, + {"name":"f_cabin","url":"f_cabin.js"}, + {"name":"f_orbitron","url":"f_orbitron.js"}, + {"name":"f_monoton","url":"f_monoton.js"}, + {"name":"f_elite","url":"f_elite.js"}, + {"name":"f_lato","url":"f_lato.js"}, + {"name":"f_latosmall","url":"f_latosmall.js"}, + {"name":"pastel.app.js","url":"pastel.app.js"}, + {"name":"pastel.img","url":"pastel.icon.js","evaluate":true}, + {"name":"pastel.settings.js","url":"pastel.settings.js"} + ], + "data": [{"name":"pastel.json"}] + }, + { + "id": "antonclk", + "name": "Anton Clock", + "version": "0.03", + "description": "A simple clock using the bold Anton font.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"antonclk.app.js","url":"app.js"}, + {"name":"antonclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "waveclk", + "name": "Wave Clock", + "version": "0.02", + "description": "A clock using a wave image by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: Works on any Bangle.js 2, but requires firmware 2v11 or later on Bangle.js 1**", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"waveclk.app.js","url":"app.js"}, + {"name":"waveclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "floralclk", + "name": "Floral Clock", + "version": "0.01", + "description": "A clock with a flower background by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: Works on any Bangle.js 2 but requires firmware 2v11 or later on Bangle.js 1**", + "icon": "app.png", + "screenshots": [{"url":"screenshot_floral.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"floralclk.app.js","url":"app.js"}, + {"name":"floralclk.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "score", + "name": "Score Tracker", + "version": "0.01", + "description": "Score Tracker for sports that use plain numbers (e.g. Badminton, Volleyball, Soccer, Table Tennis, ...). Also supports tennis scoring.", + "icon": "score.app.png", + "screenshots": [{"url":"screenshot_score.png"}], + "type": "app", + "tags": "", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"score.app.js","url":"score.app.js"}, + {"name":"score.settings.js","url":"score.settings.js"}, + {"name":"score.presets.json","url":"score.presets.json"}, + {"name":"score.img","url":"score.app-icon.js","evaluate":true} + ], + "data": [{"name":"score.json"}] + }, + { + "id": "menusmall", + "name": "Small Menus", + "version": "0.02", + "description": "Replace Bangle.js 2's menus with a version that contains smaller text", + "icon": "app.png", + "type": "boot", + "tags": "system", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"menusmall.boot.js","url":"boot.js"} + ] + }, + { + "id": "ffcniftya", + "name": "Nifty-A Clock", + "version": "0.01", + "description": "A nifty clock with time and date", + "icon": "app.png", + "screenshots": [{"url":"screenshot_nifty.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"ffcniftya.app.js","url":"app.js"}, + {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "ffcniftyb", + "name": "Nifty-B Clock", + "version": "0.02", + "description": "A nifty clock (series B) with time, date and color configuration", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"ffcniftyb.app.js","url":"app.js"}, + {"name":"ffcniftyb.img","url":"app-icon.js","evaluate":true}, + {"name":"ffcniftyb.settings.js","url":"settings.js"} + ], + "data": [{"name":"ffcniftyb.json"}] + }, + { + "id": "stopwatch", + "name": "Stopwatch Touch", + "version": "0.01", + "description": "A touch based stop watch for Bangle JS 2", + "icon": "stopwatch.png", + "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], + "tags": "tools,app", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"stopwatch.app.js","url":"stopwatch.app.js"}, + {"name":"stopwatch.img","url":"stopwatch.icon.js","evaluate":true} + ] + }, + { + "id": "vernierrespirate", + "name": "Vernier Go Direct Respiration Belt", + "shortName": "Respiration Belt", + "version": "0.01", + "description": "Connects to a Go Direct Respiration Belt and shows respiration rate", + "icon": "app.png", + "tags": "health,bluetooth", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"vernierrespirate.app.js","url":"app.js"}, + {"name":"vernierrespirate.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"vernierrespirate.json"}] + }, + { + "id": "gpstouch", + "name": "GPS Touch", + "version": "0.01", + "description": "A touch based GPS watch, shows OS map reference", + "icon": "gpstouch.png", + "screenshots": [{"url":"screenshot4.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot1.png"}], + "tags": "tools,app", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"geotools","url":"geotools.js"}, + {"name":"gpstouch.app.js","url":"gpstouch.app.js"}, + {"name":"gpstouch.img","url":"gpstouch.icon.js","evaluate":true} + ] + }, + { + "id": "swiperclocklaunch", + "name": "Swiper Clock Launch", + "version": "0.02", + "description": "Navigate between clock and launcher with Swipe action", + "icon": "swiperclocklaunch.png", + "type": "bootloader", + "tags": "tools, system", + "supports": ["BANGLEJS", "BANGLEJS2"], + "storage": [ + {"name":"swiperclocklaunch.boot.js","url":"boot.js"}, + {"name":"swiperclocklaunch.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "qalarm", + "name": "Q Alarm and Timer", + "shortName": "Q Alarm", + "icon": "app.png", + "version": "0.03", + "description": "Alarm and timer app with days of week and 'hard' option.", + "tags": "tool,alarm,widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "storage": [ + { "name": "qalarm.app.js", "url": "app.js" }, + { "name": "qalarm.boot.js", "url": "boot.js" }, + { "name": "qalarm.js", "url": "qalarm.js" }, + { "name": "qalarmcheck.js", "url": "qalarmcheck.js" }, + { "name": "qalarm.img", "url": "app-icon.js", "evaluate": true }, + { "name": "qalarm.wid.js", "url": "widget.js" } + ], + "data": [{ "name": "qalarm.json" }] + }, + { + "id": "emojuino", + "name": "Emojuino", + "shortName": "Emojuino", + "version": "0.03", + "description": "Emojis & Espruino: broadcast Unicode emojis via Bluetooth Low Energy.", + "icon": "emojuino.png", + "screenshots": [ + { "url": "screenshot-tx.png" }, + { "url": "screenshot-swipe.png" }, + { "url": "screenshot-welcome.png" } + ], + "type": "app", + "tags": "emoji", + "supports" : [ "BANGLEJS2" ], + "allow_emulator": true, + "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.03", + "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. Also added HID media controlls, just swipe on the clock face to controll the media! Gadgetbride support coming soon(hopefully) Thanks to t0m1o1 for media controls!", + "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": "wid_a_battery_widget", + "name": "A Battery Widget (with percentage)", + "shortName":"A Battery Widget", + "icon": "widget.png", + "version":"1.02", + "type": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "description": "Simple and slim battery widget with charge status and percentage", + "tags": "widget,battery", + "storage": [ + {"name":"wid_a_battery_widget.wid.js","url":"widget.js"} + ] + }, + { + "id": "lcars", + "name": "LCARS Clock", + "shortName":"LCARS", + "icon": "lcars.png", + "version":"0.07", + "readme": "README.md", + "supports": ["BANGLEJS2"], + "description": "Library Computer Access Retrieval System (LCARS) clock.", + "type": "clock", + "tags": "clock", + "screenshots": [{"url":"screenshot.png"}], + "storage": [ + {"name":"lcars.app.js","url":"lcars.app.js"}, + {"name":"lcars.img","url":"lcars.icon.js","evaluate":true}, + {"name":"lcars.settings.js","url":"lcars.settings.js"} + ] + }, + { "id": "binwatch", + "name": "Binary Watch", + "shortName":"BinWatch", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "version":"0.04", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "allow_emulator":true, + "description": "Famous binary watch", + "tags": "clock", + "type": "clock", + "storage": [ + {"name":"binwatch.app.js","url":"app.js"}, + {"name":"binwatch.bg176.img","url":"Background176_center.img"}, + {"name":"binwatch.bg240.img","url":"Background240_center.img"}, + {"name":"binwatch.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "hidmsicswipe", + "name": "Bluetooth Music Swipe Controls", + "shortName": "Swipe Control", + "version": "0.01", + "description": "Based on the original Bluetooth Music Controls. Swipe up/down for volume, left/right for previous and next, tap for play/pause and btn1 to lock and unlock the controls. Enable HID in settings, pair with your phone, then use this app to control music from your watch!", + "icon": "hidmsicswipe.png", + "tags": "bluetooth", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"hidmsicswipe.app.js","url":"hidmsicswipe.js"}, + {"name":"hidmsicswipe.img","url":"hidmsicswipe-icon.js","evaluate":true} + ] + }, + { + "id": "authentiwatch", + "name": "2FA Authenticator", + "shortName": "AuthWatch", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "version": "0.04", + "description": "Google Authenticator compatible tool.", + "tags": "tool", + "interface": "interface.html", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"authentiwatch.app.js","url":"app.js"}, + {"name":"authentiwatch.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"authentiwatch.json"}] + }, + { "id": "schoolCalendar", + "name": "School Calendar", + "shortName":"SCalendar", + "icon": "CalenderLogo.png", + "version": "0.01", + "description": "A simple calendar that you can see your upcoming events that you create in the customizer. Keep in note that your events reapeat weekly.(Beta)", + "tags": "tool", + "readme":"README.md", + "custom":"custom.html", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"screenshot_basic.png"},{"url":"screenshot_info.png"}], + "storage": [ + {"name":"schoolCalendar.app.js"}, + {"name":"schoolCalendar.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"calendarItems.csv"} + ] + }, + { "id": "timecal", + "name": "TimeCal", + "shortName":"TimeCal", + "icon": "icon.png", + "version":"0.01", + "description": "TimeCal shows the Time along with a 3 week calendar", + "tags": "clock", + "type": "clock", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"timecal.app.js","url":"timecal.app.js"} + ] + }, + { + "id": "a_clock_timer", + "name": "A Clock with Timer", + "version": "0.01", + "description": "A Clock with Timer, Map and Time Zones", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"a_clock_timer.app.js","url":"app.js"}, + {"name":"a_clock_timer.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id":"intervalTimer", + "name":"Interval Timer", + "shortName":"Interval Timer", + "icon": "app.png", + "version":"0.01", + "description": "Interval Timer for workouts, HIIT, or whatever else.", + "tags": "timer, interval, hiit, workout", + "readme":"README.md", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"intervalTimer.app.js","url":"app.js"}, + {"name":"intervalTimer.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "93dub", + "name": "93 Dub", + "shortName":"93 Dub", + "icon": "93dub.png", + "screenshots": [{"url":"screenshot.png"}], + "version":"0.05", + "description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo", + "tags": "clock", + "type": "clock", + "supports":["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"93dub.app.js","url":"app.js"}, + {"name":"93dub.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "poweroff", + "name": "Poweroff", + "shortName":"Poweroff", + "version":"0.01", + "description": "Simple app to power off your Bangle.js", + "icon": "app.png", + "tags": "tool, poweroff, shutdown", + "supports" : ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"poweroff.app.js","url":"app.js"}, + {"name":"poweroff.img","url":"app-icon.js","evaluate":true} + ] +}, +{ + "id": "sensible", + "name": "SensiBLE", + "shortName": "SensiBLE", + "version": "0.04", + "description": "Collect, display and advertise real-time sensor data.", + "icon": "sensible.png", + "screenshots": [ + { "url": "screenshot-top.png" }, + { "url": "screenshot-acc.png" }, + { "url": "screenshot-bar.png" }, + { "url": "screenshot-gps.png" }, + { "url": "screenshot-hrm.png" }, + { "url": "screenshot-mag.png" } + ], + "type": "app", + "tags": "tool,sensors", + "supports" : [ "BANGLEJS2" ], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + { "name": "sensible.app.js", "url": "sensible.js" }, + { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } + ] +}, + { + "id": "widbars", + "name": "Bars Widget", + "version": "0.01", + "description": "Display several measurements as vertical bars.", + "icon": "icon.png", + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widbars.wid.js","url":"widget.js"} + ] +}, +{ + "id":"a_speech_timer", + "name":"Speech Timer", + "icon": "app.png", + "version":"1.01", + "description": "A timer designed to help keeping your speeches and presentations to time.", + "tags": "tool,timer", + "readme":"README.md", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"a_speech_timer.app.js","url":"app.js"}, + {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} + ] +}, + { "id": "mylocation", + "name": "My Location", + "shortName":"My Location", + "icon": "mylocation.png", + "type": "app", + "screenshots": [{"url":"screenshot_1.png"}], + "version":"0.01", + "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", + "readme": "README.md", + "tags": "tool,utility", + "supports": ["BANGLEJS", "BANGLEJS2"], + "storage": [ + {"name":"mylocation.app.js","url":"mylocation.app.js"}, + {"name":"mylocation.img","url":"mylocation.icon.js","evaluate": true } + ], + "data": [ + {"name":"mylocation.json"} + ] + }, + { + "id": "pebble", + "name": "Pebble Clock", + "shortName": "Pebble", + "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"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"pebble.app.js","url":"pebble.app.js"}, + {"name":"pebble.settings.js","url":"pebble.settings.js"}, + {"name":"pebble.img","url":"pebble.icon.js","evaluate":true} + ] + }, + { "id": "pooqroman", + "name": "pooq Roman watch face", + "shortName":"pooq Roman", + "version":"0.03", + "description": "A classic watch face with a certain dynamicity. Most amusing in 24h mode. Slide up to show more hands, down for less(!). By design does not support standard widgets, sorry!", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"pooqroman.app.js","url":"app.js"}, + {"name":"pooqroman.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"pooqroman.json"} + ] + }, + { + "id": "widbata", + "name": "Battery Level Widget (Themed)", + "shortName":"Battery Theme", + "icon": "widbata.png", + "screenshots": [{"url":"screenshot_widbata_1.png"}], + "version":"0.01", + "type": "widget", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "description": "Shows the current battery level status in the top right using the clocks colour theme", + "tags": "widget,battery", + "storage": [ + {"name":"widbata.wid.js","url":"widbata.wid.js"} + ] + }, + { + "id": "weatherClock", + "name": "Weather Clock", + "version": "0.04", + "description": "A clock which displays current weather conditions (requires Gadgetbridge and Weather apps).", + "icon": "app.png", + "screenshots": [{"url":"screens/screen1.png"}], + "type": "clock", + "tags": "clock, weather", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"weatherClock.app.js","url":"app.js"}, + {"name":"weatherClock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "menuwheel", + "name": "Wheel Menus", + "version": "0.01", + "description": "Replace Bangle.js 2's menus with a version that contains variable-size text and a back button", + "readme": "README.md", + "icon": "icon.png", + "screenshots": [ + {"url":"screenshot_b1_dark.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_light.png"}, + {"url":"screenshot_b2_dark.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_light.png"} + ], + "type": "boot", + "tags": "system", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"menuwheel.boot.js","url":"boot.js"} + ] + }, + { "id": "widChargingStatus", + "name": "Charging Status", + "shortName":"ChargingStatus", + "icon": "widget.png", + "version":"0.1", + "type": "widget", + "description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widChargingStatus.wid.js","url":"widget.js"} + ] + }, + { + "id": "flow", + "name": "FLOW", + "shortName": "FLOW", + "version": "0.01", + "description": "A game where you have to help a flow avoid white obstacles thing by tapping! This is a demake of an app which I forgot the name of. Press BTN(1) to restart. See if you can get to 2500 score!", + "icon": "app.png", + "tags": "game", + "supports" : ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name": "flow.app.js", "url": "app.js" }, + {"name": "flow.img", "url": "app-icon.js","evaluate": true } + ] + }, + { "id": "scribble", + "name": "Scribble", + "shortName":"Scribble", + "version":"0.01", + "type": "app", + "description": "A keyboard on your wrist! Swipe right for space, left for delete.", + "icon": "app.png", + "allow_emulator": true, + "tags": "tools, keyboard, text, scribble", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"scribble.app.js","url":"app.js"}, + {"name":"scribble.img","url":"app-icon.js","evaluate":true} + ], + "screenshots":[ + { "url":"screenshot.png" } + ] + }, + { + "id": "ptlaunch", + "name": "Pattern Launcher", + "shortName": "Pattern Launcher", + "version": "0.11", + "description": "Directly launch apps from the clock screen with custom patterns.", + "icon": "app.png", + "screenshots": [{"url":"manage_patterns_light.png"}], + "tags": "tools", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + { "name": "ptlaunch.app.js", "url": "app.js" }, + { "name": "ptlaunch.boot.js", "url": "boot.js" }, + { "name": "ptlaunch.img", "url": "app-icon.js", "evaluate": true } + ], + "data": [{"name":"ptlaunch.patterns.json"}] + }, + { + "id": "rebble", + "name": "Rebble Clock", + "shortName": "Rebble", + "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", "widpedom":"app"}, + "screenshots": [{"url":"screenshot_rebble.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"rebble.app.js","url":"rebble.app.js"}, + {"name":"rebble.settings.js","url":"rebble.settings.js"}, + {"name":"rebble.img","url":"rebble.icon.js","evaluate":true} + ] + }, + { "id": "snaky", + "name": "Snaky", + "shortName":"Snaky", + "version":"0.01", + "description": "The classic snake game. Eat apples and don't bite your tail. Control the snake with the touch screen.", + "tags": "game,fun", + "icon": "snaky.png", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"snaky.app.js","url":"snaky.js"}, + {"name":"snaky.img","url":"snaky-icon.js","evaluate":true} + ] + }, + { + "id": "clicompleteclk", + "name": "CLI complete clock", + "shortName":"CLI cmplt clock", + "version":"0.03", + "description": "Command line styled clock with lots of information", + "icon": "app.png", + "allow_emulator": true, + "type": "clock", + "tags": "clock,cli,command,bash,shell,weather,hrt", + "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"} + ], + "data": [{"name":"clicompleteclk.json"}] + }, + { + "id":"awairmonitor", + "name":"Awair Monitor", + "icon": "app.png", + "allow_emulator": true, + "version":"0.01", + "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", + "tags": "tool,health", + "readme":"README.md", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"awairmonitor.app.js","url":"app.js"}, + {"name":"awairmonitor.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "pooqround", + "name": "pooq Round watch face", + "shortName":"pooq Round", + "version":"0.01", + "description": "A 24 hour analogue watchface with high legibility and a novel style.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"pooqround.app.js","url":"app.js"}, + {"name":"pooqround.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"pooqround.json"} + ] + }, + { + "id": "coretemp", + "name": "Core Temp Display", + "version": "0.01", + "description": "Display CoreTemp device sensor data", + "icon": "coretemp.png", + "type": "app", + "tags": "health", + "readme": "README.md", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"coretemp.boot.js","url":"boot.js"}, + {"name":"coretemp.app.js","url":"coretemp.js"}, + {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true} + ] + }, + { + "id": "showimg", + "name": "simple image viewer", + "shortName":"showImage", + "version":"0.2", + "description": "Displays the image in \"showimg.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"], + "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": "pebbled", + "name": "Pebble Clock with distance", + "shortName": "Pebble + distance", + "version": "0.1", + "description": "Fork of Pebble Clock with distance in KM. Both step count and the distance are on the main screen. Default step length = 0.75m (can be changed in settings).", + "readme": "README.md", + "icon": "pebbled.png", + "screenshots": [{"url":"pebble_screenshot.png"}], + "type": "clock", + "tags": "clock,distance", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"pebbled.app.js","url":"pebbled.app.js"}, + {"name":"pebbled.settings.js","url":"pebbled.settings.js"}, + {"name":"pebbled.img","url":"pebbled.icon.js","evaluate":true} + ] + }, + { "id": "circlesclock", + "name": "Circles clock", + "shortName":"Circles clock", + "version":"0.02", + "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"} + ] + }, + { + "id": "ltherm", + "name": "Localized Thermometer", + "shortName": "Thermometer", + "version": "0.01", + "description": "Displays the current temperature in localized units.", + "icon": "thermf.png", + "tags": "tool", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"ltherm.app.js","url":"app.js"}, + {"name":"ltherm.img","url":"icon.js","evaluate":true} + ] + } ] From f3c0dfcdcaf1cee6a3f397cdb5f9fea771be01be Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 24 Feb 2022 11:19:35 +0100 Subject: [PATCH 166/199] Change threema icon to 24x24px 1bit color --- apps/messages/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 512659c40..282a2b125 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -92,7 +92,7 @@ function getMessageImage(msg) { if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); if (s=="sms message") return getNotificationImage(); - if (s=="threema") return atob("ICCDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//+AAAAAAAAAAAP/////wAAAAAAAAB//////+AAAAAAAAP///////wAAAAAAB////////+AAAAAAP///wAP///wAAAAAP/////////wAAAAAP//+P/x///wAAAAAP//+P/x///+AAAAB///+AAB///+AAAAAP//+AAB///+AAAAAP//+AAB///wAAAAAP//+AAB///wAAAAAB/////////wAAAAAB////////+AAAAAAB////////wAAAAAAB///////+AAAAAAAP//////+AAAAAAAAP+AAP/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEkAAkAAkgAAAAAAAEkAEkgAkgAAAAAAAEkAAkAAkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); + if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); From 4143a5f105cfd2b5eb8a84d93e77cd9d2ea65542 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 24 Feb 2022 11:01:37 +0000 Subject: [PATCH 167/199] 0.05: Don't poll for GPS status, override setGPSPower handler (fix #1456) --- apps/widgps/ChangeLog | 1 + apps/widgps/metadata.json | 2 +- apps/widgps/widget.js | 27 +++++++++------------------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/apps/widgps/ChangeLog b/apps/widgps/ChangeLog index 3d47b8a0c..f68fc701c 100644 --- a/apps/widgps/ChangeLog +++ b/apps/widgps/ChangeLog @@ -2,3 +2,4 @@ 0.02: Don't break if running on 2v08 firmware (just don't display anything) 0.03: Fix positioning 0.04: Show GPS fix status +0.05: Don't poll for GPS status, override setGPSPower handler (fix #1456) diff --git a/apps/widgps/metadata.json b/apps/widgps/metadata.json index 2f59aa82a..39bff2fad 100644 --- a/apps/widgps/metadata.json +++ b/apps/widgps/metadata.json @@ -1,7 +1,7 @@ { "id": "widgps", "name": "GPS Widget", - "version": "0.04", + "version": "0.05", "description": "Tiny widget to show the power and fix status of the GPS", "icon": "widget.png", "type": "widget", diff --git a/apps/widgps/widget.js b/apps/widgps/widget.js index 25df2178a..bfdb89d33 100644 --- a/apps/widgps/widget.js +++ b/apps/widgps/widget.js @@ -1,7 +1,13 @@ (function(){ - if (!Bangle.isGPSOn) return; // old firmware + // override setGPSPower so we know if GPS is on or off + var oldSetGPSPower = Bangle.setGPSPower; + Bangle.setGPSPower = function(on,id) { + var isGPSon = oldSetGPSPower(on,id); + WIDGETS.gps.draw(); + return isGPSon; + } - function draw() { + WIDGETS.gps={area:"tr",width:24,draw:function() { g.reset(); if (Bangle.isGPSOn()) { const gpsObject = Bangle.getGPSFix(); @@ -14,20 +20,5 @@ g.setColor("#888"); // off = grey } g.drawImage(atob("GBiBAAAAAAAAAAAAAA//8B//+BgYGBgYGBgYGBgYGBgYGBgYGB//+B//+BgYGBgYGBgYGBgYGBgYGBgYGB//+A//8AAAAAAAAAAAAA=="), this.x, 2+this.y); - } - - var timerInterval; - Bangle.on('lcdPower', function(on) { - if (on) { - WIDGETS.gps.draw(); - if (!timerInterval) timerInterval = setInterval(()=>WIDGETS.gps.draw(), 2000); - } else { - if (timerInterval) { - clearInterval(timerInterval); - timerInterval = undefined; - } - } - }); - - WIDGETS.gps={area:"tr",width:24,draw:draw}; + }}; })(); From 14b6004f1c0bfa7d579c8bab9271d111853fab0a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 24 Feb 2022 11:33:05 +0000 Subject: [PATCH 168/199] Update setUI to work with new Bangle.js 2v13 menu style --- apps/ptlaunch/ChangeLog | 3 ++- apps/ptlaunch/boot.js | 1 + apps/ptlaunch/metadata.json | 2 +- apps/shortcuts/ChangeLog | 3 ++- apps/shortcuts/boot.js | 2 +- apps/shortcuts/metadata.json | 2 +- apps/swiperclocklaunch/ChangeLog | 1 + apps/swiperclocklaunch/boot.js | 1 + apps/swiperclocklaunch/metadata.json | 2 +- 9 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/ptlaunch/ChangeLog b/apps/ptlaunch/ChangeLog index 68b7d3e1c..eec3610ed 100644 --- a/apps/ptlaunch/ChangeLog +++ b/apps/ptlaunch/ChangeLog @@ -4,4 +4,5 @@ 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 0.12: Improve pattern detection code readability by PaddeK http://forum.espruino.com/profiles/117930/ -0.13: Improve pattern rendering by HughB http://forum.espruino.com/profiles/167235/ \ No newline at end of file +0.13: Improve pattern rendering by HughB http://forum.espruino.com/profiles/167235/ +0.14: Update setUI to work with new Bangle.js 2v13 menu style diff --git a/apps/ptlaunch/boot.js b/apps/ptlaunch/boot.js index 19a8f16cb..748d564f3 100644 --- a/apps/ptlaunch/boot.js +++ b/apps/ptlaunch/boot.js @@ -76,6 +76,7 @@ var sui = Bangle.setUI; Bangle.setUI = function (mode, cb) { sui(mode, cb); + if ("object"==typeof mode) mode = mode.mode; if (!mode) { Bangle.removeListener("drag", dragHandler); storedPatterns = {}; diff --git a/apps/ptlaunch/metadata.json b/apps/ptlaunch/metadata.json index 6c3870d24..0b6dce3d1 100644 --- a/apps/ptlaunch/metadata.json +++ b/apps/ptlaunch/metadata.json @@ -2,7 +2,7 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.13", + "version": "0.14", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", "screenshots": [{"url":"manage_patterns_light.png"}], diff --git a/apps/shortcuts/ChangeLog b/apps/shortcuts/ChangeLog index 2286a7f70..0e4a98065 100644 --- a/apps/shortcuts/ChangeLog +++ b/apps/shortcuts/ChangeLog @@ -1 +1,2 @@ -0.01: New App! \ No newline at end of file +0.01: New App! +0.02: Update setUI to work with new Bangle.js 2v13 menu style diff --git a/apps/shortcuts/boot.js b/apps/shortcuts/boot.js index f71f6d6ca..58ce2d067 100644 --- a/apps/shortcuts/boot.js +++ b/apps/shortcuts/boot.js @@ -1,6 +1,7 @@ (function() { var sui = Bangle.setUI; Bangle.setUI = function(mode, cb) { + if ("object"==typeof mode) mode = mode.mode; if (mode!="clock") return sui(mode,cb); return sui("clockupdown", (dir) => { let settings = require("Storage").readJSON("shortcuts.json", 1)||{}; @@ -12,4 +13,3 @@ }); }; })(); - \ No newline at end of file diff --git a/apps/shortcuts/metadata.json b/apps/shortcuts/metadata.json index 2351a102f..922d5ae11 100644 --- a/apps/shortcuts/metadata.json +++ b/apps/shortcuts/metadata.json @@ -2,7 +2,7 @@ "id": "shortcuts", "name": "Shortcuts", "shortName": "Shortcuts", - "version": "0.01", + "version": "0.02", "description": "Quickly load your favourite apps from (almost) any watch face.", "icon": "app.png", "type": "bootloader", diff --git a/apps/swiperclocklaunch/ChangeLog b/apps/swiperclocklaunch/ChangeLog index c1b4a5fbb..244b602b5 100644 --- a/apps/swiperclocklaunch/ChangeLog +++ b/apps/swiperclocklaunch/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Fix issue with mode being undefined +0.03: Update setUI to work with new Bangle.js 2v13 menu style diff --git a/apps/swiperclocklaunch/boot.js b/apps/swiperclocklaunch/boot.js index e9b203eee..bb285ea94 100644 --- a/apps/swiperclocklaunch/boot.js +++ b/apps/swiperclocklaunch/boot.js @@ -4,6 +4,7 @@ Bangle.setUI = function(mode, cb) { sui(mode,cb); if(!mode) return; + if ("object"==typeof mode) mode = mode.mode; if (!mode.startsWith("clock")) return; Bangle.swipeHandler = dir => { if (dir<0) Bangle.showLauncher(); }; Bangle.on("swipe", Bangle.swipeHandler); diff --git a/apps/swiperclocklaunch/metadata.json b/apps/swiperclocklaunch/metadata.json index 733aaa032..5e4a0d648 100644 --- a/apps/swiperclocklaunch/metadata.json +++ b/apps/swiperclocklaunch/metadata.json @@ -1,7 +1,7 @@ { "id": "swiperclocklaunch", "name": "Swiper Clock Launch", - "version": "0.02", + "version": "0.03", "description": "Navigate between clock and launcher with Swipe action", "icon": "swiperclocklaunch.png", "type": "bootloader", From 2353191df4fc566803c7596639745a4b9f7246e5 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 24 Feb 2022 15:03:13 +0100 Subject: [PATCH 169/199] messages: Remove left-over debug statement --- apps/messages/ChangeLog | 1 + apps/messages/metadata.json | 2 +- apps/messages/widget.js | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 1e6ac71d7..bd40868a5 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -36,3 +36,4 @@ Also gave the widget a pixel more room to the right 0.23: Change message colors to match current theme instead of using green Now attempt to use Large/Big/Medium fonts, and allow minimum font size to be configured +0.24: Remove left-over debug statement diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index e8ed83099..0387c1972 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.23", + "version": "0.24", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", diff --git a/apps/messages/widget.js b/apps/messages/widget.js index 4a247b917..d9363573a 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -6,7 +6,6 @@ draw:function() { g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth); g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y); let settings = require('Storage').readJSON("messages.settings.json", true) || {}; - console.log("dingen ", typeof(settings.repeat), settings.repeat) if (settings.repeat===undefined) settings.repeat = 4; if (c<120 && (Date.now()-this.l)>settings.repeat*1000) { this.l = Date.now(); @@ -47,4 +46,4 @@ want to buzz but should still show that there are unread messages. */ if (global.MESSAGES===undefined) (function() { var messages = require("Storage").readJSON("messages.json",1)||[]; if (messages.some(m=>m.new)) WIDGETS["messages"].show(true); -})(); \ No newline at end of file +})(); From 300bde3034e42d468c2d7be4c9241a52c42b5f38 Mon Sep 17 00:00:00 2001 From: Andrew <45957548+midnight4577@users.noreply.github.com> Date: Thu, 24 Feb 2022 08:45:31 -0800 Subject: [PATCH 170/199] Made "Supports" an array --- apps/aptsciclk/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/aptsciclk/metadata.json b/apps/aptsciclk/metadata.json index 15d8ec4e3..c450d926e 100644 --- a/apps/aptsciclk/metadata.json +++ b/apps/aptsciclk/metadata.json @@ -7,7 +7,7 @@ "icon": "app.png", "type": "clock", "tags": "clock", - "supports": "BANGLEJS2", + "supports": ["BANGLEJS2"], "allow_emulator": false, "readme":"README.md", "storage": [ From 8424cc91503ec8c5235b6843e368e79f16f8e321 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 24 Feb 2022 18:22:32 +0000 Subject: [PATCH 171/199] Daisy - fixed metadata --- apps/daisy/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index f2624a0f3..c35bfefa3 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -11,7 +11,7 @@ "storage": [ {"name":"daisy.app.js","url":"app.js"}, {"name":"daisy.img","url":"app-icon.js","evaluate":true}, - {"name":"daisy.settings.js","url":"daisy.settings.js"} + {"name":"daisy.settings.js","url":"settings.js"} ], "data": [{"name":"daisy.json"}] } From 8535b50a0ddf89a7b9e26a0e7369e3cdbeae15f5 Mon Sep 17 00:00:00 2001 From: Marco H Date: Fri, 25 Feb 2022 09:44:34 +0100 Subject: [PATCH 172/199] Messages: icon for alarms --- apps/messages/app.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/messages/app.js b/apps/messages/app.js index fdcad7469..3f3b80080 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -75,9 +75,13 @@ function getPosImage() { function getNegImage() { return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="); } +/* +* icons should be 24x24px with 1bpp colors and transparancy +*/ function getMessageImage(msg) { if (msg.img) return atob(msg.img); var s = (msg.src||"").toLowerCase(); + if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA="); if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); if (s=="facebook") return getFBIcon(); if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); @@ -104,6 +108,7 @@ function getMessageImage(msg) { function getMessageImageCol(msg,def) { return { // generic colors, using B2-safe colors + "alarm": "#fff", "calendar": "#f00", "mail": "#ff0", "music": "#f0f", From 0e850f38028a29d994406f719caad56722f29ff2 Mon Sep 17 00:00:00 2001 From: Marco H Date: Fri, 25 Feb 2022 09:46:03 +0100 Subject: [PATCH 173/199] Bump version to 0.11 --- apps/circlesclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/metadata.json b/apps/circlesclock/metadata.json index 3279ec2cf..b16f14c06 100644 --- a/apps/circlesclock/metadata.json +++ b/apps/circlesclock/metadata.json @@ -1,7 +1,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.10", + "version":"0.11", "description": "A clock with three or four circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}], From bef3c32a9abd4030fa7b3d65e093e83d721c8759 Mon Sep 17 00:00:00 2001 From: Markus Laire Date: Fri, 25 Feb 2022 17:51:31 +0200 Subject: [PATCH 174/199] widadjust: add metadata.json --- apps/widadjust/metadata.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 apps/widadjust/metadata.json diff --git a/apps/widadjust/metadata.json b/apps/widadjust/metadata.json new file mode 100644 index 000000000..30670fd83 --- /dev/null +++ b/apps/widadjust/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "widadjust", + "name": "Adjust Clock", + "version": "0.01", + "description": "Adjusts clock continually in the background to counter clock drift", + "type": "widget", + "tags": "widget", + "supports": [ "BANGLEJS", "BANGLEJS2" ], + "readme": "README.md", + "storage": [ + { "name": "widadjust.wid.js", "url": "widget.js" }, + { "name": "widadjust.settings.js", "url": "settings.js" } + ], + "data": [ + { "name": "widadjust.json" }, + { "name": "widadjust.state" } + ] +} From 38d6a95303cd72e56f9e041d4da1f571b1198851 Mon Sep 17 00:00:00 2001 From: Markus Laire Date: Fri, 25 Feb 2022 17:53:04 +0200 Subject: [PATCH 175/199] widadjust: add other files for v0.01 --- apps/widadjust/README.md | 52 ++++++++ apps/widadjust/settings.js | 120 ++++++++++++++++++ apps/widadjust/widget.js | 244 +++++++++++++++++++++++++++++++++++++ 3 files changed, 416 insertions(+) create mode 100644 apps/widadjust/README.md create mode 100644 apps/widadjust/settings.js create mode 100644 apps/widadjust/widget.js diff --git a/apps/widadjust/README.md b/apps/widadjust/README.md new file mode 100644 index 000000000..1b51440f5 --- /dev/null +++ b/apps/widadjust/README.md @@ -0,0 +1,52 @@ +# Adjust Clock + +Adjusts clock continually in the background to counter clock drift. + +## Usage + +First you need to determine the clock drift of your watch in PPM (parts per million). + +For example if you measure that your watch clock is too fast by 5 seconds in 24 hours, +then PPM is `5 / (24*60*60) * 1000000 = 57.9`. + +Then set PPM in settings and this widget will continually adjust the clock by that amount. + +## Settings + +See **Basic logic** below for more details. + +- **PPM x 10** - change PPM in steps of 10 +- **PPM x 1** - change PPM in steps of 1 +- **PPM x 0.1** - change PPM in steps of 0.1 +- **Update Interval** - How often to update widget and clock error. +- **Threshold** - Threshold for adjusting clock. + When clock error exceeds this threshold, clock is adjusted with `setTime`. +- **Save State** - If `On` clock error state is saved to file when widget exits, if needed. + That is recommended and default setting. + If `Off` clock error state is forgotten and reset to 0 whenever widget is restarted, + for example when going to Launcher. This can cause significant inaccuracy especially + with large **Update Interval** or **Threshold**. +- **Debug Log** - If `On` some debug information is logged to file `widadjust.log`. + +## Display + +Widget shows clock error in milliseconds and PPM. + +## Basic logic + +- When widget starts, clock error state is loaded from file `widadjust.state`. +- While widget is running, widget display and clock error is updated + periodically (**Update Interval**) according to **PPM**. +- When clock error exceeds **Threshold** clock is adjusted with `setTime`. +- When widget exists, clock error state is saved to file `widadjust.state` if needed. + +## Services + +Other apps/widgets can use `WIDGETS.adjust.now()` to request current adjusted time. +To support also case where this widget isn't present, the following code can be used: + +``` +function adjustedNow() { + return WIDGETS.adjust ? WIDGETS.adjust.now() : Date.now(); +} +``` diff --git a/apps/widadjust/settings.js b/apps/widadjust/settings.js new file mode 100644 index 000000000..5791d763b --- /dev/null +++ b/apps/widadjust/settings.js @@ -0,0 +1,120 @@ +(function(back) { + const SETTINGS_FILE = 'widadjust.json'; + const STATE_FILE = 'widadjust.state'; + + const DEFAULT_ADJUST_THRESHOLD = 100; + let thresholdV = [ 10, 25, 50, 100, 250, 500, 1000 ]; + + const DEFAULT_UPDATE_INTERVAL = 60000; + let intervalV = [ 10000, 30000, 60000, 180000, 600000, 1800000, 3600000 ]; + let intervalN = [ "10 s", "30 s", "1 m", "3 m", "10 m", "30 m", "1 h" ]; + + let stateFileErased = false; + + let settings = Object.assign({ + advanced: false, + saveState: true, + debugLog: false, + ppm: 0, + adjustThreshold: DEFAULT_ADJUST_THRESHOLD, + updateInterval: DEFAULT_UPDATE_INTERVAL, + }, require('Storage').readJSON(SETTINGS_FILE, true) || {}); + + if (thresholdV.indexOf(settings.adjustThreshold) == -1) { + settings.adjustThreshold = DEFAULT_ADJUST_THRESHOLD; + } + + if (intervalV.indexOf(settings.updateInterval) == -1) { + settings.updateInterval = DEFAULT_UPDATE_INTERVAL; + } + + function onPpmChange(v) { + settings.ppm = v; + mainMenu['PPM x 10' ].value = v; + mainMenu['PPM x 1' ].value = v; + mainMenu['PPM x 0.1'].value = v; + } + + let mainMenu = { + '': { 'title' : 'Adjust Clock' }, + + '< Back': () => { + require('Storage').writeJSON(SETTINGS_FILE, settings); + back(); + }, + + /* + // NOT FULLY WORKING YET + 'Mode': { + value: settings.advanced, + format: v => v ? 'Advanced' : 'Basic', + onchange: () => { + settings.advanced = !settings.advanced; + } + }, + */ + + 'PPM x 10' : { + value: settings.ppm, + format: v => v.toFixed(1), + step: 10, + onchange : onPpmChange, + }, + + 'PPM x 1' : { + value: settings.ppm, + format: v => v.toFixed(1), + step: 1, + onchange : onPpmChange, + }, + + 'PPM x 0.1' : { + value: settings.ppm, + format: v => v.toFixed(1), + step: 0.1, + onchange : onPpmChange, + }, + + 'Update Interval': { + value: intervalV.indexOf(settings.updateInterval), + min: 0, + max: intervalV.length - 1, + format: v => intervalN[v], + onchange: v => { + settings.updateInterval = intervalV[v]; + }, + }, + + 'Threshold': { + value: thresholdV.indexOf(settings.adjustThreshold), + min: 0, + max: thresholdV.length - 1, + format: v => thresholdV[v] + " ms", + onchange: v => { + settings.adjustThreshold = thresholdV[v]; + }, + }, + + 'Save State': { + value: settings.saveState, + format: v => v ? 'On' : 'Off', + onchange: () => { + settings.saveState = !settings.saveState; + if (!settings.saveState && !stateFileErased) { + stateFileErased = true; + require("Storage").erase(STATE_FILE); + } + }, + }, + + 'Debug Log': { + value: settings.debugLog, + format: v => v ? 'On' : 'Off', + onchange: () => { + settings.debugLog = !settings.debugLog; + }, + }, + }; + + E.showMenu(mainMenu); +}) diff --git a/apps/widadjust/widget.js b/apps/widadjust/widget.js new file mode 100644 index 000000000..ce1fee022 --- /dev/null +++ b/apps/widadjust/widget.js @@ -0,0 +1,244 @@ +(() => { + // ====================================================================== + // CONST + + const DEBUG_LOG_FILE = 'widadjust.log'; + const SETTINGS_FILE = 'widadjust.json'; + const STATE_FILE = 'widadjust.state'; + + const DEFAULT_ADJUST_THRESHOLD = 100; + const DEFAULT_UPDATE_INTERVAL = 60 * 1000; + const MIN_INTERVAL = 10 * 1000; + + const MAX_CLOCK_ERROR_FROM_SAVED_STATE = 2000; + + const SAVE_STATE_CLOCK_ERROR_DELTA_THRESHOLD = 1; + const SAVE_STATE_CLOCK_ERROR_DELTA_IN_PPM_THRESHOLD = 1; + const SAVE_STATE_PPM_DELTA_THRESHOLD = 1; + + // Widget width. + const WIDTH = 22; + + // ====================================================================== + // VARIABLES + + let settings; + let saved; + + let lastClockCheckTime = Date.now();; + let lastClockErrorUpdateTime; + + let clockError; + let currentUpdateInterval; + let lastPpm = null; + + let debugLogFile = null; + + // ====================================================================== + // FUNCTIONS + + function clockCheck() { + let now = Date.now(); + let elapsed = now - lastClockCheckTime; + lastClockCheckTime = now; + + let prevUpdateInterval = currentUpdateInterval; + currentUpdateInterval = settings.updateInterval; + setTimeout(clockCheck, lastClockCheckTime + currentUpdateInterval - Date.now()); + + // If elapsed time differs a lot from expected, + // some other app probably used setTime to change clock significantly. + // -> reset clock error since elapsed time can't be trusted + if (Math.abs(elapsed - prevUpdateInterval) > 10 * 1000) { + // RESET CLOCK ERROR + + clockError = 0; + lastClockErrorUpdateTime = now; + + debug( + 'Looks like some other app used setTime, so reset clockError. (elapsed = ' + + elapsed.toFixed(0) + ')' + ); + WIDGETS.adjust.draw(); + + } else if (!settings.advanced) { + // UPDATE CLOCK ERROR WITHOUT TEMPERATURE COMPENSATION + + updateClockError(settings.ppm); + } else { + // UPDATE CLOCK ERROR WITH TEMPERATURE COMPENSATION + + Bangle.getPressure().then(d => { + let temp = d.temperature; + updateClockError(settings.ppm0 + settings.ppm1 * temp + settings.ppm2 * temp * temp); + }).catch(e => { + WIDGETS.adjust.draw(); + }); + } + } + + function debug(line) { + console.log(line); + if (debugLogFile !== null) { + debugLogFile.write(line + '\n'); + } + } + + function draw() { + g.reset().setFont('6x8').setFontAlign(0, 0); + g.clearRect(this.x, this.y, this.x + WIDTH - 1, this.y + 23); + g.drawString(Math.round(clockError), this.x + WIDTH/2, this.y + 9); + + if (lastPpm !== null) { + g.setFont('4x6').setFontAlign(0, 1); + g.drawString(lastPpm.toFixed(1), this.x + WIDTH/2, this.y + 23); + } + } + + function loadSettings() { + settings = Object.assign({ + advanced: false, + saveState: true, + debugLog: false, + ppm: 0, + ppm0: 0, + ppm1: 0, + ppm2: 0, + adjustThreshold: DEFAULT_ADJUST_THRESHOLD, + updateInterval: DEFAULT_UPDATE_INTERVAL, + }, require('Storage').readJSON(SETTINGS_FILE, true) || {}); + + if (settings.debugLog) { + if (debugLogFile === null) { + debugLogFile = require('Storage').open(DEBUG_LOG_FILE, 'a'); + } + } else { + debugLogFile = null; + } + + settings.updateInterval = Math.max(settings.updateInterval, MIN_INTERVAL); + } + + function onQuit() { + let now = Date.now(); + // WIP + let ppm = (lastPpm !== null) ? lastPpm : settings.ppm; + let updatedClockError = clockError + (now - lastClockErrorUpdateTime) * ppm / 1000000; + let save = false; + + if (! settings.saveState) { + debug(new Date(now).toISOString() + ' QUIT'); + + } else if (saved === undefined) { + save = true; + debug(new Date(now).toISOString() + ' QUIT & SAVE STATE'); + + } else { + let elapsedSaved = now - saved.time; + let estimatedClockError = saved.clockError + elapsedSaved * saved.ppm / 1000000; + + let clockErrorDelta = updatedClockError - estimatedClockError; + let clockErrorDeltaInPpm = clockErrorDelta / elapsedSaved * 1000000; + let ppmDelta = ppm - saved.ppm; + + let debugA = new Date(now).toISOString() + ' QUIT'; + let debugB = + '\n> ' + updatedClockError.toFixed(2) + ' - ' + estimatedClockError.toFixed(2) + ' = ' + + clockErrorDelta.toFixed(2) + ' (' + + clockErrorDeltaInPpm.toFixed(1) + ' PPM) ; ' + + ppm.toFixed(1) + ' - ' + saved.ppm.toFixed(1) + ' = ' + ppmDelta.toFixed(1); + + if ((Math.abs(clockErrorDelta) >= SAVE_STATE_CLOCK_ERROR_DELTA_THRESHOLD + && Math.abs(clockErrorDeltaInPpm) >= SAVE_STATE_CLOCK_ERROR_DELTA_IN_PPM_THRESHOLD + ) || Math.abs(ppmDelta) >= SAVE_STATE_PPM_DELTA_THRESHOLD + ) + { + save = true; + debug(debugA + ' & SAVE STATE' + debugB); + } else { + debug(debugA + debugB); + } + } + + if (save) { + require('Storage').writeJSON(STATE_FILE, { + counter: (saved === undefined) ? 1 : saved.counter + 1, + time: Math.round(now), + clockError: Math.round(updatedClockError * 1000) / 1000, + ppm: Math.round(ppm * 1000) / 1000, + }); + } + } + + function updateClockError(ppm) { + let now = Date.now(); + let elapsed = now - lastClockErrorUpdateTime; + let drift = elapsed * ppm / 1000000; + clockError += drift; + lastClockErrorUpdateTime = now; + lastPpm = ppm; + + if (Math.abs(clockError) >= settings.adjustThreshold) { + let now = Date.now(); + // Shorter variables are faster to look up and this part is time sensitive. + let e = clockError / 1000; + setTime(getTime() - e); + debug( + new Date(now).toISOString() + ' -> ' + ((now / 1000 - e) % 60).toFixed(3) + + ' SET TIME (' + clockError.toFixed(2) + ')' + ); + clockError = 0; + } + + WIDGETS.adjust.draw(); + } + + // ====================================================================== + // MAIN + + loadSettings(); + + WIDGETS.adjust = { + area: 'tr', + draw: draw, + now: () => { + let now = Date.now(); + // WIP + let ppm = (lastPpm !== null) ? lastPpm : settings.ppm; + let updatedClockError = clockError + (now - lastClockErrorUpdateTime) * ppm / 1000000; + return now - updatedClockError; + }, + width: WIDTH, + }; + + if (settings.saveState) { + saved = require('Storage').readJSON(STATE_FILE, true); + } + + let now = Date.now(); + lastClockErrorUpdateTime = now; + if (saved === undefined) { + clockError = 0; + debug(new Date().toISOString() + ' START'); + } else { + clockError = saved.clockError + (now - saved.time) * saved.ppm / 1000000; + + if (Math.abs(clockError) <= MAX_CLOCK_ERROR_FROM_SAVED_STATE) { + debug( + new Date().toISOString() + ' START & LOAD STATE (' + + clockError.toFixed(2) + ')' + ); + } else { + debug( + new Date().toISOString() + ' START & IGNORE STATE (' + + clockError.toFixed(2) + ')' + ); + clockError = 0; + } + } + + clockCheck(); + + E.on('kill', onQuit); + +})() From 76363b8dc6c860f125c0e2e1c76c51f8de786ccd Mon Sep 17 00:00:00 2001 From: Markus Laire Date: Fri, 25 Feb 2022 18:43:48 +0200 Subject: [PATCH 176/199] widadjust: add icon --- apps/widadjust/README.md | 5 +++++ apps/widadjust/icon.png | Bin 0 -> 1430 bytes apps/widadjust/metadata.json | 1 + 3 files changed, 6 insertions(+) create mode 100644 apps/widadjust/icon.png diff --git a/apps/widadjust/README.md b/apps/widadjust/README.md index 1b51440f5..4f89af54b 100644 --- a/apps/widadjust/README.md +++ b/apps/widadjust/README.md @@ -50,3 +50,8 @@ function adjustedNow() { return WIDGETS.adjust ? WIDGETS.adjust.now() : Date.now(); } ``` + +## Acknowledgment + +Uses [Clock Settings](https://icons8.com/icon/tQvI71EfIWy3/clock-settings) +icon by [Icons8](https://icons8.com). diff --git a/apps/widadjust/icon.png b/apps/widadjust/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f97394618038813954dd332a92bcec1d7eb2a620 GIT binary patch literal 1430 zcmV;H1!?+;P)ZCf45&BTELc~!J-LK5hZlhsKHPXAqokP7!wyL z#ZaRmEQp$Fal^)ilCY4tP*O1_KB5URnh-VwG>Q>HN=&VfY84CwdhrFRTH0Ga7w1f7 z?$`VH9@DP;CzE@>nKNh3nK@_X%o+F}7169^%8>KKXCAN;SO&BKw*j*wG=BhtKtJ#) za0oc(Y5Y{E2Q~qRfe9dV$~ce*hP33h&ZU_^l;{NNrc>|$*b4mW2y-5I9oPumjwlyJ zJ+Me=_5#CB|I@%0&}!SFi)w0n^>f*kNPa9IcX3b;E) zznipFLkG~Oye|XW@aLb@0&ghuF`%3HOMMnN6O%Roda%CIn_!%>s0BVyhQq*;g#G{4 zk_1Z;rw@UBWKbf9o%vJ1ttoh&I>uHcy0e}U_?iM0GkqCDn z&NN1HvvH9{0T6Q<14c=(I|bMsp*zFikX-=~$2L1(EPvRVv_l2>P$0mbJx^96uE(CR zarXIY@Sy;}J=o2pV%V_>d&2sFF9kqit`G@DsuHd7G^kGn)>CD2=OGc|dD6u;rQlP6 zI%G?q0Op#?8i!z|e(whgo(A=aao_+V;|f#hDzHp{Kb}URlH#!bE;kjf0&V(xV%o$> z4kO#*QjNbO%T($zk_MX*Q!Ef;|Bi_U<#!?4Py<{+B2FLJO!4(G1fKB3+c>goJzS%M z{N!nnBTQD{s3+b-%5N4#wD5>he0|-pOn8%X2O7cADkGYa6^)|T18;z95m`r~4Zo4y ziJO7rIzT`08So|X?SD3Kvs30o+Uv0?n@RXW2VRs^YDE(wtjR94q~NiKV!wI21kGJ# z>ggp$uv7-_%pW6OIxz>Vrr0-*Dvxim6JZbl_v`OWm*J0uZbFT2mQwVR$FtUY*!1qemuit}+f4cN#l`vVd zwJ{ZVIic_Xs~kbrA@*#(2Y|y!eIO}`ZeSNhfyfKd%*bIp|Tpt16LJr-6ww1*;Y-(|# zM+F9fTPQxj9@Dnnkv<=3{c@-7Y9!5ai7E=@u&48BvMXT}Fy#_9=h==`&IE!tASP1) zuGhMqh*h|JDk4Da)T~4nbD9Y}hh)5skNt>UiFdT_EHd-P-gjyHEZ`#cuzMGHHqO8S zb|uCU$IiMt)gTWaA@G3KH3F|-A2>#V7qHQBx7L51X22Y>+~$etBw~kY(Sd|5W5~Ok zizeiua7LuQ3mbN{k`nFMF zfMgj?VHL>(Zz8$X#U%s*YYHo{@5((Czk23@r<86dVn(Lz2=J2geQ#O?4C;VKk=cko zbQh2aatPVMMiARJn?P5j&w%o|g0=B8PTRQ%|E%v8lQ0)KWcDDZ?S;sIW_I7lE`1l` z11}<{EWpo5cwz3ne Date: Fri, 25 Feb 2022 18:49:13 +0200 Subject: [PATCH 177/199] fix(widadjust): remove extra semicolon --- apps/widadjust/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widadjust/widget.js b/apps/widadjust/widget.js index ce1fee022..138833783 100644 --- a/apps/widadjust/widget.js +++ b/apps/widadjust/widget.js @@ -25,7 +25,7 @@ let settings; let saved; - let lastClockCheckTime = Date.now();; + let lastClockCheckTime = Date.now(); let lastClockErrorUpdateTime; let clockError; From b7035afa2f6790636766d2235fa8574007ac3d8c Mon Sep 17 00:00:00 2001 From: Andreas Holley Date: Fri, 25 Feb 2022 21:10:11 +0000 Subject: [PATCH 178/199] Fix Daisy Clock `"type": "clock"` was missing from metadata.json so the app couldn't be set as the clock through settings --- apps/daisy/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index c35bfefa3..1fd95806d 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -4,6 +4,7 @@ "dependencies": {"mylocation":"app"}, "description": "A clock based on the Pastel clock with large ring guage for steps", "icon": "app.png", + "type": "clock", "tags": "clock", "supports" : ["BANGLEJS2"], "screenshots": [{"url":"screenshot_daisy2.jpg"}], From 1af14f3f2c9d7f76c09f38e273e0045eda3366a6 Mon Sep 17 00:00:00 2001 From: copoer Date: Fri, 25 Feb 2022 17:11:08 -0400 Subject: [PATCH 179/199] Updated to use suggested function --- apps/contourclock/ChangeLog | 2 +- apps/contourclock/lib.js | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/contourclock/ChangeLog b/apps/contourclock/ChangeLog index aed7baf64..032edc9b5 100644 --- a/apps/contourclock/ChangeLog +++ b/apps/contourclock/ChangeLog @@ -5,4 +5,4 @@ 0.23: Customizer! Unused fonts no longer take up precious memory. 0.24: Added previews to the customizer. 0.25: Fixed a bug that would let widgets change the color of the clock. -0.26: Time now works with locale formatting +0.26: Time formatted to locale diff --git a/apps/contourclock/lib.js b/apps/contourclock/lib.js index aa83fca26..c4f927953 100644 --- a/apps/contourclock/lib.js +++ b/apps/contourclock/lib.js @@ -1,3 +1,11 @@ +var is12; +function getHours(d) { + var h = d.getHours(); + if (is12===undefined) is12 = (require('Storage').readJSON('setting.json',1)||{})["12hour"]; + if (!is12) return h; + return (h%12==0) ? 12 : h%12; +} + exports.drawClock = function(fontIndex) { var digits = []; fontFile=require("Storage").read("contourclock-"+Math.abs(parseInt(fontIndex+0.5))+".json"); @@ -13,15 +21,13 @@ exports.drawClock = function(fontIndex) { if (n!=10) return (false); //font file seems to be invalid var x=0; var y = g.getHeight()/2-digits[0].height/2; - var date = require('locale').time(new Date(),1); - var hours = date.split(":")[0]; - var minutes = date.split(":")[1]; + var date = new Date(); g.clearRect(0,38,g.getWidth()-1,138); - d1=parseInt(hours/10); - d2=parseInt(hours%10); + d1=parseInt(getHours(date)/10); + d2=parseInt(getHours(date)%10); d3=10; - d4=parseInt(minutes/10); - d5=parseInt(minutes%10); + d4=parseInt(date.getMinutes()/10); + d5=parseInt(date.getMinutes()%10); w1=digits[d1].width; w2=digits[d2].width; w3=digits[d3].width; From b31bc88351d69d2b5ceadfd6d89f103eb983be06 Mon Sep 17 00:00:00 2001 From: Andreas Holley Date: Fri, 25 Feb 2022 21:11:59 +0000 Subject: [PATCH 180/199] Bump version --- apps/daisy/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index 1fd95806d..f4a9fcbbe 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -1,6 +1,6 @@ { "id": "daisy", "name": "Daisy", - "version":"0.02", + "version":"0.03", "dependencies": {"mylocation":"app"}, "description": "A clock based on the Pastel clock with large ring guage for steps", "icon": "app.png", From faf7cb8d6c815ab8ac2a2e0821429ba2fff3fcc2 Mon Sep 17 00:00:00 2001 From: Andreas Holley Date: Fri, 25 Feb 2022 21:13:17 +0000 Subject: [PATCH 181/199] Update changelog --- apps/daisy/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/daisy/ChangeLog b/apps/daisy/ChangeLog index 4fdf333e4..254124d4e 100644 --- a/apps/daisy/ChangeLog +++ b/apps/daisy/ChangeLog @@ -1,2 +1,3 @@ 0.01: first release 0.02: added settings menu to change color +0.03: fix metadata.json to allow setting as clock From fc740bbb1ce4f3d6011ffab1e5b665d547623207 Mon Sep 17 00:00:00 2001 From: copoer Date: Fri, 25 Feb 2022 17:14:20 -0400 Subject: [PATCH 182/199] Added version --- apps/contourclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contourclock/metadata.json b/apps/contourclock/metadata.json index 54d799127..ec29c390b 100644 --- a/apps/contourclock/metadata.json +++ b/apps/contourclock/metadata.json @@ -1,7 +1,7 @@ { "id": "contourclock", "name": "Contour Clock", "shortName" : "Contour Clock", - "version":"0.25", + "version":"0.26", "icon": "app.png", "description": "A Minimalist clockface with large Digits. Now with more fonts!", "screenshots" : [{"url":"cc-screenshot-1.png"},{"url":"cc-screenshot-2.png"}], From f2f2a271ec6b29cb7748fb4f02a083cb78832681 Mon Sep 17 00:00:00 2001 From: tjsilver Date: Sat, 26 Feb 2022 14:56:05 +0000 Subject: [PATCH 183/199] fix typo in Time and Life shortName --- apps/timeandlife/metadata.json | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/timeandlife/metadata.json b/apps/timeandlife/metadata.json index 86800f16f..acd6b0086 100644 --- a/apps/timeandlife/metadata.json +++ b/apps/timeandlife/metadata.json @@ -1,18 +1,26 @@ { "id": "timeandlife", "name": "Time and Life", - "shortName":"Time and Lfie", + "shortName": "Time and Life", "icon": "app.png", - "version":"0.01", + "version": "0.01", "description": "A simple watchface which displays the time when the screen is tapped and decay according to the rules of Conway's game of life.", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS2"], - "allow_emulator":true, + "supports": [ + "BANGLEJS2" + ], + "allow_emulator": true, "readme": "README.md", "storage": [ - {"name":"timeandlife.app.js","url":"app.js"}, - {"name":"timeandlife.img","url":"app-icon.js","evaluate":true} + { + "name": "timeandlife.app.js", + "url": "app.js" + }, + { + "name": "timeandlife.img", + "url": "app-icon.js", + "evaluate": true + } ] -} - +} \ No newline at end of file From d09e3c2ce13e69548cfc667fd5baba0a50a263fc Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sat, 26 Feb 2022 19:45:35 +0100 Subject: [PATCH 184/199] Use Bangle.appRect --- apps/terminalclock/app.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/terminalclock/app.js b/apps/terminalclock/app.js index fb7bd16cc..012aab5d5 100644 --- a/apps/terminalclock/app.js +++ b/apps/terminalclock/app.js @@ -1,6 +1,5 @@ -var locale = require("locale"); +​var locale = require("locale"); var fontColor = g.theme.dark ? "#0f0" : "#000"; -var startY = 24; var paddingY = 2; var font6x8At4Size = 32; var font6x8At2Size = 18; @@ -15,25 +14,25 @@ function setFontSize(pos){ } function clearField(pos){ - var yStartPos = startY + + var yStartPos = Bangle.appRect.y + paddingY * (pos - 1) + font6x8At4Size * Math.min(1, pos-1) + font6x8At2Size * Math.max(0, pos-2); - var yEndPos = startY + + var yEndPos = Bangle.appRect.y + paddingY * (pos - 1) + font6x8At4Size * Math.min(1, pos) + font6x8At2Size * Math.max(0, pos-1); - g.clearRect(0, yStartPos, 240, yEndPos); + g.clearRect(Bangle.appRect.x, yStartPos, Bangle.appRect.x2, yEndPos); } function clearWatchIfNeeded(now){ if(now.getMinutes() % 10 == 0) - g.clearRect(0, startY, 240, 240); + g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); } function drawLine(line, pos){ setFontSize(pos); - var yPos = startY + + var yPos = Bangle.appRect.y + paddingY * (pos - 1) + font6x8At4Size * Math.min(1, pos-1) + font6x8At2Size * Math.max(0, pos-2); @@ -127,12 +126,12 @@ var settings = Object.assign({ showActivity: true, showStepCount: true, }, require('Storage').readJSON("terminalclock.json", true) || {}); -// draw immediately at first -draw(); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); +// draw immediately at first +draw(); var secondInterval = setInterval(draw, 10000); From 31277cd20a802bab3cbb448ba3e27ca559a36007 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sat, 26 Feb 2022 19:51:43 +0100 Subject: [PATCH 185/199] Replace 'Activity' with 'Motion' to be able to display motion true values --- apps/terminalclock/app.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/terminalclock/app.js b/apps/terminalclock/app.js index 012aab5d5..ab83a696f 100644 --- a/apps/terminalclock/app.js +++ b/apps/terminalclock/app.js @@ -1,4 +1,4 @@ -​var locale = require("locale"); +var locale = require("locale"); var fontColor = g.theme.dark ? "#0f0" : "#000"; var paddingY = 2; var font6x8At4Size = 32; @@ -75,11 +75,10 @@ function drawHRM(pos){ function drawActivity(pos){ clearField(pos); var health = Bangle.getHealthStatus('last'); - var steps_formated = ">Activity: " + parseInt(health.movement/10); + var steps_formated = ">Motion: " + parseInt(health.movement); drawLine(steps_formated, pos); } - function draw(){ var curPos = 1; g.reset(); @@ -108,7 +107,6 @@ function draw(){ drawInput(now, curPos); } - Bangle.on('HRM',function(hrmInfo) { if(hrmInfo.confidence >= settings.HRMinConfidence) heartRate = hrmInfo.bpm; From 35cad73a9c742b3093590053a12f8ef95d1e0c2a Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sat, 26 Feb 2022 20:01:53 +0100 Subject: [PATCH 186/199] Update terminalclock version --- apps/terminalclock/ChangeLog | 1 + apps/terminalclock/README.md | 2 +- apps/terminalclock/screenshot1.png | Bin 2938 -> 2878 bytes apps/terminalclock/screenshot2.png | Bin 3072 -> 2935 bytes 4 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/terminalclock/ChangeLog b/apps/terminalclock/ChangeLog index 5560f00bc..6515ab627 100644 --- a/apps/terminalclock/ChangeLog +++ b/apps/terminalclock/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Rename "Activity" in "Motion" and display the true values for it diff --git a/apps/terminalclock/README.md b/apps/terminalclock/README.md index 2a2bc1204..5a54583d2 100644 --- a/apps/terminalclock/README.md +++ b/apps/terminalclock/README.md @@ -5,5 +5,5 @@ It can display : - time - date - hrm -- activity +- motion - steps diff --git a/apps/terminalclock/screenshot1.png b/apps/terminalclock/screenshot1.png index a0d41f4957fa8bd96572d2e126ed2aba38d68250..c0f472102e693991580127d67665cf9774a69440 100644 GIT binary patch literal 2878 zcmd5;_gjxZnP8pXdGw_lI-lIWzM-bLPxD@0nZ|EJj*FLjnK* z>66Y5Zjhw>v&2!*-az{+01~iRH;g?{&(xX$0Evy04#(XS0_KZYk7oBtWf3QK%FlEX z3dXWbO4Lu{oq2vLy1A@^j7Hi-U|?Wc$JT%Zfy|)6#+zfXLJSPiW+t8{s#`;BZg1ON z_}CdVuX;p!>4}fS8#PX6U)*jH(nx{8m&xBq#+FPkihCy3)f_9fL%{VBe%vOkfqxWA5t%SZbT$LSU&HXIbjcJ*2%1WsEqHqeKk3V=KdXcfxN`ie#79 z^PU`n=~VKP=DZKmON^MmZ=RH&4LEXn5k>GZfE4H70~RM1rb8NTU+4g&xyvWt5R89b z>-*4=yJ|Aps)hUcm)P#)Ea364TNMXpYxbq#EIGo)OB7uhyU z$9>6w79Lb{eQZ@R>Dp{cP4?|ym`s#fZo=w@2jF=rj+I#8f};Ce5k4k^uo44WChi~} ztW~CV)<~#vYGN$CsBp;a`ak9OSI~nAz)Z{;Yv@kjZ6Plyw^`$-@LM! zneCmDaW1(XwfL5`t5QlT>Rhj+Uq0`+GYh?Ox{i>(P+|zk{n}q|sPvO`8+MFgfgOY8 zG3(g2%iihZmpiUM^pX9`ws!wYsoD<<3heVa=p@9rg>n~<**-S>7|Wr<#=ooBZzEmO z-RH&NHLb@OsEzd>kNMfIH3yqbp#uV_7v=VL7+fwtfj*I+vsEq=LkkEOu{ZamNW5*4 z@oTqJ)^EnU8<}XYK4F92hji3A)9@tK1svM=k*egyqdU{> z<~{|F3c@FnGly#*@B^u#vp<80DU#(GrWWVimq5VqY{jM~Cw8hbNg}Sz#-75U#J8g- zMCm(~bC&fB@Ep^|!$^+ZEf%J=?5}@3P&F#Vr;(@Lrsts^&ksGV|L?yWKO=yp_d>`T=(7@?X6h$K0YjcZKYZ})Y9m2TC*NmgiC&b zMbRsj4knnCiR&Z2I=uptpYbkR%B<+$`x3mm1k$6simo-K4iQ04RPU!;;0W=$BomZxiKVb6VRns0SV zx8%?rfHPFMp0W``k4;_t4%P0vf+fQls;_h0d@>!5N}zYi7`ed^R&M@6?RvX@6OGpU zGbwo$9SpU@Zzq7cTEDxpNpG(5lC=!*;K1Hr8FEE9sql`g*W&R%ubW$F<5ZtNh-g2^Hi@imdz%c;ZCr21# z5%MzlD}oc~Mxx{qVcyumJCAG)OjmMv$weNJ2a!XT4goI$&$G1{)w}uh@QHebeox$S zk;e|w^^4F+fHM1-j^j*-KV;vZywv>sQuB-7roHh65CzIzL3a-JQjPrTPg{TDVh z6iS%Mj$N?b5t?1ekNl&K(F8q3$SH1@8dA!r^7iHX(3K2*HTL)DQ&bt#Nc+fcR$^Yp zixwOVL8{%7DZ!QTG^FFqjxy^j`eZdDJuN+|#8fxtT6<%b0hb<`v~<&JFcn{dr-wmGy;4ov?4V(>;zsWKPn+JZ28k8A)4v zA3NcW))mgCslSojO55`#UEYq2 zCtF`H$hy{J%xLJlpcCL)4CiVwY5{O%dKbv6;gYwf^|JW3k2^ICfqjnQ`R=mms{jhFKjJuGQJ-7rb5`O~yAb)q&M`?;U=R z%a`{N2~@^3A!+0B(}G87uRD0Sm_0BEkLpONC@1TIc7ND{?tGhN5d)jeGJ7Z9+<= zp$EK4odbq_s;agl3nImgUhZbsQx^-t0M?7uVb3RT+v;|Xr7Ed4D~@9SOx4SnOI~}I zDm?OAfnqz4B*{8Rhjlm&1C@ucqKN||=>v?y*n+{98mI?N%1RRp#UifiUc; zFfpP*nSbTCKWc(}(-k4kZ~QOkx517fe4#&`cDVG8DdPhE5^{W19yklRH2>&On91zqNZN}D-Kcz6I<^tBAdrVXY#PhkmRDrdo21}dSk z$-MXkOa@O3P<&nuF%avu*&!?}urk_WB-|Bh)QYRoK1J}zzIWHSWx9OZ-!4v~c@f_^2M5JPx-YJRo{H$Zl@<|1j?W?;^!dr?pZ(LIW{y M(h=)WZ;#LT50cG;Bme*a literal 2938 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 diff --git a/apps/terminalclock/screenshot2.png b/apps/terminalclock/screenshot2.png index 21d7aadbf31906cf0316459a9b21bc3ae32e0bc8..8bd552a730e49cc84db62211d36b351a26ee6b60 100644 GIT binary patch literal 2935 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 literal 3072 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 jM6c{|gUSB|JP8lDilHZiwbMjjdf Date: Sun, 27 Feb 2022 12:15:35 +0100 Subject: [PATCH 187/199] Better usage of available space --- apps/circlesclock/app.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index d5df2fe44..a6aa1a8b1 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -52,7 +52,7 @@ const colorGreen = '#008000'; const colorBlue = '#0000ff'; const colorYellow = '#ffff00'; const widgetOffset = showWidgets ? 24 : 0; -const dowOffset = circleCount == 3 ? 22 : 24; // dow offset relative to date +const dowOffset = circleCount == 3 ? 20 : 22; // dow offset relative to date const h = g.getHeight() - widgetOffset; const w = g.getWidth(); const hOffset = (circleCount == 3 ? 34 : 30) - widgetOffset; @@ -88,21 +88,24 @@ const circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12"; const iconOffset = circleCount == 3 ? 6 : 8; const defaultCircleTypes = ["steps", "hr", "battery", "weather"]; +function hideWidgets() { + /* + * 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. + */ + if (WIDGETS && typeof WIDGETS === "object") { + for (let wd of WIDGETS) { + wd.draw = () => {}; + wd.area = ""; + } + } +} function draw() { g.clear(true); if (!showWidgets) { - /* - * 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. - */ - if (WIDGETS && typeof WIDGETS === "object") { - for (let wd of WIDGETS) { - wd.draw = () => {}; - wd.area = ""; - } - } + hideWidgets(); } else { Bangle.drawWidgets(); } @@ -114,7 +117,7 @@ function draw() { g.setFontRobotoRegular50NumericOnly(); g.setFontAlign(0, -1); g.setColor(colorFg); - g.drawString(locale.time(new Date(), 1), w / 2, h1 + 8); + g.drawString(locale.time(new Date(), 1), w / 2, h1 + 6); now = Math.round(new Date().getTime() / 1000); // date & dow @@ -840,7 +843,6 @@ if (isCircleEnabled("hr")) { enableHRMSensor(); } - Bangle.setUI("clock"); Bangle.loadWidgets(); From 73aac6feabb7fe06c0f0447370588c8b9f7473ba Mon Sep 17 00:00:00 2001 From: copoer Date: Sun, 27 Feb 2022 09:36:36 -0400 Subject: [PATCH 188/199] Updated Edisons ball app to work on Bangle JS 2 --- apps/edisonsball/ChangeLog | 2 ++ apps/edisonsball/README.md | 2 +- apps/edisonsball/app.js | 21 +++++++++++++++++---- apps/edisonsball/metadata.json | 6 +++--- 4 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 apps/edisonsball/ChangeLog diff --git a/apps/edisonsball/ChangeLog b/apps/edisonsball/ChangeLog new file mode 100644 index 000000000..b71b8bb0d --- /dev/null +++ b/apps/edisonsball/ChangeLog @@ -0,0 +1,2 @@ +0.01: Initial version +0.02: Added BangleJS Two diff --git a/apps/edisonsball/README.md b/apps/edisonsball/README.md index b8e9ec106..a3b013b6d 100644 --- a/apps/edisonsball/README.md +++ b/apps/edisonsball/README.md @@ -1,4 +1,4 @@ -The application is based on a technique that Thomas Edison used to prevent falling asleep using a steel ball. Essentially the app starts with a display that shows the current HR value that the watch alarm is set to and this can be adjusted with buttons 1 and 3. This HR settng should be the approximate value you want the alarm to trigger and so you should ideally know both what your HR is currently and what your heartrate normally is during sleep. For your current HR according to the watch, you can simply use the HR monitor available in the Espruino app loader, and then from that you can choose a lower value as the target for the alarm and adjust as required. +The application is based on a technique that Thomas Edison used to prevent falling asleep using a steel ball. Essentially the app starts with a display that shows the current HR value that the watch alarm is set to and this can be adjusted with buttons 1 and 3 (Mapped to top touch and bottom touch on Bangle 2). This HR settng should be the approximate value you want the alarm to trigger and so you should ideally know both what your HR is currently and what your heartrate normally is during sleep. For your current HR according to the watch, you can simply use the HR monitor available in the Espruino app loader, and then from that you can choose a lower value as the target for the alarm and adjust as required. When you press the middle button on the side, the HR monitor starts, the alarm will trigger when your heart rate average drops to the limit you’ve set and has a certain level of steadiness that is determined by a assessing the variance over several readings - the sensitivity of this variance can be adjusted in a variable in the app's code under 'ADVANCED SETTINGS' if needed. The code also has a basic logging function which shows, in a CSV file, when you started the HR tracker and when the alarm was triggered. diff --git a/apps/edisonsball/app.js b/apps/edisonsball/app.js index 557155c9a..ab5def2f6 100644 --- a/apps/edisonsball/app.js +++ b/apps/edisonsball/app.js @@ -130,10 +130,23 @@ function checkHR() { } update_target_HR(); - -setWatch(btn1Pressed, BTN1, {repeat:true}); -setWatch(btn2Pressed, BTN2, {repeat:true}); -setWatch(btn3Pressed, BTN3, {repeat:true}); +if (process.env.HWVERSION==1) { + // Bangle 1 + setWatch(btn1Pressed, BTN1, {repeat:true}); + setWatch(btn2Pressed, BTN2, {repeat:true}); + setWatch(btn3Pressed, BTN3, {repeat:true}); +} else { + setWatch(btn2Pressed, BTN2, { repeat: true }); + // Bangle 2 + Bangle.on('touch', function(zone, e) { + if (e.y < g.getHeight() / 2) { + btn1Pressed(); + } + if (e.y > g.getHeight() / 2) { + btn3Pressed(); + } + }); +} Bangle.on('HRM',function(hrm) { diff --git a/apps/edisonsball/metadata.json b/apps/edisonsball/metadata.json index f429c7b67..dfeb4451e 100644 --- a/apps/edisonsball/metadata.json +++ b/apps/edisonsball/metadata.json @@ -2,11 +2,11 @@ "id": "edisonsball", "name": "Edison's Ball", "shortName": "Edison's Ball", - "version": "0.01", + "version": "0.02", "description": "Hypnagogia/Micro-Sleep alarm for experimental use in exploring sleep transition and combating drowsiness", "icon": "app-icon.png", - "tags": "", - "supports": ["BANGLEJS"], + "tags": "sleep,hyponagogia,quick,nap", + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"edisonsball.app.js","url":"app.js"}, From 505872f0b84c86a4e45051a5625c11d7cbd6745c Mon Sep 17 00:00:00 2001 From: copoer Date: Sun, 27 Feb 2022 10:10:28 -0400 Subject: [PATCH 189/199] Fixed graphics --- apps/edisonsball/app.js | 66 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/apps/edisonsball/app.js b/apps/edisonsball/app.js index ab5def2f6..c0a4d27c6 100644 --- a/apps/edisonsball/app.js +++ b/apps/edisonsball/app.js @@ -3,6 +3,8 @@ var lower_limit_BPM = 49; var upper_limit_BPM = 140; var deviation_threshold = 3; +var ISBANGLEJS1 = process.env.HWVERSION==1; + var target_heartrate = 70; var heartrate_set; @@ -33,25 +35,39 @@ function btn2Pressed() { } function update_target_HR(){ - g.clear(); - g.setColor("#00ff7f"); - g.setFont("6x8", 4); - g.setFontAlign(0,0); // center font + if (process.env.HWVERSION==1) { + g.setColor("#00ff7f"); + g.setFont("6x8", 4); + g.setFontAlign(0,0); // center font - g.drawString(target_heartrate, 120,120); - g.setFont("6x8", 2); - g.setFontAlign(-1,-1); - g.drawString("-", 220, 200); - g.drawString("+", 220, 40); - g.drawString("GO", 210, 120); - - g.setColor("#ffffff"); - g.setFontAlign(0,0); // center font - g.drawString("target HR", 120,90); - - g.setFont("6x8", 1); - g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 120,170); + g.drawString(target_heartrate, 120,120); + g.setFont("6x8", 2); + g.setFontAlign(-1,-1); + g.drawString("-", 220, 200); + g.drawString("+", 220, 40); + g.drawString("GO", 210, 120); + + g.setColor("#ffffff"); + g.setFontAlign(0,0); // center font + g.drawString("target HR", 120,90); + + g.setFont("6x8", 1); + g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 120,170); + } else { + g.setFont("6x8", 4); + g.setFontAlign(0,0); // center font + g.drawString(target_heartrate, 88,88); + g.setFont("6x8", 2); + g.setFontAlign(-1,-1); + g.drawString("-", 160, 160); + g.drawString("+", 160, 10); + g.drawString("GO", 150, 88); + g.setFontAlign(0,0); // center font + g.drawString("target HR", 88,120); + g.setFont("6x8", 1); + g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 88,150); + } g.setFont("6x8",3); g.flip(); @@ -105,8 +121,13 @@ function checkHR() { average_HR = average(HR_samples).toFixed(0); stdev_HR = getStandardDeviation (HR_samples).toFixed(1); - g.drawString("HR: " + average_HR, 120,100); - g.drawString("STDEV: " + stdev_HR, 120,160); + if (ISBANGLEJS1) { + g.drawString("HR: " + average_HR, 120,100); + g.drawString("STDEV: " + stdev_HR, 120,160); + } else { + g.drawString("HR: " + average_HR, 60,70); + g.drawString("STDEV: " + stdev_HR, 80,70); + } HR_samples = []; if(average_HR < target_heartrate && stdev_HR < deviation_threshold){ @@ -130,14 +151,15 @@ function checkHR() { } update_target_HR(); -if (process.env.HWVERSION==1) { + +if (ISBANGLEJS1) { // Bangle 1 setWatch(btn1Pressed, BTN1, {repeat:true}); setWatch(btn2Pressed, BTN2, {repeat:true}); setWatch(btn3Pressed, BTN3, {repeat:true}); } else { - setWatch(btn2Pressed, BTN2, { repeat: true }); // Bangle 2 + setWatch(btn2Pressed, BTN1, { repeat: true }); Bangle.on('touch', function(zone, e) { if (e.y < g.getHeight() / 2) { btn1Pressed(); @@ -148,8 +170,8 @@ if (process.env.HWVERSION==1) { }); } -Bangle.on('HRM',function(hrm) { +Bangle.on('HRM',function(hrm) { if(trigger_count < 2){ if (firstBPM) firstBPM=false; // ignore the first one as it's usually rubbish From 866cfb8c6bbb3aa82e919108e724f33f5cd7ed61 Mon Sep 17 00:00:00 2001 From: copoer Date: Sun, 27 Feb 2022 10:13:07 -0400 Subject: [PATCH 190/199] Fixed graphics --- apps/edisonsball/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edisonsball/app.js b/apps/edisonsball/app.js index c0a4d27c6..a600d8fc8 100644 --- a/apps/edisonsball/app.js +++ b/apps/edisonsball/app.js @@ -64,7 +64,7 @@ function update_target_HR(){ g.drawString("+", 160, 10); g.drawString("GO", 150, 88); g.setFontAlign(0,0); // center font - g.drawString("target HR", 88,120); + g.drawString("target HR", 88,70); g.setFont("6x8", 1); g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 88,150); } From 21dc7a074db98c9b8bfabde67873316ba863771a Mon Sep 17 00:00:00 2001 From: copoer Date: Sun, 27 Feb 2022 10:19:07 -0400 Subject: [PATCH 191/199] Fixed graphics --- apps/edisonsball/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/edisonsball/app.js b/apps/edisonsball/app.js index a600d8fc8..2aa317829 100644 --- a/apps/edisonsball/app.js +++ b/apps/edisonsball/app.js @@ -64,7 +64,7 @@ function update_target_HR(){ g.drawString("+", 160, 10); g.drawString("GO", 150, 88); g.setFontAlign(0,0); // center font - g.drawString("target HR", 88,70); + g.drawString("target HR", 88,65); g.setFont("6x8", 1); g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 88,150); } @@ -125,8 +125,8 @@ function checkHR() { g.drawString("HR: " + average_HR, 120,100); g.drawString("STDEV: " + stdev_HR, 120,160); } else { - g.drawString("HR: " + average_HR, 60,70); - g.drawString("STDEV: " + stdev_HR, 80,70); + g.drawString("HR: " + average_HR, 88,60); + g.drawString("STDEV: " + stdev_HR, 88,90); } HR_samples = []; if(average_HR < target_heartrate && stdev_HR < deviation_threshold){ From 8513f34f2ac81550b4c1dbd8211fd986fc900202 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sun, 27 Feb 2022 18:23:47 +0100 Subject: [PATCH 192/199] Update changelog for v0.11 --- apps/circlesclock/ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 7165f8521..46eddd32b 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -20,3 +20,6 @@ Color depending on value (green -> red, red -> green) option Good HRM value will not be overwritten so fast anymore 0.10: Use roboto font for time, date and day of week and center align them +0.11: New color option: foreground color + Improve performance, reduce memory usage + Small optical adjustments From 4cff0792f604e19b710605d9cc4d3507c42eeee2 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 16 Feb 2022 22:44:36 +0100 Subject: [PATCH 193/199] Buzz on every measurement and longer if all are done --- apps/bthrv/ChangeLog | 1 + apps/bthrv/app.js | 6 +++++- apps/bthrv/metadata.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/bthrv/ChangeLog b/apps/bthrv/ChangeLog index e144fd8f9..eefadac78 100644 --- a/apps/bthrv/ChangeLog +++ b/apps/bthrv/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Write available data on reset or kill +0.03: Buzz short on every finished measurement and longer if all are done diff --git a/apps/bthrv/app.js b/apps/bthrv/app.js index 067c84f56..fbd0e2d05 100644 --- a/apps/bthrv/app.js +++ b/apps/bthrv/app.js @@ -75,7 +75,6 @@ function write(){ data += "," + rrMax + "," + rrMin + ","+rrNumberOfValues; data += "\n"; file.write(data); - Bangle.buzz(500); } function onBtHrm(e) { @@ -87,6 +86,11 @@ function onBtHrm(e) { if (currentSlot <= hrvSlots.length && (Date.now() - startingTime) > (hrvSlots[currentSlot] * 1000) && !hrvValues[hrvSlots[currentSlot]]){ hrvValues[hrvSlots[currentSlot]] = hrv; currentSlot++; + if (currentSlot == hrvSlots.length){ + Bangle.buzz(500) + } else { + Bangle.buzz(50); + } } } diff --git a/apps/bthrv/metadata.json b/apps/bthrv/metadata.json index 183008034..7c57be682 100644 --- a/apps/bthrv/metadata.json +++ b/apps/bthrv/metadata.json @@ -2,7 +2,7 @@ "id": "bthrv", "name": "Bluetooth Heart Rate variance calculator", "shortName": "BT HRV", - "version": "0.02", + "version": "0.03", "description": "Calculates HRV from a a BT HRM with interval data", "icon": "app.png", "type": "app", From 48d8fae37c04b19dfae172316b4a721e7c881463 Mon Sep 17 00:00:00 2001 From: DC959 Date: Mon, 28 Feb 2022 22:07:33 +1300 Subject: [PATCH 194/199] Fix date alignment and change font to closer match Rolex --- apps/rolex/ChangeLog | 3 ++- apps/rolex/README.md | 4 +++- apps/rolex/app.js | 17 +++++++++++------ apps/rolex/app.js:Zone.Identifier | 3 +++ apps/rolex/screenshot1.png | Bin 0 -> 3905 bytes apps/rolex/screenshot1.png:Zone.Identifier | 3 +++ 6 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 apps/rolex/app.js:Zone.Identifier create mode 100644 apps/rolex/screenshot1.png create mode 100644 apps/rolex/screenshot1.png:Zone.Identifier diff --git a/apps/rolex/ChangeLog b/apps/rolex/ChangeLog index 3bfed4a4e..a1e2cee0a 100644 --- a/apps/rolex/ChangeLog +++ b/apps/rolex/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial Release 0.02: Minor tweaks for light theme -0.03: Made images 2 bit and fixed theme honoring \ No newline at end of file +0.03: Made images 2 bit and fixed theme honoring +0.04: Fixed date font alignment and changed date font to match a real Rolex diff --git a/apps/rolex/README.md b/apps/rolex/README.md index 4c24aad0c..5339f1d0e 100644 --- a/apps/rolex/README.md +++ b/apps/rolex/README.md @@ -1,11 +1,13 @@ # Rolex -![](screenshot.png) +![](screenshot.png) ![](screenshot1.png) Created with the aid of the Espruino documentation and looking through many of the wonderful exising watchfaces that have been made. This has not been tested on a watch yet as I haven't aquired one but has been tested in the emulator. The hands don't rotate dead on center but they're as close as I could get them to. +Colour switches based on watch theme so if you want a white on black change your watch theme to dark, and for black on white change it to light. + Special thanks to: * rozek (for his updated widget draw code for utilization with background images) * Gordon Williams (Bangle.js, watchapps for reference code and documentation) diff --git a/apps/rolex/app.js b/apps/rolex/app.js index e409704fc..124cb6fee 100644 --- a/apps/rolex/app.js +++ b/apps/rolex/app.js @@ -28,6 +28,14 @@ var imgSec = { buffer : E.toArrayBuffer(atob("v/q//r/+v/qv+q/qq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qv+v/6/D/wD8PDw8PwD/w///6v+qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqr+r//v///X/1X/Vf9V/1X/1///+//q/qq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq6qrqg==")) }; +/* use font closer to Rolex */ + +Graphics.prototype.setFontRolexFont = function(scale) { + // Actual height 12 (12 - 1) + this.setFontCustom(atob("AAAABAACAAAAAYAHgA4AOABgAAAAA/gD/gMBgQBAwGA/4A/gAAAAAAIBAQCB/8D/4AAQAAAAAAAAAwEDAYEBQIEgYxA/CA4MAAAAAAAAgIBAhCBCEDOYHvgCOAAAAAAABgANAAyAHEAf/A/+AAgABAAAAAAADBAcCBsECYIEYgIeAAAAAAAHwAfwB5wGggZBAjGBH4CDgAAACAAYAAgABAMCDwE+APgAYAAAAAAABxwH3wJwgRhA3iB54AhgAAAAAAPhA/iBDMCCQGHgH+AHwAAAAAAAQIAgQAAAAAA="), 46, atob("BAUJCQkJCQkJCQkJBQ=="), 17+(scale<<8)+(1<<16)); + return this; +}; + /* Set variables to get screen width, height and center points */ let W = g.getWidth(); @@ -36,10 +44,6 @@ let cx = W/2; let cy = H/2; let Timeout; -/* set font */ - -require("Font4x5Numeric").add(Graphics); - Bangle.loadWidgets(); /* Custom version of Bangle.drawWidgets (does not clear the widget areas) Thanks to rozek */ @@ -106,9 +110,10 @@ function drawHands() { g.drawImage(imgHour,cx-22*hourSin,cy+22*hourCos,{rotate:hourAngle}); g.drawImage(imgMin,cx-34*minSin,cy+34*minCos,{rotate:minAngle}); g.drawImage(imgSec,cx-25*secSin,cy+25*secCos,{rotate:secAngle}); - g.setFont("4x5Numeric:3"); + g.setFontRolexFont(); g.setColor(g.theme.bg); - g.drawString(d.getDate(),157,81); + g.setFontAlign(0,0,0); + g.drawString(d.getDate(),165,89); } function drawBackground() { diff --git a/apps/rolex/app.js:Zone.Identifier b/apps/rolex/app.js:Zone.Identifier new file mode 100644 index 000000000..053d1127c --- /dev/null +++ b/apps/rolex/app.js:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=about:internet diff --git a/apps/rolex/screenshot1.png b/apps/rolex/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..f84b0ef5c3ef50356dc790e36e51d0a99cabe16f GIT binary patch literal 3905 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 literal 0 HcmV?d00001 diff --git a/apps/rolex/screenshot1.png:Zone.Identifier b/apps/rolex/screenshot1.png:Zone.Identifier new file mode 100644 index 000000000..053d1127c --- /dev/null +++ b/apps/rolex/screenshot1.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=about:internet From 08c9e519b99982c57a3f53c16693b33f503a6f4b Mon Sep 17 00:00:00 2001 From: DC959 Date: Mon, 28 Feb 2022 22:11:19 +1300 Subject: [PATCH 195/199] Fix date alignment and change font to closer match Rolex --- apps/rolex/app.js:Zone.Identifier | 3 --- apps/rolex/screenshot1.png:Zone.Identifier | 3 --- 2 files changed, 6 deletions(-) delete mode 100644 apps/rolex/app.js:Zone.Identifier delete mode 100644 apps/rolex/screenshot1.png:Zone.Identifier diff --git a/apps/rolex/app.js:Zone.Identifier b/apps/rolex/app.js:Zone.Identifier deleted file mode 100644 index 053d1127c..000000000 --- a/apps/rolex/app.js:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=about:internet diff --git a/apps/rolex/screenshot1.png:Zone.Identifier b/apps/rolex/screenshot1.png:Zone.Identifier deleted file mode 100644 index 053d1127c..000000000 --- a/apps/rolex/screenshot1.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=about:internet From 6ed617949b1317274aefe7e5bcc8e58003c3792f Mon Sep 17 00:00:00 2001 From: Daniel Cox Date: Mon, 28 Feb 2022 22:22:26 +1300 Subject: [PATCH 196/199] Update metadata.json --- apps/rolex/metadata.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/rolex/metadata.json b/apps/rolex/metadata.json index e24344dad..f307e60c4 100644 --- a/apps/rolex/metadata.json +++ b/apps/rolex/metadata.json @@ -2,8 +2,8 @@ "name": "rolex", "shortName":"rolex", "icon": "rolex.png", - "screenshots": [{"url":"screenshot.png"}], - "version":"0.03", + "screenshots": [{"url":"screenshot1.png"}], + "version":"0.04", "description": "A rolex like watch face", "tags": "clock", "type": "clock", @@ -14,4 +14,4 @@ {"name":"rolex.app.js","url":"app.js"}, {"name":"rolex.img","url":"app-icon.js","evaluate":true} ] - } \ No newline at end of file + } From 52d54c9234d158a27eb9212daf63500d1d03e76d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 28 Feb 2022 13:10:55 +0000 Subject: [PATCH 197/199] Remove BangleRun as it's unmaintained and no longer works nicely with PR #1052 for Typescript support Remove Travis builds as we're now switching to GitHub actions --- .travis.yml | 3 - apps/banglerun/ChangeLog | 13 -- apps/banglerun/activity.js | 40 ------- apps/banglerun/activity.ts | 41 ------- apps/banglerun/app-icon.js | 1 - apps/banglerun/app.js | 15 --- apps/banglerun/app.ts | 20 ---- apps/banglerun/banglerun.png | Bin 10456 -> 0 bytes apps/banglerun/display.js | 106 ----------------- apps/banglerun/display.ts | 123 ------------------- apps/banglerun/gps.js | 71 ----------- apps/banglerun/gps.ts | 90 -------------- apps/banglerun/hrm.js | 19 --- apps/banglerun/hrm.ts | 29 ----- apps/banglerun/interface.html | 217 ---------------------------------- apps/banglerun/log.js | 37 ------ apps/banglerun/log.ts | 47 -------- apps/banglerun/metadata.json | 16 --- apps/banglerun/state.js | 37 ------ apps/banglerun/state.ts | 93 --------------- apps/banglerun/step.js | 14 --- apps/banglerun/step.ts | 15 --- 22 files changed, 1047 deletions(-) delete mode 100644 .travis.yml delete mode 100644 apps/banglerun/ChangeLog delete mode 100644 apps/banglerun/activity.js delete mode 100644 apps/banglerun/activity.ts delete mode 100644 apps/banglerun/app-icon.js delete mode 100644 apps/banglerun/app.js delete mode 100644 apps/banglerun/app.ts delete mode 100644 apps/banglerun/banglerun.png delete mode 100644 apps/banglerun/display.js delete mode 100644 apps/banglerun/display.ts delete mode 100644 apps/banglerun/gps.js delete mode 100644 apps/banglerun/gps.ts delete mode 100644 apps/banglerun/hrm.js delete mode 100644 apps/banglerun/hrm.ts delete mode 100644 apps/banglerun/interface.html delete mode 100644 apps/banglerun/log.js delete mode 100644 apps/banglerun/log.ts delete mode 100644 apps/banglerun/metadata.json delete mode 100644 apps/banglerun/state.js delete mode 100644 apps/banglerun/state.ts delete mode 100644 apps/banglerun/step.js delete mode 100644 apps/banglerun/step.ts diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f3d0d2159..000000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - "node" diff --git a/apps/banglerun/ChangeLog b/apps/banglerun/ChangeLog deleted file mode 100644 index c778588cc..000000000 --- a/apps/banglerun/ChangeLog +++ /dev/null @@ -1,13 +0,0 @@ -0.01: First release -0.02: Bugfix time: Reset minutes to 0 when hitting 60 -0.03: Fix distance >=10 km (fix #529) -0.04: Use offscreen buffer for flickerless updates -0.05: Complete rewrite. New UI, GPS & HRM Kalman filters, activity logging -0.06: Reading HDOP directly from the GPS event (needs Espruino 2v07 or above) -0.07: Fixed GPS update, added guards against NaN values -0.08: Fix issue with GPS coordinates being wrong after the first one -0.09: Another GPS fix (log raw coordinates - not filtered ones) -0.10: Removed kalman filtering to allow distance log to work - Only log data every 5 seconds (not 1 sec) - Don't create a file until the first log entry is ready - Add labels for buttons diff --git a/apps/banglerun/activity.js b/apps/banglerun/activity.js deleted file mode 100644 index 94512094c..000000000 --- a/apps/banglerun/activity.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.stopActivity = exports.startActivity = exports.clearActivity = void 0; -const display_1 = require("./display"); -const log_1 = require("./log"); -const state_1 = require("./state"); -function startActivity(state) { - if (state.status === state_1.ActivityStatus.Stopped) { - (0, log_1.initLog)(state); - } - if (state.status === state_1.ActivityStatus.Running) { - state.status = state_1.ActivityStatus.Paused; - } - else { - state.status = state_1.ActivityStatus.Running; - } - (0, display_1.draw)(state); -} -exports.startActivity = startActivity; -function stopActivity(state) { - if (state.status === state_1.ActivityStatus.Paused) { - clearActivity(state); - } - if (state.status === state_1.ActivityStatus.Running) { - state.status = state_1.ActivityStatus.Paused; - } - else { - state.status = state_1.ActivityStatus.Stopped; - } - (0, display_1.draw)(state); -} -exports.stopActivity = stopActivity; -function clearActivity(state) { - state.duration = 0; - state.distance = 0; - state.speed = 0; - state.steps = 0; - state.cadence = 0; -} -exports.clearActivity = clearActivity; diff --git a/apps/banglerun/activity.ts b/apps/banglerun/activity.ts deleted file mode 100644 index c1a01f30b..000000000 --- a/apps/banglerun/activity.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { draw } from './display'; -import { initLog } from './log'; -import { ActivityStatus, AppState } from './state'; - -function startActivity(state: AppState): void { - if (state.status === ActivityStatus.Stopped) { - initLog(state); - } - - if (state.status === ActivityStatus.Running) { - state.status = ActivityStatus.Paused; - } else { - state.status = ActivityStatus.Running; - } - - draw(state); -} - -function stopActivity(state: AppState): void { - if (state.status === ActivityStatus.Paused) { - clearActivity(state); - } - - if (state.status === ActivityStatus.Running) { - state.status = ActivityStatus.Paused; - } else { - state.status = ActivityStatus.Stopped; - } - - draw(state); -} - -function clearActivity(state: AppState): void { - state.duration = 0; - state.distance = 0; - state.speed = 0; - state.steps = 0; - state.cadence = 0; -} - -export { clearActivity, startActivity, stopActivity }; diff --git a/apps/banglerun/app-icon.js b/apps/banglerun/app-icon.js deleted file mode 100644 index 9eeaced6e..000000000 --- a/apps/banglerun/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEwwIHEuAEDgP8ApMDAqAXBjAGD/E8AgUcgF8CAX/BgIFBn//wAFCv//8PwAoP///5Aon/8AcB+IFB4AFB8P/34FBgfj/8fwAFB4f+g4cBg/H/w/Cg+HKQcPx4FEh4/CAoMfAocOj4/CKYRwELIIFDLII6BAoZSBLIYeCgP+v4FD/k/GAQFBHgcD/ABBIIX4gIFBSYPwAoUPAog/B8AFEwAFDDQQCBQoQFCZYYFigCKEgFwgAA==")) diff --git a/apps/banglerun/app.js b/apps/banglerun/app.js deleted file mode 100644 index 84d03820a..000000000 --- a/apps/banglerun/app.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const activity_1 = require("./activity"); -const display_1 = require("./display"); -const gps_1 = require("./gps"); -const hrm_1 = require("./hrm"); -const state_1 = require("./state"); -const step_1 = require("./step"); -const appState = (0, state_1.initState)(); -(0, gps_1.initGps)(appState); -(0, hrm_1.initHrm)(appState); -(0, step_1.initStep)(appState); -(0, display_1.initDisplay)(appState); -setWatch(() => (0, activity_1.startActivity)(appState), BTN1, { repeat: true, edge: 'falling' }); -setWatch(() => (0, activity_1.stopActivity)(appState), BTN3, { repeat: true, edge: 'falling' }); diff --git a/apps/banglerun/app.ts b/apps/banglerun/app.ts deleted file mode 100644 index 7093e24e0..000000000 --- a/apps/banglerun/app.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { startActivity, stopActivity } from './activity'; -import { initDisplay } from './display'; -import { initGps } from './gps'; -import { initHrm } from './hrm'; -import { initState } from './state'; -import { initStep } from './step'; - -declare var BTN1: any; -declare var BTN3: any; -declare var setWatch: any; - -const appState = initState(); - -initGps(appState); -initHrm(appState); -initStep(appState); -initDisplay(appState); - -setWatch(() => startActivity(appState), BTN1, { repeat: true, edge: 'falling' }); -setWatch(() => stopActivity(appState), BTN3, { repeat: true, edge: 'falling' }); diff --git a/apps/banglerun/banglerun.png b/apps/banglerun/banglerun.png deleted file mode 100644 index bf2cd8af3ef5f9711d18df1656a03a98283bcc67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10456 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 O0000 { - state.drawing = on; - if (on) { - drawAll(state); - } - }); - drawAll(state); -} -exports.initDisplay = initDisplay; -function drawBackground() { - g.clear(); - g.setColor(0xC618); - g.setFont('6x8', 2); - g.setFontAlign(0, -1, 0); - g.drawString('DIST (KM)', 60, 32); - g.drawString('TIME', 172, 32); - g.drawString('PACE', 60, 92); - g.drawString('HEART', 172, 92); - g.drawString('STEPS', 60, 152); - g.drawString('CADENCE', 172, 152); -} -exports.drawBackground = drawBackground; -function drawValue(value, x, y) { - g.setColor(0x0000); - g.fillRect(x - 60, y, x + 60, y + 30); - g.setColor(0xFFFF); - g.drawString(value, x, y); -} -exports.drawValue = drawValue; -function draw(state) { - g.setFontVector(30); - g.setFontAlign(0, -1, 0); - drawValue(formatDistance(state.distance), 60, 55); - drawValue(formatTime(state.duration), 172, 55); - drawValue(formatPace(state.speed), 60, 115); - drawValue(state.hr.toFixed(0), 172, 115); - drawValue(state.steps.toFixed(0), 60, 175); - drawValue(state.cadence.toFixed(0), 172, 175); - g.setFont('6x8', 2); - g.setColor(state.gpsValid ? 0x07E0 : 0xF800); - g.fillRect(0, 216, 80, 240); - g.setColor(0x0000); - g.drawString('GPS', 40, 220); - g.setColor(0xFFFF); - g.fillRect(80, 216, 160, 240); - g.setColor(0x0000); - g.drawString(formatClock(new Date()), 120, 220); - g.setColor(STATUS_COLORS[state.status]); - g.fillRect(160, 216, 230, 240); - g.setColor(0x0000); - g.drawString(state.status, 200, 220); - g.setFont("6x8").setFontAlign(0, 0, 1).setColor(-1); - if (state.status === state_1.ActivityStatus.Paused) { - g.drawString("START", 236, 60, 1).drawString(" CLEAR ", 236, 180, 1); - } - else if (state.status === state_1.ActivityStatus.Running) { - g.drawString(" PAUSE ", 236, 60, 1).drawString(" PAUSE ", 236, 180, 1); - } - else { - g.drawString("START", 236, 60, 1).drawString(" ", 236, 180, 1); - } -} -exports.draw = draw; -function drawAll(state) { - drawBackground(); - draw(state); - Bangle.drawWidgets(); -} -exports.drawAll = drawAll; -function formatClock(date) { - return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); -} -exports.formatClock = formatClock; -function formatDistance(meters) { - return (meters / 1000).toFixed(2); -} -exports.formatDistance = formatDistance; -function formatPace(speed) { - if (speed < 0.1667) { - return `__'__"`; - } - const pace = Math.round(1000 / speed); - const min = Math.floor(pace / 60); - const sec = pace % 60; - return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; -} -exports.formatPace = formatPace; -function formatTime(time) { - const seconds = Math.round(time); - const hrs = Math.floor(seconds / 3600); - const min = Math.floor(seconds / 60) % 60; - const sec = seconds % 60; - return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); -} -exports.formatTime = formatTime; diff --git a/apps/banglerun/display.ts b/apps/banglerun/display.ts deleted file mode 100644 index 528890c35..000000000 --- a/apps/banglerun/display.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { ActivityStatus, AppState } from './state'; - -declare var Bangle: any; -declare var g: any; - -const STATUS_COLORS = { - 'STOP': 0xF800, - 'PAUSE': 0xFFE0, - 'RUN': 0x07E0, -} - -function initDisplay(state: AppState): void { - Bangle.loadWidgets(); - Bangle.on('lcdPower', (on: boolean) => { - state.drawing = on; - if (on) { - drawAll(state); - } - }); - drawAll(state); -} - -function drawBackground(): void { - g.clear(); - g.setColor(0xC618); - g.setFont('6x8', 2); - g.setFontAlign(0, -1, 0); - g.drawString('DIST (KM)', 60, 32); - g.drawString('TIME', 172, 32); - g.drawString('PACE', 60, 92); - g.drawString('HEART', 172, 92); - g.drawString('STEPS', 60, 152); - g.drawString('CADENCE', 172, 152); -} - -function drawValue(value: string, x: number, y: number) { - g.setColor(0x0000); - g.fillRect(x - 60, y, x + 60, y + 30); - g.setColor(0xFFFF); - g.drawString(value, x, y); -} - -function draw(state: AppState): void { - g.setFontVector(30); - g.setFontAlign(0, -1, 0); - - drawValue(formatDistance(state.distance), 60, 55); - drawValue(formatTime(state.duration), 172, 55); - drawValue(formatPace(state.speed), 60, 115); - drawValue(state.hr.toFixed(0), 172, 115); - drawValue(state.steps.toFixed(0), 60, 175); - drawValue(state.cadence.toFixed(0), 172, 175); - - g.setFont('6x8', 2); - - g.setColor(state.gpsValid ? 0x07E0 : 0xF800); - g.fillRect(0, 216, 80, 240); - g.setColor(0x0000); - g.drawString('GPS', 40, 220); - - g.setColor(0xFFFF); - g.fillRect(80, 216, 160, 240); - g.setColor(0x0000); - g.drawString(formatClock(new Date()), 120, 220); - - g.setColor(STATUS_COLORS[state.status]); - g.fillRect(160, 216, 230, 240); - g.setColor(0x0000); - g.drawString(state.status, 200, 220); - - g.setFont("6x8").setFontAlign(0,0,1).setColor(-1); - if (state.status === ActivityStatus.Paused) { - g.drawString("START",236,60,1).drawString(" CLEAR ",236,180,1); - } else if (state.status === ActivityStatus.Running) { - g.drawString(" PAUSE ",236,60,1).drawString(" PAUSE ",236,180,1); - } else { - g.drawString("START",236,60,1).drawString(" ",236,180,1); - } -} - -function drawAll(state: AppState) { - drawBackground(); - draw(state); - Bangle.drawWidgets(); -} - -function formatClock(date: Date): string { - return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); -} - -function formatDistance(meters: number): string { - return (meters / 1000).toFixed(2); -} - -function formatPace(speed: number): string { - if (speed < 0.1667) { - return `__'__"`; - } - const pace = Math.round(1000 / speed); - const min = Math.floor(pace / 60); - const sec = pace % 60; - return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; -} - -function formatTime(time: number): string { - const seconds = Math.round(time); - const hrs = Math.floor(seconds / 3600); - const min = Math.floor(seconds / 60) % 60; - const sec = seconds % 60; - return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); -} - -export { - draw, - drawAll, - drawBackground, - drawValue, - formatClock, - formatDistance, - formatPace, - formatTime, - initDisplay, -}; diff --git a/apps/banglerun/gps.js b/apps/banglerun/gps.js deleted file mode 100644 index 35e0f8769..000000000 --- a/apps/banglerun/gps.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.updateGps = exports.readGps = exports.initGps = void 0; -const display_1 = require("./display"); -const log_1 = require("./log"); -const state_1 = require("./state"); -const EARTH_RADIUS = 6371008.8; -function initGps(state) { - Bangle.on('GPS', (gps) => readGps(state, gps)); - Bangle.setGPSPower(1); -} -exports.initGps = initGps; -function readGps(state, gps) { - state.lat = gps.lat; - state.lon = gps.lon; - state.alt = gps.alt; - state.vel = gps.speed / 3.6; - state.fix = gps.fix; - state.dop = gps.hdop; - state.gpsValid = state.fix > 0; - updateGps(state); - (0, display_1.draw)(state); - /* Only log GPS data every 5 secs if we - have a fix and we're running. */ - if (state.gpsValid && - state.status === state_1.ActivityStatus.Running && - state.timeSinceLog > 5) { - state.timeSinceLog = 0; - (0, log_1.updateLog)(state); - } -} -exports.readGps = readGps; -function updateGps(state) { - const t = Date.now(); - let dt = (t - state.t) / 1000; - if (!isFinite(dt)) - dt = 0; - state.t = t; - state.timeSinceLog += dt; - if (state.status === state_1.ActivityStatus.Running) { - state.duration += dt; - } - if (!state.gpsValid) { - return; - } - const r = EARTH_RADIUS + state.alt; - const lat = state.lat * Math.PI / 180; - const lon = state.lon * Math.PI / 180; - const x = r * Math.cos(lat) * Math.cos(lon); - const y = r * Math.cos(lat) * Math.sin(lon); - const z = r * Math.sin(lat); - if (!state.x) { - state.x = x; - state.y = y; - state.z = z; - return; - } - const dx = x - state.x; - const dy = y - state.y; - const dz = z - state.z; - const dpMag = Math.sqrt(dx * dx + dy * dy + dz * dz); - state.x = x; - state.y = y; - state.z = z; - if (state.status === state_1.ActivityStatus.Running) { - state.distance += dpMag; - state.speed = (state.distance / state.duration) || 0; - state.cadence = (60 * state.steps / state.duration) || 0; - } -} -exports.updateGps = updateGps; diff --git a/apps/banglerun/gps.ts b/apps/banglerun/gps.ts deleted file mode 100644 index 1886ecfb2..000000000 --- a/apps/banglerun/gps.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { draw } from './display'; -import { updateLog } from './log'; -import { ActivityStatus, AppState } from './state'; - -declare var Bangle: any; - -interface GpsEvent { - lat: number; - lon: number; - alt: number; - speed: number; - hdop: number; - fix: number; -} - -const EARTH_RADIUS = 6371008.8; - -function initGps(state: AppState): void { - Bangle.on('GPS', (gps: GpsEvent) => readGps(state, gps)); - Bangle.setGPSPower(1); -} - -function readGps(state: AppState, gps: GpsEvent): void { - state.lat = gps.lat; - state.lon = gps.lon; - state.alt = gps.alt; - state.vel = gps.speed / 3.6; - state.fix = gps.fix; - state.dop = gps.hdop; - state.gpsValid = state.fix > 0; - - updateGps(state); - draw(state); - - /* Only log GPS data every 5 secs if we - have a fix and we're running. */ - if (state.gpsValid && - state.status === ActivityStatus.Running && - state.timeSinceLog > 5) { - state.timeSinceLog = 0; - updateLog(state); - } -} - -function updateGps(state: AppState): void { - const t = Date.now(); - let dt = (t - state.t) / 1000; - if (!isFinite(dt)) dt=0; - state.t = t; - state.timeSinceLog += dt; - - if (state.status === ActivityStatus.Running) { - state.duration += dt; - } - - if (!state.gpsValid) { - return; - } - - const r = EARTH_RADIUS + state.alt; - const lat = state.lat * Math.PI / 180; - const lon = state.lon * Math.PI / 180; - const x = r * Math.cos(lat) * Math.cos(lon); - const y = r * Math.cos(lat) * Math.sin(lon); - const z = r * Math.sin(lat); - - if (!state.x) { - state.x = x; - state.y = y; - state.z = z; - return; - } - - const dx = x - state.x; - const dy = y - state.y; - const dz = z - state.z; - const dpMag = Math.sqrt(dx * dx + dy * dy + dz * dz); - - state.x = x; - state.y = y; - state.z = z; - - if (state.status === ActivityStatus.Running) { - state.distance += dpMag; - state.speed = (state.distance / state.duration) || 0; - state.cadence = (60 * state.steps / state.duration) || 0; - } -} - -export { initGps, readGps, updateGps }; diff --git a/apps/banglerun/hrm.js b/apps/banglerun/hrm.js deleted file mode 100644 index c002de2f6..000000000 --- a/apps/banglerun/hrm.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.updateHrm = exports.initHrm = void 0; -function initHrm(state) { - Bangle.on('HRM', (hrm) => updateHrm(state, hrm)); - Bangle.setHRMPower(1); -} -exports.initHrm = initHrm; -function updateHrm(state, hrm) { - if (hrm.confidence === 0) { - return; - } - const dHr = hrm.bpm - state.hr; - const hrError = Math.abs(dHr) + 101 - hrm.confidence; - const hrGain = (state.hrError / (state.hrError + hrError)) || 0; - state.hr += dHr * hrGain; - state.hrError += (hrError - state.hrError) * hrGain; -} -exports.updateHrm = updateHrm; diff --git a/apps/banglerun/hrm.ts b/apps/banglerun/hrm.ts deleted file mode 100644 index 08dd237a7..000000000 --- a/apps/banglerun/hrm.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AppState } from './state'; - -interface HrmData { - bpm: number; - confidence: number; - raw: string; -} - -declare var Bangle: any; - -function initHrm(state: AppState) { - Bangle.on('HRM', (hrm: HrmData) => updateHrm(state, hrm)); - Bangle.setHRMPower(1); -} - -function updateHrm(state: AppState, hrm: HrmData) { - if (hrm.confidence === 0) { - return; - } - - const dHr = hrm.bpm - state.hr; - const hrError = Math.abs(dHr) + 101 - hrm.confidence; - const hrGain = (state.hrError / (state.hrError + hrError)) || 0; - - state.hr += dHr * hrGain; - state.hrError += (hrError - state.hrError) * hrGain; -} - -export { initHrm, updateHrm }; diff --git a/apps/banglerun/interface.html b/apps/banglerun/interface.html deleted file mode 100644 index 6388d3b65..000000000 --- a/apps/banglerun/interface.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - -

- - - - - diff --git a/apps/banglerun/log.js b/apps/banglerun/log.js deleted file mode 100644 index 0cdeaa964..000000000 --- a/apps/banglerun/log.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.updateLog = exports.initLog = void 0; -function initLog(state) { - const datetime = new Date().toISOString().replace(/[-:]/g, ''); - const date = datetime.substr(2, 6); - const time = datetime.substr(9, 6); - const filename = `banglerun_${date}_${time}`; - return Object.assign(Object.assign({}, state), { file: require('Storage').open(filename, 'w'), fileWritten: false }); -} -exports.initLog = initLog; -function updateLog(state) { - if (!state.fileWritten) { - state.file.write([ - 'timestamp', - 'latitude', - 'longitude', - 'altitude', - 'duration', - 'distance', - 'heartrate', - 'steps', - ].join(',') + '\n'); - state.fileWritten = true; - } - state.file.write([ - Date.now().toFixed(0), - state.lat.toFixed(6), - state.lon.toFixed(6), - state.alt.toFixed(2), - state.duration.toFixed(0), - state.distance.toFixed(2), - state.hr.toFixed(0), - state.steps.toFixed(0), - ].join(',') + '\n'); -} -exports.updateLog = updateLog; diff --git a/apps/banglerun/log.ts b/apps/banglerun/log.ts deleted file mode 100644 index ba1c1f00e..000000000 --- a/apps/banglerun/log.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { AppState, AppStateWithLog } from './state'; - -declare var require: any; - -function initLog(state: AppState): AppStateWithLog { - const datetime = new Date().toISOString().replace(/[-:]/g, ''); - const date = datetime.substr(2, 6); - const time = datetime.substr(9, 6); - const filename = `banglerun_${date}_${time}`; - return { - ...state, - file: require('Storage').open(filename, 'w'), - fileWritten: false, - } as AppStateWithLog; -} - -function updateLog(state: AppStateWithLog): void { - if (!state.fileWritten) { - state.file.write( - [ - 'timestamp', - 'latitude', - 'longitude', - 'altitude', - 'duration', - 'distance', - 'heartrate', - 'steps', - ].join(',') + '\n' - ); - state.fileWritten = true; - } - state.file.write( - [ - Date.now().toFixed(0), - state.lat.toFixed(6), - state.lon.toFixed(6), - state.alt.toFixed(2), - state.duration.toFixed(0), - state.distance.toFixed(2), - state.hr.toFixed(0), - state.steps.toFixed(0), - ].join(',') + '\n' - ); -} - -export { initLog, updateLog }; diff --git a/apps/banglerun/metadata.json b/apps/banglerun/metadata.json deleted file mode 100644 index d66441c8d..000000000 --- a/apps/banglerun/metadata.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "banglerun", - "name": "BangleRun", - "shortName": "BangleRun", - "version": "0.10", - "description": "An app for running sessions. Displays info and logs your run for later viewing.", - "icon": "banglerun.png", - "tags": "run,running,fitness,outdoors", - "supports": ["BANGLEJS"], - "interface": "interface.html", - "allow_emulator": false, - "storage": [ - {"name":"banglerun.app.js","url":"app.js"}, - {"name":"banglerun.img","url":"app-icon.js","evaluate":true} - ] -} diff --git a/apps/banglerun/state.js b/apps/banglerun/state.js deleted file mode 100644 index 349ef1954..000000000 --- a/apps/banglerun/state.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.initState = exports.ActivityStatus = void 0; -var ActivityStatus; -(function (ActivityStatus) { - ActivityStatus["Stopped"] = "STOP"; - ActivityStatus["Paused"] = "PAUSE"; - ActivityStatus["Running"] = "RUN"; -})(ActivityStatus || (ActivityStatus = {})); -exports.ActivityStatus = ActivityStatus; -function initState() { - return { - fix: NaN, - lat: NaN, - lon: NaN, - alt: NaN, - vel: NaN, - dop: NaN, - gpsValid: false, - x: NaN, - y: NaN, - z: NaN, - t: NaN, - timeSinceLog: 0, - hr: 60, - hrError: 100, - fileWritten: false, - drawing: false, - status: ActivityStatus.Stopped, - duration: 0, - distance: 0, - speed: 0, - steps: 0, - cadence: 0, - }; -} -exports.initState = initState; diff --git a/apps/banglerun/state.ts b/apps/banglerun/state.ts deleted file mode 100644 index 1ba9bca26..000000000 --- a/apps/banglerun/state.ts +++ /dev/null @@ -1,93 +0,0 @@ -enum ActivityStatus { - Stopped = 'STOP', - Paused = 'PAUSE', - Running = 'RUN', -} - -interface BasicAppState { - // GPS NMEA data - fix: number; - lat: number; - lon: number; - alt: number; - vel: number; - dop: number; - gpsValid: boolean; - - // Absolute position data - x: number; - y: number; - z: number; - // Last fix time - t: number; - // Last time we saved log info - timeSinceLog : number; - - // HRM data - hr: number, - hrError: number, - - // Logger data - fileWritten: boolean; - - // Drawing data - drawing: boolean; - - // Activity data - duration: number; - distance: number; - speed: number; - steps: number; - cadence: number; -} - -interface AppStateWithoutLog extends BasicAppState { - status: 'STOP'; -} - -interface AppStateWithLog extends BasicAppState { - file: File; - status: ActivityStatus; -} - -type AppState = AppStateWithLog | AppStateWithoutLog; - -interface File { - read: Function; - write: Function; - erase: Function; -} - -function initState(): AppState { - return { - fix: NaN, - lat: NaN, - lon: NaN, - alt: NaN, - vel: NaN, - dop: NaN, - gpsValid: false, - - x: NaN, - y: NaN, - z: NaN, - t: NaN, - timeSinceLog : 0, - - hr: 60, - hrError: 100, - - fileWritten: false, - - drawing: false, - - status: ActivityStatus.Stopped, - duration: 0, - distance: 0, - speed: 0, - steps: 0, - cadence: 0, - } -} - -export { ActivityStatus, AppState, AppStateWithLog, File, initState }; diff --git a/apps/banglerun/step.js b/apps/banglerun/step.js deleted file mode 100644 index e4acfd66a..000000000 --- a/apps/banglerun/step.js +++ /dev/null @@ -1,14 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.updateStep = exports.initStep = void 0; -const state_1 = require("./state"); -function initStep(state) { - Bangle.on('step', () => updateStep(state)); -} -exports.initStep = initStep; -function updateStep(state) { - if (state.status === state_1.ActivityStatus.Running) { - state.steps += 1; - } -} -exports.updateStep = updateStep; diff --git a/apps/banglerun/step.ts b/apps/banglerun/step.ts deleted file mode 100644 index c7fcb61ea..000000000 --- a/apps/banglerun/step.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ActivityStatus, AppState } from './state'; - -declare var Bangle: any; - -function initStep(state: AppState) { - Bangle.on('step', () => updateStep(state)); -} - -function updateStep(state: AppState) { - if (state.status === ActivityStatus.Running) { - state.steps += 1; - } -} - -export { initStep, updateStep }; From bc8eecf998a8d380485139ce4016e888b648ffb6 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 1 Mar 2022 08:12:53 +0000 Subject: [PATCH 198/199] fix lint warnings --- .eslintignore | 1 + apps/pooqroman/app.js | 6 ++++-- apps/pooqroman/resourcer.js | 3 ++- apps/pooqround/resourcer.js | 3 ++- apps/speedalt2/app.js | 3 ++- apps/weatherClock/app.js | 1 - 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.eslintignore b/.eslintignore index 7bbe41136..fcbea07f9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ apps/animclk/V29.LBM.js apps/banglerun/rollup.config.js apps/schoolCalendar/fullcalendar/main.js apps/authentiwatch/qr_packed.js +apps/qrcode/qr-scanner.umd.min.js *.test.js diff --git a/apps/pooqroman/app.js b/apps/pooqroman/app.js index bed8ef3d2..fcb2437e1 100644 --- a/apps/pooqroman/app.js +++ b/apps/pooqroman/app.js @@ -353,13 +353,15 @@ const events = { let c, p, i, l = from - o, h = to - o; for (i = 0; (c = this.wall[i]).time < l; i++) ; for (; (c = this.wall[i]).time < h; i++) { - if ((p = c.time < t) ? c.past : c.future) + p = c.time < t; + if (p ? c.past : c.future) result = Math.min(result, f(c, new Date(c.time + o), p)); } l += o; h += o; t += o; for (i = 0; (c = this.fixed[i]).time < l; i++) ; for (; (c = this.fixed[i]).time < h; i++) { - if ((p = c.time < t) ? c.past : c.future) + p = c.time < t; + if (p ? c.past : c.future) result = Math.min(f(c, new Date(c.time), p)); } return result; diff --git a/apps/pooqroman/resourcer.js b/apps/pooqroman/resourcer.js index 69365018e..8b95dc834 100644 --- a/apps/pooqroman/resourcer.js +++ b/apps/pooqroman/resourcer.js @@ -60,7 +60,8 @@ const prepFont = (name, data) => { let width = m[2] == '*' ? null : +m[2]; let c = null, o = 0; lines.forEach((line, l) => { - if (m = /^(<*)(=)([*\d]*)(=*)(>*)$/.exec(line) || /^(<*)(-)(.)(-*)(>*)$/.exec(line)) { + m = /^(<*)(=)([*\d]*)(=*)(>*)$/.exec(line) || /^(<*)(-)(.)(-*)(>*)$/.exec(line); + if (m) { const h = m[2] == '='; if (m[1].length > desc || h && m[1].length != desc) throw new Error('Invalid descender height at ' + l); diff --git a/apps/pooqround/resourcer.js b/apps/pooqround/resourcer.js index 17c35a40d..6b969a102 100644 --- a/apps/pooqround/resourcer.js +++ b/apps/pooqround/resourcer.js @@ -60,7 +60,8 @@ const prepFont = (name, data) => { let width = m[2] == '*' ? null : +m[2]; let c = null, o = 0; lines.forEach((line, l) => { - if (m = /^(<*)(=)([*\d]*)(=*)(>*)$/.exec(line) || /^(<*)(-)(.)(-*)(>*)$/.exec(line)) { + m = /^(<*)(=)([*\d]*)(=*)(>*)$/.exec(line) || /^(<*)(-)(.)(-*)(>*)$/.exec(line); + if (m) { const h = m[2] == '='; if (m[1].length > desc || h && m[1].length != desc) throw new Error('Invalid descender height at ' + l); diff --git a/apps/speedalt2/app.js b/apps/speedalt2/app.js index 73fa3bacb..ed16131a4 100644 --- a/apps/speedalt2/app.js +++ b/apps/speedalt2/app.js @@ -179,7 +179,8 @@ 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(120,10,10); } + this.isOn = v===undefined||!!v; + g.setColor(this.isOn?1:0,0,0).fillCircle(120,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 diff --git a/apps/weatherClock/app.js b/apps/weatherClock/app.js index 1a7f53f05..91d0ab36f 100644 --- a/apps/weatherClock/app.js +++ b/apps/weatherClock/app.js @@ -71,7 +71,6 @@ function chooseIconByCode(code) { case 801: return partSunIcon; default: return cloudIcon; } - break; default: return cloudIcon; } } From 7ce68ff66cd84996d4bef974fe17a407aa8fc460 Mon Sep 17 00:00:00 2001 From: BartS23 <10829389+BartS23@users.noreply.github.com> Date: Sun, 27 Feb 2022 08:35:17 +0100 Subject: [PATCH 199/199] Make links to github absolute otherwise they will not work in the apploader --- apps/run/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/run/README.md b/apps/run/README.md index 17975f92c..5b3bb635a 100644 --- a/apps/run/README.md +++ b/apps/run/README.md @@ -46,8 +46,8 @@ record GPS/HRM/etc data every time you start a run? ## Development -This app uses the [`exstats` module](/modules/exstats.js). When uploaded via the +This app uses the [`exstats` module](https://github.com/espruino/BangleApps/blob/master/modules/exstats.js). When uploaded via the app loader, the module is automatically included in the app's source. However when developing via the IDE the module won't get pulled in by default. -There are some options to fix this easily - please check out the [modules README.md file](/modules/README.md) +There are some options to fix this easily - please check out the [modules README.md file](https://github.com/espruino/BangleApps/blob/master/modules/README.md)