merge changes, add mtimer

master
Bryan 2024-04-25 13:41:40 -06:00
commit d97caa0444
1340 changed files with 25904 additions and 2750 deletions

View File

@ -1,11 +1,6 @@
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
apps/gipy/pkg/gps.js
apps/health/chart.min.js
*.test.js
# typescript/generated files
apps/btadv/*.js
# Needs to be ignored because it uses ESM export/import
apps/gipy/pkg/gps.js
# Needs to be ignored because it includes broken JS
apps/health/chart.min.js

View File

@ -11,10 +11,10 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- name: Use Node.js 16.x
- name: Use Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x
- name: Install testing dependencies
run: npm ci
- name: Test all apps and widgets

9
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,9 @@
Contributing to BangleApps
==========================
https://github.com/espruino/BangleApps?tab=readme-ov-file#getting-started
has some links to tutorials on developing for Bangle.js.
Please check out the Wiki to get an idea what sort of things
we'd like to see for contributed apps: https://github.com/espruino/BangleApps/wiki/App-Contribution

View File

@ -554,6 +554,30 @@ You can use `g.setColor(r,g,b)` OR `g.setColor(16bitnumber)` - some common 16 bi
| GreenYellow | 0xAFE5 |
| Pink | 0xF81F |
## Fonts
A recent addition to Bangle.js is the ability to use extra fonts with support for more characters.
For example [all regions](https://banglejs.com/apps/?id=fontall) or [extended](https://banglejs.com/apps/?id=fontext) fonts.
Once installed, these apps cause a new font, `Intl` to be added to `Graphics`, which can be used with just `g.setFont("Intl")`.
There is also a `font` library - this is not implemented yet, but more information about the planned implementation
is available at https://github.com/espruino/BangleApps/issues/3109
For now, to make your app work with the international font, you can check if `Graphics.prototype.setFontIntl` exists,
and if so you can change the font you plan on using:
```JS
myFont = "6x8:2";
if (Graphics.prototype.setFontIntl)
myFont = "Intl";
```
Any new Font library must contain the metadata `"icon": "app.png", "tags": "font", "type": "module", "provides_modules" : ["fonts"],`
and should provide a `font` library, as well as a `boot.js` that adds `Graphics.prototype.setFontIntl`. If you plan on
making a new library it's best to just copy one of the existing ones for now.
## API Reference
[Reference](http://www.espruino.com/Reference#software)

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8,maximum-scale=0.8, minimum-scale=0.8, shrink-to-fit=no">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" href="css/spectre.min.css">
<link rel="stylesheet" href="css/spectre-exp.min.css">
<link rel="stylesheet" href="css/spectre-icons.min.css">
@ -22,7 +22,7 @@
<body>
<header class="navbar-primary navbar">
<section class="navbar-section" >
<a href="https://banglejs.com" target="_blank" class="navbar-brand mr-2" ><img src="img/banglejs-logo-sml.png" alt="Bangle.js">
<a href="https://banglejs.com" target="_blank" class="navbar-brand mr-2"><img src="img/banglejs-logo-small.svg" alt="Bangle.js">
<div>App Loader</div></a>
<!-- <a href="#" class="btn btn-link">...</a> -->
</section>

View File

@ -1,7 +1,10 @@
{
const lintExemptions = require("./lint_exemptions.js");
module.exports = {
"env": {
// TODO: "espruino": false
// TODO: "banglejs": false
// For a prototype of the above, see https://github.com/espruino/BangleApps/pull/3237
},
"extends": "eslint:recommended",
"globals": {
@ -23,10 +26,8 @@
"Flash": "readonly",
"Float32Array": "readonly",
"Float64Array": "readonly",
"fs": "readonly",
"Function": "readonly",
"Graphics": "readonly",
"heatshrink": "readonly",
"I2C": "readonly",
"Int16Array": "readonly",
"Int32Array": "readonly",
@ -46,11 +47,9 @@
"RegExp": "readonly",
"Serial": "readonly",
"SPI": "readonly",
"Storage": "readonly",
"StorageFile": "readonly",
"String": "readonly",
"SyntaxError": "readonly",
"tensorflow": "readonly",
"TFMicroInterpreter": "readonly",
"TypeError": "readonly",
"Uint16Array": "readonly",
@ -58,8 +57,10 @@
"Uint32Array": "readonly",
"Uint8Array": "readonly",
"Uint8ClampedArray": "readonly",
"Unistroke": "readonly",
"Waveform": "readonly",
// Methods and Fields at https://banglejs.com/reference
"__FILE__": "readonly",
"analogRead": "readonly",
"analogWrite": "readonly",
"arguments": "readonly",
@ -129,7 +130,43 @@
"VIBRATE": "readonly",
// Aliases and not defined at https://banglejs.com/reference
"g": "readonly",
"WIDGETS": "readonly"
"WIDGETS": "readonly",
"module": "readonly",
"exports": "writable",
"D0": "readonly",
"D1": "readonly",
"D2": "readonly",
"D3": "readonly",
"D4": "readonly",
"D5": "readonly",
"D6": "readonly",
"D7": "readonly",
"D8": "readonly",
"D9": "readonly",
"D10": "readonly",
"D11": "readonly",
"D12": "readonly",
"D13": "readonly",
"D14": "readonly",
"D15": "readonly",
"D16": "readonly",
"D17": "readonly",
"D18": "readonly",
"D19": "readonly",
"D20": "readonly",
"D21": "readonly",
"D22": "readonly",
"D23": "readonly",
"D24": "readonly",
"D25": "readonly",
"D26": "readonly",
"D27": "readonly",
"D28": "readonly",
"D29": "readonly",
"D30": "readonly",
"D31": "readonly",
"bleServiceOptions": "writable", // available in boot.js code that's called ad part of bootupdate
},
"parserOptions": {
"ecmaVersion": 11
@ -142,22 +179,25 @@
"SwitchCase": 1
}
],
"no-case-declarations": "off",
"no-constant-condition": "off",
"no-delete-var": "off",
"no-empty": "off",
"no-empty": ["warn", { "allowEmptyCatch": true }],
"no-global-assign": "off",
"no-inner-declarations": "off",
"no-octal": "off",
"no-prototype-builtins": "off",
"no-redeclare": "off",
"no-unreachable": "warn",
"no-cond-assign": "warn",
"no-useless-catch": "warn",
// TODO: "no-undef": "warn",
"no-undef": "off",
"no-unused-vars": "off",
"no-undef": "warn",
"no-unused-vars": ["warn", { "args": "none" } ],
"no-useless-escape": "off",
"no-control-regex" : "off"
}
},
overrides: [
...Object.entries(lintExemptions).map(([filePath, {rules}]) => ({
files: [filePath],
rules: Object.fromEntries(rules.map(rule => [rule, "off"])),
})),
],
}

View File

@ -1 +1,2 @@
0.01: New Widget!
0.02: Minor code improvements

View File

@ -1,7 +1,7 @@
{
"id": "1button",
"name": "One-Button-Tracker",
"version": "0.01",
"version": "0.02",
"description": "A widget that turns BTN1 into a tracker, records time of button press/release.",
"icon": "widget.png",
"type": "widget",

View File

@ -22,7 +22,7 @@
console.log("Button let go");
digitalWrite(LED2,0);
var unpress_time = new Date();
recFile = require("Storage").open("one_button_presses.csv","a");
const recFile = require("Storage").open("one_button_presses.csv","a");
recFile.write([press_time.getTime(),unpress_time.getTime()].join(",")+"\n");
}, BTN1, { repeat: true, edge: 'falling', debounce: 50 });

View File

@ -122,13 +122,13 @@
}
}
function swipeHandler() {
/*function swipeHandler() {
}
}*/
function buttonHandler() {
/*function buttonHandler() {
}
}*/
var twok = new TwoK();
twok.addDigit(); twok.addDigit();

View File

@ -1,3 +1,4 @@
0.01: New app!
0.02: Better support for watch themes
0.03: Workaround minifier bug
0.04: Minor code improvements

View File

@ -2,7 +2,7 @@
"name": "2047pp",
"shortName":"2047pp",
"icon": "app.png",
"version":"0.03",
"version": "0.04",
"description": "Bangle version of a tile shifting game",
"supports" : ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Minor code improvements

View File

@ -80,7 +80,7 @@ function refreshBattery() {
}
// Only update displayed battery level every minute as it fluctuates a lot
var batteryInterval = setInterval(refreshBattery, 60000);
setInterval(refreshBattery, 60000);
Bangle.setUI("clock");
Bangle.setLocked(false);

View File

@ -1,7 +1,7 @@
{
"id": "2ofthemclk",
"name": "two of them clock",
"version": "0.01",
"version": "0.02",
"description": "You can now wear teh memez on your wrist.",
"readme": "README.md",
"icon": "app.png",

View File

@ -3,7 +3,7 @@
"shortName":"3DClock",
"icon": "app.png",
"version":"0.01",
"description": "This is a simple 3D scalig demo based on Anton Clock",
"description": "This is a simple 3D scaling demo based on Anton Clock",
"screenshots" : [ { "url":"screenshot.png" }],
"type":"clock",
"tags": "clock",

View File

@ -282,7 +282,7 @@ function drawWidgeds() {
//print(BluetoothDevice.connected);
var x1Bt = 160;
var y1Bt = 0;
var x2Bt = x1Bt + 30;
//var x2Bt = x1Bt + 30;
var y2Bt = y2Bt;
if (NRF.getSecurityStatus().connected)
@ -391,4 +391,4 @@ Bangle.on('lock', function(on) {
SetFull(Bangle.isLocked());
var secondInterval = setInterval(draw, 1000);
/*var secondInterval =*/ setInterval(draw, 1000);

View File

@ -1,3 +1,4 @@
0.01: Initial version for upload
0.02: Better theme support, configurable colors, small improvements
0.03: Use `messages` library to check for new messages
0.04: Minor code improvements

View File

@ -1,7 +1,7 @@
{ "id": "7x7dotsclock",
"name": "7x7 Dots Clock",
"shortName":"7x7 Dots Clock",
"version":"0.03",
"version": "0.04",
"description": "A clock with a big 7x7 dots Font",
"icon": "dotsfontclock.png",
"tags": "clock",

View File

@ -4,3 +4,4 @@
0.04: Set 00:00 to 12:00 for 12 hour time
0.05: Display time, even on Thursday
0.06: Fix light theme issue, where widgets would end up on a light strip
0.07: Minor code improvements

View File

@ -8,7 +8,7 @@ var imgBg = require("heatshrink").decompress(atob("2GwgJC/AH4A/AH4A/AH4A/AH4A/AC
// reg number first char 48 28 by 41
var fontNum = atob("AAAAAAAAAAAAAA//8D//g//8P/+I//8//44//w//j4//A/+P4/8A/4/4AAAAD/4AAAAP/wAAAAf/gAAAA//AAAAB/+AAAAD/8AAAAH/4AAAAP/wAAAAf/gAAAA//AAAAB/+AAAAD/8AAAAH/wAAAAH/H/gH/H8f/gf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wB/4AP/4H/4A//4f/4D//5//4P//h//4//+B//4AAAAAAAAAAAAAAAAAf/+AAAB//4gAAD//jgAAD/+PgABj/4/gAHj/j/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8f88AAfx/8wAAfH/8AAAcf/8AAAR//4AAAH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA4AAAAAD4AAYAAP4AD8AA/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAHgAH/H/GH/H8f/gf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAP//AAAAP//AAAAP//AAAAP/8AAAAP/2AAAAP/eAAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAB/7x/4AH/7H/4Af/4f/4B//5//4H//h//4f/+B//4AAAAAAAAAAAAAD//wAAAD//wAAAj//gAADj/+AAAPj/5gAA/j/ngAD/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8AA8f8fwAAx/8fAAAH/8cAAAf/8QAAA//8AAAA//8AAAAAAAAAAAAAA//8D//g//8P/+I//8//44//0//j4//Y/+P4/94/4/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAPwAH/AAPH/H8AAMf/HwAAB//HAAAH//EAAAH//AAAAH//AAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAGAAAAAAOAAAAAAeAAAAAA+AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB8AAAAADx/4B/4HH/4H/4Mf/4f/4R//5//4H//h//4f/+B//4AAAAAAAAAAAAAD//wP/+D//w//4j//z//jj//T/+Pj/9j/4/j/3j/j/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8f+8f8fx/+x/8fH/+H/8cf/+f/8R//4f/8H//gf/8AAAAAAAAAAAAAA//8AAAA//8AAAI//8AAA4//0AAD4//YAAP4/94AA/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAPwAH/H/vH/H8f/sf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
// tiny font for percentage first char 48 6 by 8
var fontTiny = atob("AH6BgYF+ACFB/wEBAGGDhYlxAEKBkZFuAAx0hP8EAPqRkZGOAH6RkZFOAICHmKDAAG6RkZFuAHKJiYl+AAAAAAAAAAAAAAAA");
//var fontTiny = atob("AH6BgYF+ACFB/wEBAGGDhYlxAEKBkZFuAAx0hP8EAPqRkZGOAH6RkZFOAICHmKDAAG6RkZFuAHKJiYl+AAAAAAAAAAAAAAAA");
// date font first char 48 12 by 15
var fontDate = atob("AAAAAfv149wAeADwAeADwAeADvHr9+AAAAAAAAAAAAAAAAAAAAAAAAAPHn9/AAAAAAP0A9wweGDwweGDwweGDvAL8AAAAAAAAAAAgwOGDwweGDwweGDvHp98AAAAA/gB6AAwAGAAwAGAAwAGAPHj9/AAAAAfgF6BwweGDwweGDwweGDgHoB+AAAAAfv169wweGDwweGDwweGDgHoB+AAAAAAAAAAgAGAAwAGAAwAGAAvHh9/AAAAAfv169wweGDwweGDwweGDvHr9+AAAAAfgF6BwweGDwweGDwweGDvHr9+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
@ -25,7 +25,7 @@ var imgSun = E.toArrayBuffer(atob("Ig8BwHf7D7Ac/MHD/z8wMP/PzMQ/8/M/D/z8z8QPf7f6A
// define icons
var imgSep = E.toArrayBuffer(atob("BhsBAAAAAA///////////////AAAAAAA"));
var imgPercent = E.toArrayBuffer(atob("BwcBuq7ffbqugA=="));
//var imgPercent = E.toArrayBuffer(atob("BwcBuq7ffbqugA=="));
var img24hr = E.toArrayBuffer(atob("EwgBj7vO53na73tcDtu9uDev7vA93g=="));
var imgPM = E.toArrayBuffer(atob("EwgB+HOfdnPu1X3ar4dV9+q+/bfftg=="));

View File

@ -3,7 +3,7 @@
"shortName":"93 Dub",
"icon": "93dub.png",
"screenshots": [{"url":"screenshot.png"}],
"version":"0.06",
"version": "0.07",
"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",

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Minor code improvements

View File

@ -25,7 +25,7 @@ declare global variables for the toggle button
statuses; if you add an additional toggle button
you should declare it and initiase it here */
var status_spk = {value: true};
//var status_spk = {value: true};
var status_face = {value: true};
var status_iris_light = {value: false};
var status_iris = {value: false};

View File

@ -2,7 +2,7 @@
"id": "BLEcontroller",
"name": "BLE Customisable Controller with Joystick",
"shortName": "BLE Controller",
"version": "0.01",
"version": "0.02",
"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",

View File

@ -1 +1,2 @@
0.01: 1st ver, defining a common UI/UX
0.02: Minor code improvements

View File

@ -5,7 +5,7 @@ identify device and dimensions
max printable position max_x-1 i.e 239
*/
var colbackg='#111111';//black
//var colbackg='#111111';//black
var colorange='#e56e06'; //RGB format rrggbb
var v_color_lines=0xFFFF; //White hex format
var v_color_b_area='#111111';
@ -13,13 +13,13 @@ max printable position max_x-1 i.e 239
var v_font1size=10; //out of quotes
var v_font2size=12;
var v_font_banner_size=30;
var v_clicks=0;
//var v_clicks=0;
//pend identify widget area dinamically
var v_model=process.env.BOARD;
console.log("device="+v_model);
var x_max_screen=g.getWidth();//240;
var y_max_screen=g.getHeight(); //240;
//var y_max_screen=g.getHeight(); //240;
var y_wg_bottom=g.getHeight()-25;
var y_wg_top=25;
if (v_model=='BANGLEJS') {

View File

@ -2,7 +2,7 @@
"id": "UI4swatch",
"name": "UI 4 swatch",
"shortName": "UI 4 swatch",
"version": "0.01",
"version": "0.02",
"description": "A UI/UX for espruino smartwatches, displays dinamically calc. x,y coordinates.",
"icon": "app.png",
"tags": "Color,input,buttons,touch,UI",

View File

@ -1,3 +1,4 @@
0.01: New App!
0.02: Increased Legibility, GUI rework
0.03: 13 new chords
0.04: Minor code improvements

View File

@ -176,8 +176,6 @@ const b7 = [
var index = 0;
var chords = [];
var menu = {
"" : { "title" : "Uke Chords" },
"C" : function() { draw(cc); },

View File

@ -1,7 +1,7 @@
{ "id": "Uke",
"name": "Uke Chords",
"shortName":"Uke",
"version":"0.03",
"version": "0.04",
"description": "Wrist mounted ukulele chords",
"icon": "app.png",
"tags": "uke, chords",

View File

@ -1 +1 @@
0.01: New Widget!
0.01: New Clock Info!

View File

@ -0,0 +1 @@
0.01: New Clock!

View File

@ -0,0 +1,25 @@
# Clock Name
More info on making Clock Faces: https://www.espruino.com/Bangle.js+Clock
Describe the Clock...
## Usage
Describe how to use it
## Features
Name the function
## Controls
Name the buttons and what they are used for
## Requests
Name who should be contacted for support/update requests
## Creator
Your name

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="))

View File

@ -0,0 +1,44 @@
// timeout used to update every minute
let 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() {
// queue next draw in one minute
queueDraw();
// Work out where to draw...
var x = g.getWidth()/2;
var y = g.getHeight()/2;
g.reset();
// work out locale-friendly date/time
var date = new Date();
var timeStr = require("locale").time(date,1);
var dateStr = require("locale").date(date);
// draw time
g.setFontAlign(0,0).setFont("Vector",48);
g.clearRect(0,y-15,g.getWidth(),y+25); // clear the background
g.drawString(timeStr,x,y);
// draw date
y += 35;
g.setFontAlign(0,0).setFont("6x8");
g.clearRect(0,y-4,g.getWidth(),y+4); // clear the background
g.drawString(dateStr,x,y);
}
// Clear the screen once, at startup
g.clear();
// draw immediately at first, queue update
draw();
// Show launcher when middle button pressed
Bangle.setUI("clock");
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,15 @@
{ "id": "7chname",
"name": "My clock human readable name",
"shortName":"Short Name",
"version":"0.01",
"description": "A detailed description of my clock",
"icon": "icon.png",
"type": "clock",
"tags": "clock",
"supports" : ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"7chname.app.js","url":"app.js"},
{"name":"7chname.img","url":"app-icon.js","evaluate":true}
]
}

View File

@ -2,3 +2,4 @@
0.02: Shows night time on the map (2022/12/28)
0.03: Add 1 minute timer with upper taps (2023/01/05)
1.00: Page to set up custom time zones (2023/01/06)
1.01: Minor code improvements

View File

@ -2,7 +2,7 @@
function getImg() {
return require("heatshrink").decompress(atob("2FRgP/ABnxBRP5BJH+gEfBZHghnAv4JFmA+Bj0PBIn3//4h3An4oDAQJWEEIf8AwMEuFOCofAh/QjAWEg4VEwEAnw2DDoKEHEYPwAoUBmgrDhgUHS4XgAwUD/gVC/g+FAAZgEwEf4YqC/EQFQ4NDFgV/4Z3C/EcCo1974VCLAV/V4d7Co9/Co0PCoX+vk4Ko/HCosCRYX5nwTFkEAr/nCokICoL+B/aCGCoMHCoq3EdoraGCosPz4HBcILEJCocBwEHOwQrIgQrHgoHCFYMEgwVJYoMBsEnCofAnkMNQJXH4D4EbQMPkF/xwrEj+/HIkAoAVDj8QueHCoorDCoUDLwd96J0BKwgrHh4VDv+9CosDx6QCCo4HB//8VwvvXgQVDJIYSBCo/sBwaZBgF/NoYVHgH8V4qYDAwUYlAVFEYbFDDgwAGConogf9Zg8DCpP4cIh0Dg0BGAgVE+gVIgUA+AVI+wVE/xAEh5HDEgn+CpEAbgJCCHQoVBn4VJ/ED4ANDAAQVJ4EPPQPAt4VF4BeDColgj/8h/gFYwJBCpF//k//ANDCAYVIcgP+CpH/54VHCAIVB/4VIwYECCocIAwIVBx4VG9+AMITbCYAYJB34VG/UAj4VI7/9Cgw9CJYXAmBtDMAQsIfYhvCCofyvywGB4QFFgYGC/d+agYVLSgf8+ArG/APBD4QVBgh0CAwNwv/fCo4PCCo94s7VDCohnDAoI7Enlv8BZECoRCDAggAB3/3/gzDMAIVFY4IVE4IPBOoZ9DCpXwCoMvCqKxB//3bYywD4BtFAAPfDooVFFYIVGw4VFB4KZFngNE/uPCovgFYgEBuK+Fg4zFCoIrFCovwgQVF+AVFgPxEYzFEbgQVD4EDCoozBYogVCgYVE8bpGCo4HDCoPzBgoVIL4fAg4MGgAIHCofgCszND8BOHK4x2BCofwXgv4h6vGCps/Co6uDAA/7RgIjDDwTaDABPA//9FaAtDCop0FC5YVDLwoAH8//94GD/wVNCYKNECpwPBQggVPNggVBNp4VFFZwAGCquHCqnzCB4"));
}
var IMAGEWIDTH = 176;
//var IMAGEWIDTH = 176;
var IMAGEHEIGHT = 81;
Graphics.prototype.setFontMichroma36 = function() {

View File

@ -1,7 +1,7 @@
{
"id": "a_clock_timer",
"name": "A Clock with Timer",
"version": "1.00",
"version": "1.01",
"description": "A Clock with Timer, Map and Time Zones",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot-1.png"}],

View File

@ -1 +1,2 @@
0.01: Initial version
0.02: Add settings page; Add line break to update message

View File

@ -1,10 +1,13 @@
# a_dndtoggle - Toggle Quiet Mode of the watch
When Quiet mode is off, just start this app to set quiet mode. Start it again to turn off quiet mode.
Use the app settings to choose which quiet mode you prefer ("Alarms" or "Silent"). Default is "Silent".
Work in progress.
#ToDo
Settings page, current status indicator.
Current status indicator
## Creator

View File

@ -6,11 +6,14 @@ let current = 0|bSettings.quiet;
//1 alarms
//2 silent
const dndSettings =
require('Storage').readJSON("a_dndtoggle.settings.json", true) || {};
console.log("old: " + current);
switch (current) {
case 0:
bSettings.quiet = 2;
bSettings.quiet = dndSettings.mode || 2;
Bangle.buzz();
setTimeout('Bangle.buzz();',500);
break;
@ -29,7 +32,7 @@ switch (current) {
console.log("new: " + bSettings.quiet);
E.showMessage(modeNames[current] + " -> " + modeNames[bSettings.quiet]);
E.showMessage(modeNames[current] + " -> \n" + modeNames[bSettings.quiet]);
setTimeout('exitApp();', 2000);

View File

@ -2,14 +2,18 @@
"id": "a_dndtoggle",
"name": "a_dndtoggle - Toggle Quiet Mode of the watch",
"shortName": "A_DND Toggle",
"version": "0.01",
"version": "0.02",
"description": "Toggle Quiet Mode of the watch just by starting this app.",
"icon": "a_dndtoggle.png",
"type": "app",
"tags": "tool",
"supports": ["BANGLEJS","BANGLEJS2"],
"data" : [
{"name":"a_dndtoggle.settings.json"}
],
"storage": [
{"name":"a_dndtoggle.app.js","url":"a_dndtoggle.app.js"},
{"name":"a_dndtoggle.settings.js","url":"settings.js"},
{"name":"a_dndtoggle.img","url":"app-icon.js","evaluate":true}
],
"readme": "README.md"

View File

@ -0,0 +1,33 @@
(function(back) {
const settings =
require('Storage').readJSON("a_dndtoggle.settings.json", true) || {};
function updateSettings() {
require('Storage').writeJSON("a_dndtoggle.settings.json", settings);
}
function buildMainMenu(){
// 0-Noisy is only a placeholder so that the other values map to the Bangle quiet mode options
const modes = [/*LANG*/"Noisy",/*LANG*/"Alarms",/*LANG*/"Silent"];
let mainmenu = {
'': { 'title': 'A_DND Toggle' },
'< Back': back,
/*LANG*/"Quiet Mode": {
value: settings.mode || 2,
min: 1, // don't allow choosing 0-Noisy
max: modes.length - 1,
format: v => modes[v],
onchange: v => {
settings.mode = v;
updateSettings();
}
}
};
return mainmenu;
}
E.showMenu(buildMainMenu());
});

View File

@ -1,3 +1,4 @@
1.00: Release (2021/12/01)
1.01: Grey font when timer is frozen (2021/12/04)
1.02: Force light theme, since the app is not designed for dark theme (2022/12/28)
1.03: Minor code improvements

View File

@ -124,7 +124,6 @@ Bangle.on('swipe',(swiperight, swipedown)=>{
}
});
var drawTimeout;
var showInstructions = true;
function draw() {

View File

@ -2,7 +2,7 @@
"id":"a_speech_timer",
"name":"Speech Timer",
"icon": "app.png",
"version":"1.02",
"version": "1.03",
"description": "A timer designed to help keeping your speeches and presentations to time.",
"tags": "tool,timer",
"readme":"README.md",

View File

@ -12,3 +12,4 @@
0.12: Actual pixels as of 29th Nov 2021
0.13: Bangle.js 2: Use setUI to add software back button
0.14: Add automatic translation of more strings
0.15: Minor code improvements

View File

@ -20,11 +20,11 @@ function getVersion(name,file) {
return v?(name+" "+(v?"v"+v:"Unknown")):"NO "+name;
}
var versions = [
/*var versions = [
getVersion("Bootloader","boot.info"),
getVersion("Launcher","launch.info"),
getVersion("Settings","setting.info")
];
];*/
var logo = E.toArrayBuffer(atob("PBwBAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAD/w+AAAAQAHA4hAAAAQAMAMhAAAAQAYBmhAAAAQAYBGiAAAAQAQCD/H74+R4wGDhoKJCSEwEDgoKJCT8wFDgoKJCSAwHDhoKJCSEQHj/H6I+R4YHmAAAACAAYEGAAABCAAMEMAAAA8AAHA4AAAAAAAD/wAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/gAAAAAAAB/g"));
var imageTop = 24;

View File

@ -1,7 +1,7 @@
{
"id": "about",
"name": "About",
"version": "0.14",
"version": "0.15",
"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",

View File

@ -3,3 +3,4 @@
Calculate the time moving in graph display
Trigger on 1.04g now, and record 10 samples before trigger
0.03: Bangle.js 2 compatibility
0.04: Minor code improvements

View File

@ -1,4 +1,4 @@
var acc;
//var acc;
var HZ = 100;
var SAMPLES = 5*HZ; // 5 seconds
var SCALE = 5000;

View File

@ -2,7 +2,7 @@
"id": "accelrec",
"name": "Acceleration Recorder",
"shortName": "Accel Rec",
"version": "0.03",
"version": "0.04",
"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": "",

View File

@ -1,3 +1,5 @@
0.01: New App!
0.02: Faster maze generation
0.03: Avoid clearing bottom widgets
0.04: Minor code improvements
0.05: Minor code improvements

View File

@ -54,7 +54,7 @@ function Maze(n) {
// Abort if BTN1 pressed [grace period for menu]
// (for some reason setWatch() fails inside constructor)
if (ngroups<n*n-16 && digitalRead(BTN1)) {
aborting = true;
//aborting = true;
return;
}
from_group = to_group = -1;
@ -206,7 +206,7 @@ function Maze(n) {
return false;
};
this.tick = function() {
accel = Bangle.getAccel();
let accel = Bangle.getAccel();
if (this.ball_x%this.wall_length) {
this.try_move_horizontally(accel.x);
} else if (this.ball_y%this.wall_length) {
@ -243,7 +243,7 @@ function timeToText(t) { // Courtesy of stopwatch app
return text;
}
let aborting = false;
//let aborting = false;
let start_time = 0;
let duration = 0;
let maze=null;
@ -261,13 +261,13 @@ Bangle.drawWidgets();
Bangle.setLocked(false);
Bangle.setLCDTimeout(0);
E.showMenu(mazeMenu);
let maze_interval = setInterval(
/*let maze_interval =*/ setInterval(
function() {
if (maze) {
if (digitalRead(BTN1) || maze.status==STATUS_ABORTED) {
maze = null;
start_time = duration = 0;
aborting = false;
//aborting = false;
setTimeout(function() {E.showMenu(mazeMenu); }, 100);
return;
}

View File

@ -1,7 +1,7 @@
{ "id": "acmaze",
"name": "AccelaMaze",
"shortName":"AccelaMaze",
"version":"0.03",
"version": "0.05",
"description": "Tilt the watch to roll a ball through a maze.",
"icon": "app.png",
"tags": "game",

View File

@ -7,3 +7,5 @@
0.07: Added settings to be able to hide line1 and line2 so there is no visible widget
0.08: Fixed zero steps issue caused by 0.07
0.09: Prettied up user interface, decluttered graphs
0.10: Minor code improvements
0.11: Minor code improvements

View File

@ -136,7 +136,7 @@
function drawMenu() {
var x = 100;
var y = 24;
var stps ="-";
//var stps ="-";
var y_inc = 25;
g.clear();

View File

@ -2,7 +2,7 @@
"id": "activepedom",
"name": "Active Pedometer",
"shortName": "Active Pedometer",
"version": "0.09",
"version": "0.11",
"description": "(NOT RECOMMENDED) 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. The `Health` app now provides step logging and graphs.",
"icon": "app.png",
"tags": "outdoors,widget",

View File

@ -3,7 +3,7 @@
var startTimeStep = new Date(); //set start time
var stopTimeStep = 0; //Time after one step
var timerResetActive = 0; //timer to reset active
var timerStoreData = 0; //timer to store data
//var timerStoreData = 0; //timer to store data
var steps = 0; //steps taken
var stepsCounted = 0; //active steps counted
var active = 0; //x steps in y seconds achieved
@ -32,10 +32,10 @@
}
function storeData() {
now = new Date();
month = now.getMonth() + 1; //month is 0-based
let now = new Date();
let month = now.getMonth() + 1; //month is 0-based
if (month < 10) month = "0" + month; //leading 0
filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; //new file for each day
let filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data"; //new file for each day
dataFile = s.open(filename,"a");
if (dataFile) { //check if filen already exists
if (dataFile.getLength() == 0) {
@ -223,6 +223,7 @@
});
// Read data from file and set variables
{ // new scope ensures pedomData gets freed
let pedomData = s.readJSON(PEDOMFILE,1);
if (pedomData) {
if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate);
@ -231,10 +232,10 @@
stepsTooLong = pedomData.stepsTooLong;
stepsOutsideTime = pedomData.stepsOutsideTime;
}
pedomdata = 0; //reset pedomdata to save memory
}
setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive)
timerStoreData = setInterval(storeData, storeDataInterval); //store data regularly
/*timerStoreData =*/ setInterval(storeData, storeDataInterval); //store data regularly
//Add widget, use: WIDGETS.activepedom.getSteps() inside another App to return todays step count
WIDGETS["activepedom"]={area:"tl",width:width,draw:draw, getSteps:()=>stepsCounted};
})();

View File

@ -9,3 +9,4 @@
0.09: New app screen (instead of showing settings or the alert) and some optimisations
0.10: Add software back button via setUI
0.11: Add setting to unlock screen
0.12: Fix handling that dates can be given as ms since epoch.

View File

@ -29,16 +29,13 @@ exports.loadData = function () {
dismissDate: new Date(1970),
pauseDate: new Date(1970),
},
require("Storage").readJSON("activityreminder.data.json") || {});
if (typeof (data.stepsDate) == "string")
data.stepsDate = new Date(data.stepsDate);
if (typeof (data.okDate) == "string")
data.okDate = new Date(data.okDate);
if (typeof (data.dismissDate) == "string")
data.dismissDate = new Date(data.dismissDate);
if (typeof (data.pauseDate) == "string")
data.pauseDate = new Date(data.pauseDate);
data.stepsDate = new Date(typeof data.stepsDate === 'string' ? data.stepsDate : data.stepsDate.ms);
data.okDate = new Date(typeof data.okDate === 'string' ? data.okDate : data.okDate.ms);
data.dismissDate = new Date(typeof data.dismissDate === 'string' ? data.dismissDate : data.dismissDate.ms);
data.pauseDate = new Date(typeof data.pauseDate === 'string' ? data.pauseDate : data.pauseDate.ms);
return data;
};

View File

@ -3,7 +3,7 @@
"name": "Activity Reminder",
"shortName":"Activity Reminder",
"description": "A reminder to take short walks for the ones with a sedentary lifestyle",
"version":"0.11",
"version":"0.12",
"icon": "app.png",
"type": "app",
"tags": "tool,activity",

View File

@ -3,3 +3,4 @@
0.03: Tell clock widgets to hide.
0.04: Swipe down to see widgets, step counter now just uses getHealthStatus
0.05: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
0.06: Use watch temperature

View File

@ -3,8 +3,7 @@
<img src="https://user-images.githubusercontent.com/2981891/175355586-1dfc0d66-6555-4385-b124-1605fdb71a11.jpg" width="250" />
An over-engineered clock inspired by Casio watches.<br/>
It has a dedicated timer, a scratchpad and can display the weather condition 4 days ahead.<br/>
It uses a <a target="_blank" href="https://dotgreg.github.io/advCasioBangleClock/">custom web app</a> to update its content.<br/>
It has a dedicated timer, a scratchpad and displays the current temperature.<br/>
Forked from the awesome Cassio Watch.<br/>
## Todo
@ -21,7 +20,7 @@ Forked from the awesome Cassio Watch.<br/>
- Footsteps
- Battery
- Simple Timer embedded
- Weather forecast (7 days)
- Current temperature
- Scratchpad
## Screenshots
@ -36,14 +35,6 @@ Web interface to update weather & scratchpad <br/>
<img src="https://user-images.githubusercontent.com/2981891/175519121-851bb209-7192-40db-a014-490c344f7597.jpg" width="250" />
## Usage
### How to update the tasks list / weather
- you will need a <a target="_blank" href="https://openweathermap.org/price#weather">free openweathermap.org api key</a>.
- go to https://dotgreg.github.io/advCasioBangleClock/
- Alternatively you can install it on your own server/heroku/service/github pages, the web-app code is <a target="_blank" href="https://github.com/dotgreg/advCasioBangleClock/tree/master/web-app">here</a>
- fill the location and the api key (it will be saved on your browser, no need to do it each time)
- edit the scratchpad with what you want
- click on sync
- reload your clock!
### How to start/stop the timer
- swipe up : add time (+5min)

View File

@ -88,9 +88,9 @@ function drawRocket() {
function getTemperature(){
try {
var weatherJson = storage.readJSON('weather.json');
var weather = weatherJson.weather;
return Math.round(weather.temp-273.15);
var temperature = E.getTemperature()
var formatted = require("locale").temp(temperature).replace(/[^\d-]/g, '');
return formatted;
} catch(ex) {
print(ex)

View File

@ -1,8 +1,8 @@
{ "id": "advcasio",
"name": "Advanced Casio Clock",
"shortName":"advcasio",
"version":"0.05",
"description": "An over-engineered clock inspired by Casio watches. It has a 4 days weather, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.",
"version":"0.06",
"description": "An over-engineered clock inspired by Casio watches. It has current temperature, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.",
"icon": "app.png",
"tags": "clock",
"type": "clock",
@ -18,8 +18,5 @@
"storage": [
{"name":"advcasio.app.js","url":"app.js"},
{"name":"advcasio.img","url":"app-icon.js","evaluate":true}
],
"data": [
{ "name": "advcasio.data.json", "url": "data.json", "storageFile": true }
]
}

View File

@ -14,3 +14,4 @@
0.12: Added color field and updating clkinfo periodically (running events)
0.13: Show day of the week in date
0.14: Fixed "Today" and "Yesterday" wrongly displayed for allDay events on some time zones
0.15: Minor code improvements

View File

@ -15,14 +15,14 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
var FILE = "android.calendar.json";
//var FILE = "android.calendar.json";
var Locale = require("locale");
var fontSmall = "6x8";
//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 fontLarge = g.getFonts().includes("6x15")?"6x15:2":"6x8:4";
//FIXME maybe write the end from GB already? Not durationInSeconds here (or do while receiving?)
var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[];

View File

@ -1,7 +1,7 @@
{
"id": "agenda",
"name": "Agenda",
"version": "0.14",
"version": "0.15",
"description": "Simple agenda",
"icon": "agenda.png",
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],

View File

@ -49,3 +49,4 @@
0.44: Add "delete timer after expiration" setting to events.
0.45: Fix new alarm when selectedAlarm is undefined
0.46: Show alarm groups if the Show Group setting is ON. Scroll alarms menu back to previous position when getting back to it.
0.47: Fix wrap around when snoozed through midnight

View File

@ -28,6 +28,8 @@ const iconTimerOff = "\0" + (g.theme.dark
// An array of alarm objects (see sched/README.md)
var alarms = require("sched").getAlarms();
// Fix possible wrap around in existing alarms #3281, broken alarms still needs to be saved to get fixed
alarms.forEach(e => e.t %= 86400000); // This can probably be removed in the future when we are sure there are no more broken alarms
function handleFirstDayOfWeek(dow) {
if (firstDayOfWeek == 1) {
@ -497,7 +499,7 @@ function showEditTimerMenu(selectedTimer, timerIndex) {
function prepareTimerForSave(timer, timerIndex, time, temp) {
timer.timer = require("time_utils").encodeTime(time);
timer.t = require("time_utils").getCurrentTimeMillis() + timer.timer;
timer.t = (require("time_utils").getCurrentTimeMillis() + timer.timer) % 86400000;
timer.last = 0;
if (!temp) {

View File

@ -2,7 +2,7 @@
"id": "alarm",
"name": "Alarms & Timers",
"shortName": "Alarms",
"version": "0.46",
"version": "0.47",
"description": "Set alarms and timers on your Bangle",
"icon": "app.png",
"tags": "tool,alarm",

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: Added adjustment for Bangle.js magnetometer heading fix
0.03: Minor code improvements

View File

@ -145,7 +145,7 @@ Bangle.setCompassPower(1);
Bangle.setGPSPower(1);
g.clear();
process_GPS();
var poll_GPS = setInterval(process_GPS, 9000);
/*var poll_GPS =*/ setInterval(process_GPS, 9000);
setWatch(function () {
if (!button_lock) {

View File

@ -1,7 +1,7 @@
{
"id": "alpinenav",
"name": "Alpine Nav",
"version": "0.02",
"version": "0.03",
"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",

View File

@ -0,0 +1,2 @@
0.01: New Clock!
0.02: Fix fastloading memory leak and clockinfo overwritten by hands

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEw4X//8HA4IEBgH4C5cFqgJHitQjWpBY9q0gLvI5ar/AAkgBRMC1ALJlX6CxOrBZMq34LJ1f/9QKHhW//2gCxP6wAWHy/+KREqq4WIgGtr+qLhG1vw5IgX1KBALBywWIIwNaHJEAlNqUZOltAuJyouKqwuKrQuhywuJNIIuJlIuJHQLGIBYQ6IgtU1Q6GitQjWplQVGtWkBYIhHBcpHBBY5HBM5IABA"))

259
apps/analogquadclk/app.js Normal file
View File

@ -0,0 +1,259 @@
{
const W = g.getWidth();
const H = g.getHeight();
const background = require("clockbg"); // image backgrounds
let drawTimeout; // timeout used to update every minute
let date = new Date(); // date at last draw
let lastModified = {x1:0,y1:0,x2:W-1,y2:H-1,first:true}; // rect that was covered by hands
const HOUR_LEN = 55; // how far forwards does hand go?
const MIN_LEN = 72;
const HOUR_BACK = 10; // how far backwards dows hand go?
const MIN_BACK = 10;
const HOUR_W = 10; // width of cleared area
const MIN_W = 8;
const get_hand = function(len, w, cornerw, overhang) {
return new Int8Array([
0, overhang+w,
-cornerw, overhang+cornerw,
-w, overhang,
-w, -len,
-cornerw, -len - cornerw,
0, -len - w,
cornerw, -len - cornerw,
w, -len,
w, overhang,
cornerw, overhang+cornerw
]);
};
const hand_hour = get_hand(HOUR_LEN, 6, 4, HOUR_BACK);
const hand_hour_bg = get_hand(HOUR_LEN, HOUR_W, 8, HOUR_BACK);
const hand_minute = get_hand(MIN_LEN, 4, 3, MIN_BACK);
const hand_minute_bg = get_hand(MIN_LEN, MIN_W, 6, MIN_BACK);
// schedule a draw for the next minute
let queueDraw = function() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
};
// draw the clock hands
let drawHands = function() {
let h = (date.getHours() + date.getMinutes()/60)*Math.PI/6, m = date.getMinutes()*Math.PI/30;
g.setColor(g.theme.bg).fillPolyAA(g.transformVertices(hand_hour_bg,{x:W/2,y:H/2,rotate:h}));
g.fillPolyAA(g.transformVertices(hand_minute_bg,{x:W/2,y:H/2,rotate:m}));
g.setColor("#f00").fillPolyAA(g.transformVertices(hand_hour,{x:W/2,y:H/2,rotate:h}));
g.setColor(g.theme.fg).fillPolyAA(g.transformVertices(hand_minute,{x:W/2,y:H/2,rotate:m}));
};
// return the screen area covered by clock hands (used for filling in background)
let getHandBounds = function() {
let h = (date.getHours() + date.getMinutes()/60)*Math.PI/6, m = date.getMinutes()*Math.PI/30;
let sh = Math.sin(h), ch = Math.cos(h), sm = Math.sin(m), cm = Math.cos(m);
return {
x1 : Math.round((W/2)+Math.min(sh*HOUR_LEN, sm*MIN_LEN, -sh*HOUR_BACK, -sm*MIN_BACK)-HOUR_W),
y1 : Math.round((H/2)-Math.max(ch*HOUR_LEN, cm*MIN_LEN, -ch*HOUR_BACK, -cm*MIN_BACK)-HOUR_W),
x2 : Math.round((W/2)+Math.max(sh*HOUR_LEN, sm*MIN_LEN, -sh*HOUR_BACK, -sm*MIN_BACK)+HOUR_W),
y2 : Math.round((H/2)-Math.min(ch*HOUR_LEN, cm*MIN_LEN, -ch*HOUR_BACK, -cm*MIN_BACK)+HOUR_W),
};
};
let draw = function() {
// queue next draw in one minute
queueDraw();
// work out locale-friendly date/time
date = new Date();
//var timeStr = require("locale").time(date,1);
//var dateStr = require("locale").date(date);
// fill in area that we changed last time
background.fillRect(lastModified.x1, lastModified.y1, lastModified.x2, lastModified.y2);
if (!lastModified.first) { // first draw we don't have clockInfoMenuA/etc defined
//print(lastModified);
if (lastModified.y1<40) {
if (lastModified.x1 < 40 ||
(lastModified.x1 < W/2 && lastModified.y1 < 16)) clockInfoMenuA.redraw();
if (lastModified.x2 > W-40 ||
(lastModified.x1 > W/2 && lastModified.y1 < 16)) clockInfoMenuB.redraw();
}
if (lastModified.y2>W-40) {
if (lastModified.x1 < 40 ||
(lastModified.x1 < W/2 && lastModified.y2>W-16)) clockInfoMenuD.redraw();
if (lastModified.x2 > W-40 ||
(lastModified.x1 > W/2 && lastModified.y2>W-16)) clockInfoMenuC.redraw();
}
}
// draw hands
drawHands();
lastModified = getHandBounds();
//g.drawRect(lastModified); // debug
};
// Clear the screen once, at startup
background.fillRect(0, 0, W - 1, H - 1);
// draw immediately at first, queue update
draw();
let clockInfoMenuA, clockInfoMenuB, clockInfoMenuC, clockInfoMenuD;
// Show launcher when middle button pressed
Bangle.setUI({
mode: "clock",
remove: function() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
if (clockInfoMenuA) clockInfoMenuA.remove();
if (clockInfoMenuB) clockInfoMenuB.remove();
if (clockInfoMenuC) clockInfoMenuC.remove();
if (clockInfoMenuD) clockInfoMenuD.remove();
require("widget_utils").show(); // re-show widgets
}
});
// Load widgets
Bangle.loadWidgets();
require("widget_utils").hide();
// used for clockinfo image rendering
let clockInfoG = Graphics.createArrayBuffer(28, 28, 2, {msb:true});
clockInfoG.transparent = 3;
// render clockinfos
let clockInfoDraw = function(itm, info, options) {
// itm: the item containing name/hasRange/etc
// info: data returned from itm.get() containing text/img/etc
// options: options passed into addInteractive
const left = options.x < 88,
top = options.y < 88,
imgx = left ? 1 : W - 28, imgy = top ? 19 : H - 42,
textx = left ? 2 : W - 1, texty = top ? 2 : H - 16;
let bg = g.theme.bg, fg = g.theme.fg;
// Clear the background
g.reset();
background.fillRect(imgx, imgy, imgx+25, imgy+25); // erase image
background.fillRect(left?0:W/2, texty-1, left?W/2:W-1, texty+15); // erase text
// indicate focus - change colours
if (options.focus) {
bg = g.theme.fg;
fg = g.toColor("#f00");
}
if (info.img) {
//g.drawImage(info.img, left ? 2 : W - 27, top ? 18 : H - 41); // draw the image
// fiddle around colouring the border and inside of the image
clockInfoG.clear(1);
// do a border - images need to be transparent for this
clockInfoG.setColor(2).drawImage(info.img, 1,1).drawImage(info.img, 3,1).
drawImage(info.img, 1,3).drawImage(info.img, 3,3);
clockInfoG.setColor(1).drawImage(info.img, 2,2); // main image
clockInfoG.floodFill(27,27,3); // flood fill edge to transparent
clockInfoG.palette = new Uint16Array([bg,fg,bg/*border*/, g.toColor("#888")]);
g.drawImage(clockInfoG, imgx-1, imgy-1);
}
g.setFont("6x8:2").setFontAlign(left ? -1 : 1, -1);
g.setColor(bg).drawString(info.text, textx-2, texty). // draw the text background
drawString(info.text, textx+2, texty).
drawString(info.text, textx, texty-2).
drawString(info.text, textx, texty+2);
g.setColor(fg).drawString(info.text, textx, texty); // draw the text
// redraw hands if needed
if ((top && lastModified.x1<texty+15) ||
(!top && lastModified.y2>=texty)) {
g.reset();
drawHands();
}
};
// Load the clock infos
let clockInfoItems = require("clock_info").load();
let clockInfoItemsBangle = clockInfoItems.find(i=>i.name=="Bangle");
// Add extra Calendar and digital clock ClockInfos
if (clockInfoItemsBangle) {
if (!clockInfoItemsBangle.items.find(i=>i.name=="Date")) {
clockInfoItemsBangle.items.push({ name : "Date",
get : () => {
let d = new Date();
let g = Graphics.createArrayBuffer(24,24,1,{msb:true});
g.drawImage(atob("FhgBDADAMAMP/////////////////////8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAP///////"),1,0);
g.setFont("6x15").setFontAlign(0,0).drawString(d.getDate(),11,17);
return {
text : require("locale").dow(d,1).toUpperCase(),
img : g.asImage("string")
};
},
show : function() {
this.interval = setTimeout(()=>{
this.emit("redraw");
this.interval = setInterval(()=>{
this.emit("redraw");
}, 86400000);
}, 86400000 - (Date.now() % 86400000));
},
hide : function() {
clearInterval(this.interval);
this.interval = undefined;
}
});
}
if (!clockInfoItemsBangle.items.find(i=>i.name=="Clock")) {
clockInfoItemsBangle.items.push({ name : "Clock",
get : () => {
return {
text : require("locale").time(new Date(),1),
img : atob("GBiBAAAAAAB+AAD/AAD/AAH/gAP/wAP/wAYAYAYAYAYAYAYAYAYAcAYAcAYAYAYAYAYAYAYAYAP/wAP/wAH/gAD/AAD/AAB+AAAAAA==")
};
},
show : function() {
this.interval = setTimeout(()=>{
this.emit("redraw");
this.interval = setInterval(()=>{
this.emit("redraw");
}, 60000);
}, 60000 - (Date.now() % 60000));
},
hide : function() {
clearInterval(this.interval);
this.interval = undefined;
}
});
}
}
// Add the 4 clockinfos
const CLOCKINFOSIZE = 50;
clockInfoMenuA = require("clock_info").addInteractive(clockInfoItems, {
x: 0,
y: 0,
w: CLOCKINFOSIZE,
h: CLOCKINFOSIZE,
draw: clockInfoDraw
});
clockInfoMenuB = require("clock_info").addInteractive(clockInfoItems, {
x: W - CLOCKINFOSIZE,
y: 0,
w: CLOCKINFOSIZE,
h: CLOCKINFOSIZE,
draw: clockInfoDraw
});
clockInfoMenuC = require("clock_info").addInteractive(clockInfoItems, {
x: W - CLOCKINFOSIZE,
y: H - CLOCKINFOSIZE,
w: CLOCKINFOSIZE,
h: CLOCKINFOSIZE,
draw: clockInfoDraw
});
clockInfoMenuD = require("clock_info").addInteractive(clockInfoItems, {
x: 0,
y: H - CLOCKINFOSIZE,
w: CLOCKINFOSIZE,
h: CLOCKINFOSIZE,
draw: clockInfoDraw
});
/*setInterval(function() {
date.ms += 60000; draw();
}, 500);*/
}

BIN
apps/analogquadclk/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,16 @@
{ "id": "analogquadclk",
"name": "Analog Quad Clock",
"shortName":"Quad Clock",
"version":"0.02",
"description": "An analog clock with clockinfos in each of the 4 corners, allowing 4 different data types to be rendered at once",
"icon": "icon.png",
"screenshots" : [ { "url":"screenshot.png" }, { "url":"screenshot2.png" } ],
"type": "clock",
"tags": "clock,clkinfo,analog",
"supports" : ["BANGLEJS2"],
"dependencies" : { "clock_info":"module", "clockbg":"module" },
"storage": [
{"name":"analogquadclk.app.js","url":"app.js"},
{"name":"analogquadclk.img","url":"app-icon.js","evaluate":true}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -104,7 +104,6 @@ Bangle.on('lcdPower',on=>{
if (on) {
secondInterval = setInterval(draw, 1000);
draw(); // draw immediately
}else{
}
});
Bangle.on('lock',on=>{

View File

@ -33,3 +33,4 @@
0.31: Implement API for activity fetching
0.32: Added support for loyalty cards from gadgetbridge
0.33: Fix alarms created in Gadgetbridge not repeating
0.34: Implement API for activity tracks fetching (Recorder app logs).

View File

@ -44,6 +44,10 @@ The boot code also provides some useful functions:
* `id` - a custom (string) ID
* `timeout` - a timeout for the request in milliseconds (default 30000ms)
* `xpath` an xPath query to run on the request (but right now the URL requested must be XML - HTML is rarely XML compliant)
* `return` for xpath, if not specified, one result is returned. If `return:"array"` an array of results is returned.
* `method` HTTP method (default is `get`) - `get/post/head/put/patch/delete`
* `body` the body of the HTTP request
* `headers` an object of headers, eg `{HeaderOne : "headercontents"}`
eg:

View File

@ -16,10 +16,12 @@
if (settings.vibrate == undefined) settings.vibrate = "..";
require('Storage').writeJSON("android.settings.json", settings);
var _GB = global.GB;
let fetchRecInterval;
global.GB = (event) => {
// feed a copy to other handlers if there were any
if (_GB) setTimeout(_GB,0,Object.assign({},event));
/* TODO: Call handling, fitness */
var HANDLERS = {
// {t:"notify",id:int, src,title,subject,body,sender,tel:string} add
@ -230,6 +232,49 @@
}
gbSend({t: "actfetch", state: "end", count: actCount});
},
//{t:"listRecs", id:"20230616a"}
"listRecs": function() {
let recs = require("Storage").list(/^recorder\.log.*\.csv$/,{sf:true}).map(s => s.slice(12, 21));
if (event.id.length > 2) { // Handle if there was no id supplied. Then we send a list all available recorder logs back.
let firstNonsyncedIdx = recs.findIndex((logId) => logId > event.id);
if (-1 == firstNonsyncedIdx) {
recs = []
} else {
recs = recs.slice(firstNonsyncedIdx);
}
}
gbSend({t:"actTrksList", list: recs}); // TODO: split up in multiple transmissions?
},
//{t:"fetchRec", id:"20230616a"}
"fetchRec": function() {
// TODO: Decide on what names keys should have.
if (fetchRecInterval) {
clearInterval(fetchRecInterval);
fetchRecInterval = undefined;
}
if (event.id=="stop") {
return
} else {
let log = require("Storage").open("recorder.log"+event.id+".csv","r");
let lines = "init";// = log.readLine();
let pkgcnt = 0;
gbSend({t:"actTrk", log:event.id, lines:"erase", cnt:pkgcnt}); // "erase" will prompt Gadgetbridge to erase the contents of a already fetched log so we can rewrite it without keeping lines from the previous (probably failed) fetch.
let sendlines = ()=>{
lines = log.readLine();
for (var i = 0; i < 3; i++) {
let line = log.readLine();
if (line) lines += line;
}
pkgcnt++;
gbSend({t:"actTrk", log:event.id, lines:lines, cnt:pkgcnt});
if (!lines && fetchRecInterval) {
clearInterval(fetchRecInterval);
fetchRecInterval = undefined;
}
}
fetchRecInterval = setInterval(sendlines, 50)
}
},
"nav": function() {
event.id="nav";
if (event.instr) {

View File

@ -2,7 +2,7 @@
"id": "android",
"name": "Android Integration",
"shortName": "Android",
"version": "0.33",
"version": "0.34",
"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,gadgetbridge",

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Minor code improvements

View File

@ -4,8 +4,6 @@ var avrAngle = undefined;
var history = [];
var R = Bangle.appRect;
var W = g.getWidth();
var H = g.getHeight();
var relativeTo = undefined;
function draw(v) {

View File

@ -2,7 +2,7 @@
"id": "angles",
"name": "Angles (Spirit Level)",
"shortName": "Angles",
"version": "0.01",
"version": "0.02",
"description": "Shows Angle or Relative angle in degrees (Digital Protractor/Inclinometer). Place Bangle sideways against a surface with the button facing away for best readings.",
"icon": "icon.png",
"screenshots": [{"url":"screenshot.png"}],

View File

@ -3,3 +3,4 @@
0.03: Update to use setUI
0.04: Tell clock widgets to hide. Move loadWidgets() so it only runs on
startup and not on every draw.
0.05: Minor code improvements

View File

@ -16,7 +16,6 @@ var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
var IX = 80, IY = 10, IBPP = 1;
var IW = 174, IH = 45, OY = 24;
var inf = {align:0};
var bgoptions;
require("Font7x11Numeric7Seg").add(Graphics);
var cg = Graphics.createArrayBuffer(IW,IH,IBPP,{msb:true});

View File

@ -2,7 +2,7 @@
"id": "animclk",
"name": "Animated Clock",
"shortName": "Anim Clock",
"version": "0.04",
"version": "0.05",
"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",

View File

@ -13,3 +13,4 @@
0.09: Use default Bangle formatter for booleans
0.10: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16
Modified to avoid leaving functions defined when using setUI({remove:...})
0.11: Minor code improvements

View File

@ -107,7 +107,7 @@ let isoStr = function(date) {
let calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested)
let ISO8601calWeek = function(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
dateNoTime = date; dateNoTime.setHours(0,0,0,0);
const dateNoTime = date; dateNoTime.setHours(0,0,0,0);
if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2];
calWeekBuffer[0] = date.getTimezoneOffset();
calWeekBuffer[1] = dateNoTime;

View File

@ -2,7 +2,7 @@
"id": "antonclkplus",
"name": "Anton Clock Plus",
"shortName": "Anton Clock+",
"version": "0.10",
"version": "0.11",
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
"readme":"README.md",
"icon": "app.png",

View File

@ -2,3 +2,4 @@
0.2: Added more descriptive approximations
0.2f: Bug fixes: Incorrect hour drawn after 50 mins, incorrect quarter minute drawn after 50 mins
0.3: Added touch interaction to display exact time and date.
0.04: Minor code improvements

Some files were not shown because too many files have changed in this diff Show More