Merge remote-tracking branch 'upstream/master' into no-unused-vars

pull/3213/head
Anton 2024-03-04 22:39:25 +01:00
commit f16bf3d351
92 changed files with 757 additions and 113 deletions

View File

@ -149,7 +149,7 @@ module.exports = {
],
"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-prototype-builtins": "off",

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

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

View File

@ -6,3 +6,4 @@
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
0.09: Minor code improvements

View File

@ -270,8 +270,7 @@ function queueDraw() {
function draw() {
if (pause){}
else{
if (!pause){
// get date
var d = new Date();
var da = d.toString().split(" ");

View File

@ -2,7 +2,7 @@
"id": "aptsciclk",
"name": "Apeture Science Clock",
"shortName":"AptSci Clock",
"version": "0.08",
"version": "0.09",
"description": "A clock based on the portal series",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],

1
apps/autoreset/ChangeLog Normal file
View File

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

21
apps/autoreset/README.md Normal file
View File

@ -0,0 +1,21 @@
# Auto Reset
Sets a timeout to load the clock face. The timeout is stopped and started again upon user input.
## Usage
Install with app loader and Auto Reset will run in background. If you don't interact with the watch it will time out to the clock face after 10 minutes.
## TODO
- Add settings page
- set how many minutes the timeout should count down.
- whitelist/blacklist for apps.
## Requests
Mention @thyttan in an issue on the espruino/BangleApps repo for bug reports and feature requests.
## Creator
thyttan

BIN
apps/autoreset/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

20
apps/autoreset/boot.js Normal file
View File

@ -0,0 +1,20 @@
{
let timeoutAutoreset;
let resetTimeoutAutoreset = (force)=>{
if (timeoutAutoreset) clearTimeout(timeoutAutoreset);
setTimeout(()=>{ // Short outer timeout to make sure we have time to leave clock face before checking `Bangle.CLOCK!=1`.
if (Bangle.CLOCK!=1) { // Only add timeout if not already on clock face.
timeoutAutoreset = setTimeout(()=>{
if (Bangle.CLOCK!=1) Bangle.showClock();
}, 10*60*1000);
}
},200);
};
Bangle.on('touch', resetTimeoutAutoreset);
Bangle.on('swipe', resetTimeoutAutoreset);
Bangle.on('message', resetTimeoutAutoreset);
setWatch(resetTimeoutAutoreset, BTN, {repeat:true, edge:'rising'});
if (Bangle.CLOCK!=1) resetTimeoutAutoreset();
}

View File

@ -0,0 +1,13 @@
{ "id": "autoreset",
"name": "Auto Reset",
"version":"0.01",
"description": "Sets a timeout to load the clock face. The timeout is stopped and started again upon user input.",
"icon": "app.png",
"type": "bootloader",
"tags": "system",
"supports" : ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"autoreset.boot.js","url":"boot.js"}
]
}

View File

@ -1,4 +1,5 @@
0.01: Added app
0.02: Removed unneeded squares
0.03: Added settings with fullscreen option
0.04: Minor code improvements
0.03: Added setting for fullscreen option
0.04: Added settings to hide unused squares and show date
0.05: Minor code improvements

View File

@ -1,11 +1,15 @@
var settings = Object.assign({
fullscreen: false,
fullscreen: false,
hidesq: false,
showdate: false,
}, require('Storage').readJSON("binaryclk.json", true) || {});
function draw() {
var dt = new Date();
var h = dt.getHours(), m = dt.getMinutes();
var h = dt.getHours(), m = dt.getMinutes(), d = dt.getDate();
const t = [];
t[0] = Math.floor(h/10);
t[1] = Math.floor(h%10);
t[2] = Math.floor(m/10);
@ -17,25 +21,44 @@ function draw() {
let i = 0;
var gap = 8;
var mgn = 20;
if (settings.fullscreen) {
gap = 12;
mgn = 0;
}
const sq = 29;
var pos = sq + gap;
for (let r = 3; r >= 0; r--) {
for (let c = 0; c < 4; c++) {
if (t[c] & Math.pow(2, r)) {
g.fillRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq);
g.fillRect(Math.floor(mgn/2) + gap + c * pos, mgn + gap + i * pos, Math.floor(mgn/2) + gap + c * pos + sq, mgn + gap + i * pos + sq);
} else {
g.drawRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq);
g.drawRect(Math.floor(mgn/2) + gap + c * pos, mgn + gap + i * pos, Math.floor(mgn/2) + gap + c * pos + sq, mgn + gap + i * pos + sq);
}
}
i++;
}
g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq);
g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq);
var c1sqhide = 0;
var c3sqhide = 0;
if (settings.hidesq) {
c1sqhide = 2;
c3sqhide = 1;
}
if (settings.hidesq) {
g.clearRect(Math.floor(mgn/2), mgn, Math.floor(mgn/2) + pos, mgn + c1sqhide * pos);
g.clearRect(Math.floor(mgn/2) + 2 * pos + gap, mgn, Math.floor(mgn/2) + 3 * pos, mgn + c3sqhide * pos);
}
if (settings.showdate) {
g.setFontAlign(0, 0);
g.setFont("Vector",20);
g.drawRect(Math.floor(mgn/2) + gap, mgn + gap, Math.floor(mgn/2) + gap + sq, mgn + gap + sq);
g.drawString(d, Math.ceil(mgn/2) + gap + Math.ceil(sq/2) + 1, mgn + gap + Math.ceil(sq/2) + 1);
}
}
g.clear();

View File

@ -1,8 +1,8 @@
{
"id": "binaryclk",
"name": "Bin Clock",
"version": "0.04",
"description": "Clock face to show binary time in 24 hr format",
"version": "0.05",
"description": "Clock face to show binary time in 24 hour format",
"icon": "app-icon.png",
"screenshots": [{"url":"screenshot.png"}],
"type": "clock",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -2,6 +2,8 @@
var FILE = "binaryclk.json";
var settings = Object.assign({
fullscreen: false,
hidesq: false,
showdate: false,
}, require('Storage').readJSON(FILE, true) || {});
function writeSettings() {
@ -16,7 +18,21 @@
onchange: v => {
settings.fullscreen = v;
writeSettings();
}
},
},
'Hide Squares': {
value: settings.hidesq,
onchange: v => {
settings.hidesq = v;
writeSettings();
},
},
'Show Date': {
value: settings.showdate,
onchange: v => {
settings.showdate = v;
writeSettings();
},
},
});
})

View File

@ -1,4 +1,4 @@
0.01: Car Crazy is now avialable for testing in beta!
0.02: 10 Levels are now added making the game harder as it goes along. Some of the levels include multiple cars and faster cars. More levels coming soon.
0.03: Settings are now added so that you can reset your high score.
0.04: Minor code improvements
0.04: Minor code improvements.

View File

@ -66,10 +66,8 @@ function moveEnemyPosition(){
enemyPositonCenterX2 = 120;
}else if((randomRoadPositionIndicator2 == 3)){
enemyPositonCenterX2 = 155;
}else if(level == 7||level == 8){
}
}
} // TODO: else if(level == 7)
}
function collision(){

View File

@ -1,3 +1,4 @@
0.01: Simple app to display loyalty cards
0.02: Hiding widgets while showing the code
0.03: Minor code improvements
0.03: Added option to use max brightness when showing code
0.04: Minor code improvements

View File

@ -14,6 +14,14 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
// get brightness
let brightness;
function loadBrightness() {
const getBrightness = require('Storage').readJSON("setting.json", 1) || {};
brightness = getBrightness.brightness || 0.1;
}
//may make it configurable in the future
const WHITE=-1
const BLACK=0
@ -89,6 +97,10 @@ function printLinearCode(binary) {
}
function showCode(card) {
// set to full bright when the setting is true
if(settings.fullBrightness) {
Bangle.setLCDBrightness(1);
}
widget_utils.hide();
E.showScroller();
// keeping it on rising edge would come back twice..
@ -129,6 +141,10 @@ function showCode(card) {
}
function showCard(card) {
// reset brightness to old value after maxing it out
if(settings.fullBrightness) {
Bangle.setLCDBrightness(brightness);
}
var lines = [];
var bodyFont = fontBig;
if(!card) return;
@ -206,4 +222,7 @@ function showList() {
back : () => load()
});
}
if(settings.fullBrightness) {
loadBrightness();
}
showList();

View File

@ -14,6 +14,13 @@
updateSettings();
}
},
/*LANG*/"Full Brightness" : {
value : !!settings.fullBrightness,
onchange: v => {
settings.fullBrightness = v;
updateSettings();
}
}
};
E.showMenu(mainmenu);
})

View File

@ -7,3 +7,4 @@
Improve connection code
0.07: Make Bangle.js 2 compatible
0.08: Convert Yes/No On/Off in settings to checkboxes
0.09: Automatically reconnect on error

View File

@ -226,7 +226,7 @@ function getSensorBatteryLevel(gatt) {
function connection_setup() {
mySensor.screenInit = true;
E.showMessage("Scanning for CSC sensor...");
NRF.requestDevice({ filters: [{services:["1816"]}]}).then(function(d) {
NRF.requestDevice({ filters: [{services:["1816"]}], maxInterval: 100}).then(function(d) {
device = d;
E.showMessage("Found device");
return device.gatt.connect();
@ -249,6 +249,7 @@ function connection_setup() {
}).catch(function(e) {
E.showMessage(e.toString(), "ERROR");
console.log(e);
setTimeout(connection_setup, 1000);
});
}

View File

@ -2,7 +2,7 @@
"id": "cscsensor",
"name": "Cycling speed sensor",
"shortName": "CSCSensor",
"version": "0.08",
"version": "0.09",
"description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch",
"icon": "icons8-cycling-48.png",
"tags": "outdoors,exercise,ble,bluetooth,bike,cycle,bicycle",

View File

@ -5,4 +5,4 @@
0.05: extraneous comments and code removed
display improved
now supports Adjust Clock widget, if installed
0.06: Minor code improvements
0.06: Minor code improvements

View File

@ -223,9 +223,8 @@ function fixTime() {
Bangle.on("GPS",function cb(g) {
Bangle.setGPSPower(0,"time");
Bangle.removeListener("GPS",cb);
if (!g.time || (g.time.getFullYear()<2000) ||
(g.time.getFullYear()>2200)) {
} else {
if (g.time && (g.time.getFullYear()>=2000) &&
(g.time.getFullYear()<=2200)) {
// We have a GPS time. Set time
setTime(g.time.getTime()/1000);
}

7
apps/fallout_clock/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
node_modules/
res/
fallout_clock.code-workspace
package.json
package-lock.json

View File

@ -0,0 +1,5 @@
0.10: (20240125) Basic Working Clock.
0.11: (20240125) Widgets Added. Improved Interval Loop.
0.12: (20240221) Fix: Month Reporting Wrong.
0.20: (20240223) Created as a Package.
0.21: (20240223) Added StandardJS and NPM.

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Zachary D. Skelton <zskelton@skeltonnetworks.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,29 @@
# Fallout Clock
Inspired by the aesthetic of the Fallout series, this clock face looks to emulate the color and feel of a PipBoy.
![clockface](./res/screenshot.png)
## Usage
You can also go into Settings, and choose it as the default clock under **Select Clock**.
## Planned Features:
- Display Steps as Health
- Display Heartrate
- Brighter Color when the backlight is not on.
- Configurable Settings
## Controls
Zero Settings, Zero Configuration. Install and add as your clockface.
## Requests
To request new features, add [an issue](https://github.com/zskelton/fallout_clock/issues).
## Creator
Zachary D. Skelton <zskelton@skeltonnetworks.com>\
[Skelton Networks](https://skeltonnetworks.com)\
[Github](https://github.com/zskelton)

View File

@ -0,0 +1 @@
atob("MDDDAb88//9u/1r/1/YZrgAAit4kkkkkkkkkkAAVIkkkkkkkkkkkkkkkkkkAAAARJJIkkkkkkkkkkkkkkkAAAACJJJJUkkkkkkkkkkkkkAAAAARJJJJAAkkkkkkkkkkkAAAAACpJJJKgAAkkkkkkkkkgAAAAAVJJJJIAAAEkkkkkkkkAAAAACpJfpJUAAAAkkkkkkkgAAAAABJf/9JAAAAAEkkkkkkAAAAAARJdf/+gAAAAAkkkkkgAAAAAC//dL//gAAAAAEkkkkAAAAYADpJJL//8AAAAAAkkkkAAAD8AdJJJL///gAAAAAkkkgAAADr/pJJL////0AAAAAEkkgAAABJJL/pfb////gAAAAAkkAAAADpJeu22X////4AAAAAkkAAAADpL1tttuf/7f8AAAAAkgAAAAb/+ttttuSSS7/AAAAAEgAAAAdeyttttySSSb/gAAAAEgAAAC9eWtttuaySSf/2SSSSkgAAAVfxtttttyySX//9JJJQAAAAAJetttttttyST//9JJJUAAAABJeOaNyNutySW//9JJKgAAAARJdu6N1tvRySS3/JJJUAAAACJJVuVu1tzRyST2/JJKAAAAAVJL1ttyttuNuSWW7pJKgAAACpJLxtt6NtttuSS27pJUAAAAVJJLxtt6ttttuSWT9JKgAAAAJJJLxttzNtttuSST9JIAAAAiJJJL1ttttt2NuSSS9JUAAAA2222212xtty3RySSS9KgAAAEgAAAAZ6OW2tu1ySST9QAAAAEgAAAAaW1ttu2VySSXKAAAAAEkAAAACtu221ttySbdKgAAAAEkAAAADNty1ttuST9JUAAAAAkkAAAAAVty1ttuSXpKAAAAAAkkgAAAACtttttyT9JIAAAAAEkkkAAAAARttttyfdJUAAAAAEkkkAAAAACtttuSzJKgAAAAAkkkkgAAAAAWtuSSfpQAAAAAEkkkkkAAAAADa2yT9JAAAAAAkkkkkkgAAAAD7e3/pKgAAAAAkkkkkkkAAAAVL/9JJUAAAAAEkkkkkkkgAAARJJJJKAAAAAEkkkkkkkkkAAAJJJJJIAAAAAkkkkkkkkkkkACpJJJJUAAAAEkkkkkkkkkkkgCJJJJKgAAAEkkkkkkkkkkkkklJJJJQAAAEkkkkkkkkkkkkkkkkpJJAAEkkkkkkkkk=")

141
apps/fallout_clock/clock.js Normal file
View File

@ -0,0 +1,141 @@
/* global Bangle, Graphics, g */
// NAME: Fallout Clock (Bangle.js 2)
// DOCS: https://www.espruino.com/ReferenceBANGLEJS2
// AUTHOR: Zachary D. Skelton <zskelton@bws-solutions.com>
// VERSION: 0.1.0 (24JAN2024) - Creating [ Maj.Min.Bug ] REF: https://semver.org/
// LICENSE: MIT License (2024) [ https://opensource.org/licenses/MIT ]
/* THEME COLORS */
// Dark Full - #000000 - (0,0.00,0)
// Dark Half - #002f00 - (0,0.18,0)
// Dark Zero - #005f00 - (0,0.37,0)
// Light Zero - #008e00 - (0,0.55,0)
// Light Half - #00bf00 - (0,0.75,0)
// Light Full - #00ee00 - (0,0.93,0)
/* FONTS */
// Font: Good Time Rg - https://www.dafont.com/good-times.font
// Large = 50px
Graphics.prototype.setLargeFont = function () {
this.setFontCustom(
atob('AAAAAAAAAAAAAAAAAAAAAABAAAAAAAB8AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAB8AAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAADwAAAAAAD8AAAAAAD/AAAAAAD/wAAAAAD/8AAAAAH/8AAAAAH/8AAAAAH/4AAAAAH/4AAAAAH/4AAAAAH/4AAAAAP/4AAAAAP/wAAAAAP/wAAAAAP/wAAAAAP/wAAAAAH/wAAAAAB/wAAAAAAfgAAAAAAHgAAAAAABgAAAAAAAAAAAAAAAAAAOAAAAAAB//AAAAAB//8AAAAB///wAAAA////AAAAf///4AAAP////AAAH////4AAD/+B//AAB/8AD/wAAf8AAP+AAP+AAB/gAD/AAAP8AA/gAAB/AAf4AAAf4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/gAAB/gAP4AAAfwAD/AAAP8AA/4AAH+AAH/AAD/gAB/8AD/wAAP/4H/8AAB////+AAAP////AAAB////gAAAP///wAAAB///wAAAAH//wAAAAAf/wAAAAAAOAAAAAAAAAAAAAfgAAAAAAH8AAAAAAB/AAAAAAAfwAAAAAAH8AAAAAAB/AAAAAAAfwAAAAAAH+AAAAAAB/wAAAAAAf/////wAD/////8AA//////AAH/////wAA/////8AAH/////AAAf////wAAA////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wAH8AA//8AB/AA///AAfwAf//wAH8AH//8AB/AD///AAfwA///wAH8Af//8AB/AH8B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwD+AfwAH+B/AH8AB///wB/AAf//8AfwAD///AH8AA///gB/AAH//wAfwAA//4AH8AAH/8AB/AAAf8AAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AB/AAAB/AAfwAAAfwAH8AAAH8AB/AAAB/AAfwAAAfwAH8AAAH8AB/AAAB/AAfwAAAfwAH8AfAH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8A/gH8AB/gP4D/AAf8H/A/wAH///8/8AA/////+AAP/////gAB/////4AAf/8//8AAD/+P/+AAAf/B//AAAA/AH/AAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAH///AAAAB///8AAAAf///gAAAH///8AAAB////gAAAf///4AAAH////AAAAAAD/wAAAAAAP8AAAAAAB/AAAAAAAfwAAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAH/////8AB//////AAf/////wAH/////8AB//////AAf/////wAH/////8AAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/AAAAAAAAAAAAAAAAAAAAH///AD8AB///4B/AAf//+AfwAH///gH8AB///4B/AAf//+AfwAH///gH8AB///4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH8D/AAfwB/h/wAH8Af//8AB/AD//+AAfwA///gAH8AH//wAB/AA//4AAfgAH/8AAAAAAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAB//4AAAAB///wAAAB////AAAA////4AAAf////AAAP////4AAH/////AAB//fv/wAA/8H4f+AAP+B+D/gAH/AfgP8AB/gH4D/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+A/wAH8Afwf8AB/AH///AAfwA///gAH8AP//4AB/AD//8AAfwAf/+AAH8AD//AAAAAAP/gAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAAAAB/AAAABAAfwAAAAwAH8AAAAcAB/AAAAfAAfwAAAPwAH8AAAH8AB/AAAD/AAfwAAD/wAH8AAB/8AB/AAA//AAfwAAf/gAH8AAP/gAB/AAP/wAAfwAH/4AAH8AD/8AAB/AB/8AAAfwB/+AAAH8A//AAAB/Af/gAAAfwP/gAAAH8P/wAAAB/H/4AAAAfz/8AAAAH9/8AAAAB//+AAAAAf//AAAAAH//gAAAAB//gAAAAAf/wAAAAAH/4AAAAAB/8AAAAAAf8AAAAAAH+AAAAAAB/AAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAD/gP/gAAB/+H/8AAA//z//gAAf////8AAP/////gAD/////4AB//////AAf+P/B/wAH+A/gP8AB/AP4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8A/gH8AB/gP8D/AAf+P/h/wAH/////8AA/////+AAP/////gAB/////wAAP/8//4AAB/+H/8AAAH+A/+AAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAH/4AAAAAH//gAAAAD//8AAAAB///AD8AA///4B/AAP///AfwAH///wH8AB/4f8B/AAf4B/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH+APwP8AB/wD8D/AAP+A/B/gAD/wPx/4AAf/j9/+AAH/////AAA/////gAAH////4AAA////8AAAH///8AAAAf//+AAAAA//8AAAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAEAAAAD4AHwAAAB/AD+AAAAfwA/gAAAH8AP4AAAB/AD+AAAAfwA/gAAAD4AHwAAAAMAAYAAAAAAAAAAAAAAAAA'),
46,
atob('DRYqEykpKiwsJi0rDQ=='),
50 | 65536
)
return this
}
// Medium = 16px ()
Graphics.prototype.setMediumFont = function () {
this.setFontCustom(
atob('AAAAAAAADwAAAB8AAAAPAAAAGwAAAb8AAB/9AAH/kAAv+QAA/4AAAPQAAAACvkAAH//wAD///AC/Qf4A/AA/APQAHwDwAA8A9AAfAPwAPwC+Qf4AP//8AB//9AAG/4AAoAAAAPAAAAD4AAAA////AL///wAv//8AAAAAAPAL/wDwH/8A8D//APA9DwDwPA8A8DwPAPA8DwDwPA8A9DwPAP78DwD/+A8AL+APAPAADwDwAA8A8BQPAPA8DwDwPA8A8DwPAPA8DwDwPA8A9DwfAP7/vwD///8AP+v8AAUBUACqqQAA//9AAP//wABVW8AAAAPAAAADwAAAA8AAAAPAAAADwAD///8A////AP///wAAA8AAAAKAAAAAAAD//A8A//wPAP/8DwDwPA8A8DwPAPA8DwDwPA8A8DwPAPA8DwDwPR8A8D+/APAv/gCgC/gAC//gAD///AC///4A/Tx/APg8LwDwPA8A8DwPAPA8DwDwPA8A8D0fAPA/vwDwL/4AoAv4AAAAQABQAAAA8AAHAPAAHwDwAL8A8AP/APAf+ADwf9AA8v9AAP/4AAD/4AAA/0AAAP0AAAAAAEAAL9v4AL///gD//78A+H0vAPA8DwDwPA8A8DwPAPA8DwDwPA8A9D0fAP7/vwD///8AP9v8AC/4AAC//g8A/r8PAPQfDwDwDw8A8A8PAPAPDwDwDw8A+A8fAP5PfwC///4AL//8AAb/4AAAAAAAAAAAAAA8DwAAfB8AADwPAA=='),
46,
atob('BAcNBg0NDg4ODA4OBA=='),
16 | 131072
)
return this
}
/* VARIABLES */
// Const
const H = g.getHeight()
const W = g.getWidth()
// Mutable
let timer = null
/* UTILITY FUNCTIONS */
// Return String of Current Time
function getCurrentTime () {
try {
const d = new Date()
const h = d.getHours()
const m = d.getMinutes()
return `${h}:${m.toString().padStart(2, 0)}`
} catch (e) {
console.log(e)
return '0:00'
}
}
// Return String of Current Date
function getCurrentDate () {
try {
const d = new Date()
const year = d.getFullYear()
const month = d.getMonth()
const day = d.getDate()
const display = `${month + 1}.${day.toString().padStart(2, 0)}.${year}`
return display
} catch (e) {
console.log(e)
return '0.0.0000'
}
}
// Set A New Draw for the Next Minute
function setNextDraw () {
console.log('tick')
// Clear Timeout
if (timer) {
clearInterval(timer)
}
// Calculate time until next minute
const d = new Date()
const s = d.getSeconds()
const ms = d.getMilliseconds()
const delay = 60000 - (s * 1000) - ms
// Set Timeout
timer = setInterval(draw, delay)
}
function draw () {
// Reset Variables
g.reset()
// Set Background Color
g.setBgColor(0, 0, 0)
// Draw Background
g.setColor(0, 0, 0)
g.fillRect(0, 0, W, H)
// Set Font for Time
g.setColor(0, 0.93, 0)
g.setLargeFont()
g.setFontAlign(0, 0)
// Draw Time
const time = getCurrentTime()
g.drawString(time, W / 2, H / 2, true /* clear background */)
// Set Font for Date
g.setColor(0, 0.75, 0)
g.setMediumFont()
g.setFontAlign(0, 1)
// Draw Date
const dateStr = getCurrentDate()
g.drawString(dateStr, W / 2, H - 45, true)
// Draw Border
g.setColor(0, 0.93, 0)
g.drawLine(5, 36, W - 5, 36)
g.drawLine(5, H - 9, W - 5, H - 9)
g.setColor(0, 0.18, 0)
g.fillRect(0, 27, W, 32)
g.fillRect(0, H, W, H - 5)
// Draw Widgets
Bangle.drawWidgets()
// Schedule Next Draw
setNextDraw()
}
/* MAIN LOOP */
function main () {
// Clear Screen
g.clear()
// Set as Clock to Enable Launcher Screen on BTN1
Bangle.setUI('clock')
// Load Widgets
Bangle.loadWidgets()
// Draw Clock
draw()
}
/* BOOT CODE */
main()

BIN
apps/fallout_clock/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,18 @@
{
"id":"fallout_clock",
"name":"Fallout Clock",
"version":"0.21",
"description":"A simple clock for the Fallout fan",
"icon":"icon.png",
"type":"clock",
"tags": "clock,fallout,green,retro",
"supports": ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"fallout_clock.app.js", "url":"clock.js"},
{"name":"fallout_clock.img", "url":"app-icon.js", "evaluate":true}
],
"screenshots": [
{"url":"./screenshot.png", "name":"Fallout Clock Screenshot"}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -8,3 +8,4 @@
0.08: Handling exceptions
0.09: Add option for showing battery high mark
0.10: Fix background color
0.11: Minor code improvements

View File

@ -3,7 +3,7 @@
"name": "A Battery Widget (with percentage) - Hanks Mod",
"shortName":"H Battery Widget",
"icon": "widget.png",
"version":"0.10",
"version":"0.11",
"type": "widget",
"supports": ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",

View File

@ -24,8 +24,7 @@
var s = width - 1;
var x = this.x;
var y = this.y;
if ((typeof x === 'undefined') || (typeof y === 'undefined')) {
} else {
if (x !== undefined && y !== undefined) {
g.setBgColor(COLORS.white);
g.clearRect(old_x, old_y, old_x + width, old_y + height);

View File

@ -3,3 +3,4 @@
0.03: Update clock_info to avoid a redraw
0.04: Fix clkinfo -- use .get instead of .show
0.05: Use clock_info module as an app
0.06: Fix month in date (jan 0 -> 1, etc)

View File

@ -112,7 +112,7 @@ function getTime(){
function getDate(){
var date = new Date();
return twoD(date.getDate()) + "." + twoD(date.getMonth());
return twoD(date.getDate()) + "." + twoD(date.getMonth() + 1);
}
function getDay(){

View File

@ -1,7 +1,7 @@
{
"id": "linuxclock",
"name": "Linux Clock",
"version": "0.05",
"version": "0.06",
"description": "A Linux inspired clock.",
"readme": "README.md",
"icon": "app.png",

View File

@ -790,7 +790,8 @@ var locales = {
trans: { yes: "ja", Yes: "Ja", no: "nei", No: "Nei", ok: "ok", on: "på", off: "av", "< Back": "< Tilbake", "Delete": "Slett", "Mark Unread": "Merk som ulest" }
},
"ca_ES": {
lang: "es_ES",
lang: "ca_ES",
icon: "🇪🇺",
decimal_point: ",",
thousands_sep: ".",
currency_symbol: "€",
@ -800,7 +801,7 @@ var locales = {
temperature: "°C",
ampm: { 0: "", 1: "" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A, %d de %B %Y", "1": "%d/%m/%y" },
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" },
abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.",
month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octobre,novembre,desembre",
abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.",

View File

@ -101,4 +101,6 @@
0.72: Nav message updastes don't automatically launch navigation menu unless they're new
0.73: Add sharp left+right nav icons
0.74: Add option for driving on left (affects roundabout icons in navigation)
0.75: Handle text with images in messages list by just displaying the first line
0.75: Handle text with images in messages list by just displaying the first line
0.76: Swipe up/down on a shown message to show the next newer/older message.

View File

@ -38,6 +38,7 @@ When a message is shown, you'll see a screen showing the message title and text.
* The 'back-arrow' button (or physical button on Bangle.js 2) goes back to Messages, marking the current message as read.
* The top-left icon shows more options, for instance deleting the message of marking unread
* On Bangle.js 2 you can tap on the message body to view a scrollable version of the title and text (or can use the top-left icon + `View Message`)
- On Bangle.js 2 swipe up/down to show newer/older message
* If shown, the 'tick' button:
* **Android** opens the notification on the phone
* **iOS** responds positively to the notification (accept call/etc)

View File

@ -289,7 +289,8 @@ function showMessageSettings(msg) {
}
function showMessage(msgid) {
var msg = MESSAGES.find(m=>m.id==msgid);
let idx = MESSAGES.findIndex(m=>m.id==msgid);
var msg = MESSAGES[idx];
if (updateLabelsInterval) {
clearInterval(updateLabelsInterval);
updateLabelsInterval=undefined;
@ -389,9 +390,11 @@ function showMessage(msgid) {
{type:"h",fillx:1, c: footer}
]},{back:goBack});
Bangle.swipeHandler = lr => {
Bangle.swipeHandler = (lr,ud) => {
if (lr>0 && posHandler) posHandler();
if (lr<0 && negHandler) negHandler();
if (ud>0 && idx<MESSAGES.length-1) showMessage(MESSAGES[idx+1].id);
if (ud<0 && idx>0) showMessage(MESSAGES[idx-1].id);
};
Bangle.on("swipe", Bangle.swipeHandler);
g.reset().clearRect(Bangle.appRect);

View File

@ -2,7 +2,7 @@
"id": "messagegui",
"name": "Message UI",
"shortName": "Messages",
"version": "0.75",
"version": "0.76",
"description": "Default app to display notifications from iOS and Gadgetbridge/Android",
"icon": "app.png",
"type": "app",

View File

@ -6,3 +6,4 @@
0.06: Support fastloading
0.07: Fix fastloading support - ensure drag handler's restored after
menu display/fastload removes it
0.08: Add setting for initial page to display

View File

@ -78,7 +78,7 @@ function drawTimers() {
}, 1000 - (timers[idx].t % 1000));
}
E.showScroller({
const s = E.showScroller({
h : 40, c : timers.length+2,
back : function() {load();},
draw : (idx, r) => {
@ -138,7 +138,7 @@ function timerMenu(idx) {
}, 1000 - (a.t % 1000));
}
E.showScroller({
const s = E.showScroller({
h : 40, c : 5,
back : function() {
clearInt();
@ -328,9 +328,22 @@ function editTimer(idx, a) {
setUI();
}
function readJson() {
let json = require("Storage").readJSON("multitimer.json", true) || {};
if (Array.isArray(json)) {
// old format, convert
json = { sw: json };
require("Storage").writeJSON("multitimer.json", json);
}
if (!json.sw) json.sw = [];
return json;
}
function drawSw() {
layer = 1;
const sw = require("Storage").readJSON("multitimer.json", true) || [];
const sw = readJson().sw;
function updateTimers(idx) {
if (!timerInt1[idx]) timerInt1[idx] = setTimeout(function() {
@ -341,7 +354,7 @@ function drawSw() {
}, 1000 - (sw[idx].t % 1000));
}
E.showScroller({
const s = E.showScroller({
h : 40, c : sw.length+2,
back : function() {load();},
draw : (idx, r) => {
@ -382,12 +395,13 @@ function drawSw() {
function swMenu(idx, a) {
layer = -1;
const sw = require("Storage").readJSON("multitimer.json", true) || [];
const json = readJson();
const sw = json.sw;
if (sw[idx]) a = sw[idx];
else {
a = {"t" : 0, "on" : false, "msg" : ""};
sw[idx] = a;
require("Storage").writeJSON("multitimer.json", sw);
require("Storage").writeJSON("multitimer.json", json);
}
function updateTimer() {
@ -408,7 +422,7 @@ function swMenu(idx, a) {
}
else delete a.msg;
sw[idx] = a;
require("Storage").writeJSON("multitimer.json", sw);
require("Storage").writeJSON("multitimer.json", json);
swMenu(idx, a);
});
}
@ -420,7 +434,7 @@ function swMenu(idx, a) {
setUI();
}
E.showScroller({
const s = E.showScroller({
h : 40, c : 5,
back : function() {
clearInt();
@ -458,7 +472,7 @@ function swMenu(idx, a) {
select : (i) => {
function saveAndReload() {
require("Storage").writeJSON("multitimer.json", sw);
require("Storage").writeJSON("multitimer.json", json);
s.draw();
}
@ -707,5 +721,17 @@ function onDrag(e) {
}
}
drawTimers();
switch (readJson().initialScreen) {
case 1:
drawSw();
break;
case 2:
drawAlarms();
break;
case 0:
case undefined:
default:
drawTimers();
break;
}
}

View File

@ -1,7 +1,7 @@
{
"id": "multitimer",
"name": "Multi Timer",
"version": "0.07",
"version": "0.08",
"description": "Set timers and chronographs (stopwatches) and watch them count down in real time. Pause, create, edit, and delete timers and chronos, and add custom labels/messages. Also sets alarms.",
"icon": "app.png",
"screenshots": [
@ -16,6 +16,7 @@
{"name":"multitimer.app.js","url":"app.js"},
{"name":"multitimer.boot.js","url":"boot.js"},
{"name":"multitimer.alarm.js","url":"alarm.js"},
{"name":"multitimer.settings.js","url":"settings.js"},
{"name":"multitimer.img","url":"app-icon.js","evaluate":true}
],
"data": [{"name":"multitimer.json"}],

View File

@ -0,0 +1,32 @@
(function(back) {
const file = "multitimer.json";
let json = require('Storage').readJSON(file, true) || {};
if (Array.isArray(json)) {
// old format, convert
json = { sw: json };
}
if (!json.sw) json.sw = [];
function writeSettings() {
require('Storage').writeJSON(file, json);
}
const screens = ["Timers", "Chronos", "Alarms"];
E.showMenu({
"": {
"title": "multitimer"
},
"< Back": back,
"Initial screen": {
value: json.initialScreen || 0,
min: 0,
max: screens.length - 1,
format: v => screens[v],
onchange: v => {
json.initialScreen = v;
writeSettings();
}
},
});
});

View File

@ -85,7 +85,7 @@ function novaOpenEyes(speed, white, animation) {
scale: 2.2
});
}, speed * 5);
} else {}
}
} else {
g.drawImage(novaEyesStage4(), -10, -10, {
@ -126,7 +126,7 @@ function novaOpenEyes(speed, white, animation) {
});
open = true;
}, speed * 5);
} else {}
}
}
}
@ -136,7 +136,7 @@ function novaCloseEyes(speed, white, animation) {
g.drawImage(novaEyesStage0(), -10, -10, {
scale: 2.2
});
} else {}
}
setTimeout(function() {
g.drawImage(novaEyesStage1(), -10, -10, {
scale: 2.2
@ -164,7 +164,7 @@ function novaCloseEyes(speed, white, animation) {
g.drawImage(novaEyesWhiteStage0(), -10, -10, {
scale: 2.2
});
} else {}
}
setTimeout(function() {
timedraw(true);
g.drawImage(novaEyesTransStage1(), -10, -10, {

View File

@ -4,4 +4,4 @@
0.04: Update cards to draw rounded on newer firmware. Make sure in-game menu can't be pulled up during end of game.
0.05: add confirmation prompt to new game to prevent fat fingering new game during existing one.
0.06: fix AI logic typo and add prompt to show what AI played each turn.
0.07: Minor code improvements
0.07: Minor code improvements.

View File

@ -2,7 +2,7 @@
"name": "Red 7 Card Game",
"shortName" : "Red 7",
"icon": "icon.png",
"version": "0.07",
"version":"0.07",
"description": "An implementation of the card game Red 7 for your watch. Play against the AI and be the last player still in the game to win!",
"tags": "game",
"supports":["BANGLEJS2"],

View File

@ -486,8 +486,7 @@ function canPlay(hand, palette, otherPalette) {
} else {
//Check if any palette play can win with rule.
for(let h of hand.handCards) {
if(h === c) {}
else {
if(h !== c) {
clonePalette.addCard(c);
if(isWinningCombo(c, clonePalette, otherPalette)) {
return true;
@ -531,8 +530,7 @@ class AI {
} else {
//Check if any palette play can win with rule.
for(let h of this.hand.handCards) {
if(h === c) {}
else {
if(h !== c) {
clonePalette.addCard(h);
if(isWinningCombo(c, clonePalette, otherPalette)) {
ruleStack.addCard(c);

View File

@ -101,7 +101,8 @@ function getData() {
uploadBtn.disabled = true;
Util.showModal("Loading...");
Util.readStorageJSON(repJson, reps => {
Util.readStorageJSON(repJson, reps_ => {
reps = reps_;
Util.hideModal();
for(const rep of reps){
renderRep(rep);

View File

@ -23,3 +23,5 @@
0.20: Alarm dismiss and snooze events
0.21: Fix crash in clock_info
0.22: Dated event repeat option
0.23: Allow buzzing forever when an alarm fires
0.24: Emit alarmReload when alarms change (used by widalarm)

View File

@ -14,10 +14,10 @@ Global Settings
---------------
- `Unlock at Buzz` - If `Yes` the alarm/timer will unlock the watch
- `Delete Expired Timers` - Default for whether expired timers are removed after firing.
- `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only)
- `Default Snooze` - Default _Snooze_ value for newly created alarms/timers
- `Default Repeat` - Default _Repeat_ value for newly created alarms (_Alarms_ only)
- `Buzz Count` - The number of buzzes before the watch goes silent
- `Buzz Count` - The number of buzzes before the watch goes silent, or "forever" to buzz until stopped.
- `Buzz Interval` - The interval between one buzz and the next
- `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers

View File

@ -2,6 +2,26 @@
<head>
<link rel="stylesheet" href="../../css/spectre.min.css">
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
<style>
.multi-select {
/* e.g. day <select> */
height: 100%;
}
td.single-row {
/* no border between single rowspans */
border-bottom: none;
}
.btn-center {
justify-content: center;
display: flex;
}
.event-summary {
text-align: center;
}
</style>
<script src="../../core/lib/interface.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ical.js/1.5.0/ical.min.js"></script>
<script>
@ -115,15 +135,17 @@ function renderAlarm(alarm, exists) {
const localDate = alarm.date ? dateFromAlarm(alarm) : null;
const tr = document.createElement('tr');
const tr2 = document.createElement('tr');
tr.classList.add('event-row');
tr.dataset.uid = alarm.id;
const tdType = document.createElement('td');
tdType.type = "text";
tdType.classList.add('event-summary');
tr.appendChild(tdType);
const inputTime = document.createElement('input');
let type;
if (localDate) {
tdType.textContent = "Event";
type = "Event";
inputTime.type = "datetime-local";
inputTime.value = localDate.toISOString().slice(0,16);
inputTime.onchange = (e => {
@ -139,18 +161,19 @@ function renderAlarm(alarm, exists) {
inputTime.value = `${hours}:${mins}:${secs}`;
if (alarm.timer) {
tdType.textContent = "Timer";
type = "Timer";
inputTime.onchange = e => {
alarm.timer = hmsToMs(inputTime.value);
// alarm.t is set on upload
};
} else {
tdType.textContent = "Alarm";
type = "Alarm";
inputTime.onchange = e => {
alarm.t = hmsToMs(inputTime.value);
};
}
}
tdType.textContent = type;
if (!exists) {
const asterisk = document.createElement('sup');
asterisk.textContent = '*';
@ -160,11 +183,33 @@ function renderAlarm(alarm, exists) {
inputTime.classList.add('form-input');
inputTime.dataset.uid = alarm.id;
const tdTime = document.createElement('td');
tr.appendChild(tdTime);
tdTime.appendChild(inputTime);
let tdDays;
if (type === "Alarm") {
tdDays = document.createElement('td');
const selectDays = document.createElement('select');
selectDays.multiple = true;
selectDays.classList.add('form-input', 'multi-select');
selectDays.dataset.uid = alarm.id;
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const options = days.map((day, i) => {
const option = document.createElement('option');
option.value = day;
option.text = day;
option.selected = alarm.dow & (1 << i);
if(day !== "Sun")
selectDays.appendChild(option);
return option;
});
selectDays.appendChild(options.find(o => o.text === "Sun"));
selectDays.onchange = (e => {
alarm.dow = options.reduce((bits, opt, i) => bits | (opt.selected ? 1 << i : 0), 0);
});
tdDays.appendChild(selectDays);
}
const tdSummary = document.createElement('td');
tr.appendChild(tdSummary);
const inputSummary = document.createElement('input');
inputSummary.type = "text";
inputSummary.classList.add('event-summary');
@ -181,9 +226,8 @@ function renderAlarm(alarm, exists) {
inputSummary.onchange();
const tdOptions = document.createElement('td');
tr.appendChild(tdOptions);
const onOffCheck = document.createElement('input');
tdOptions.classList.add('btn-center');
onOffCheck.type = 'checkbox';
onOffCheck.checked = alarm.on;
onOffCheck.onchange = e => {
@ -199,8 +243,6 @@ function renderAlarm(alarm, exists) {
tdOptions.appendChild(onOff);
const tdInfo = document.createElement('td');
tr.appendChild(tdInfo);
const buttonDelete = document.createElement('button');
buttonDelete.classList.add('btn');
buttonDelete.classList.add('btn-action');
@ -212,9 +254,22 @@ function renderAlarm(alarm, exists) {
buttonDelete.onclick = (e => {
alarms = alarms.filter(a => a !== alarm);
document.getElementById('events').removeChild(tr);
document.getElementById('events').removeChild(tr2);
});
tr.appendChild(tdTime); tdTime.colSpan = 3; tdTime.classList.add('single-row');
tr2.appendChild(tdType);
tr2.appendChild(tdOptions);
tr2.appendChild(tdInfo);
if (tdDays) {
tr.appendChild(tdDays); tdDays.rowSpan = 2;
} else {
tdSummary.colSpan = 2;
}
tr.appendChild(tdSummary); tdSummary.rowSpan = 2;
document.getElementById('events').appendChild(tr);
document.getElementById('events').appendChild(tr2);
document.getElementById('upload').disabled = false;
}
@ -318,11 +373,9 @@ function onInit() {
<table class="table">
<thead>
<tr>
<th>Type</th>
<th>Date/Time</th>
<th colspan="3">Time & Options</th>
<th>Days</th>
<th>Summary</th>
<th>On?</th>
<th></th>
</tr>
</thead>
<tbody id="events">

View File

@ -55,10 +55,7 @@ exports.getTimeToAlarm = function(alarm, time) {
/// Force a reload of the current alarms and widget
exports.reload = function() {
eval(require("Storage").read("sched.boot.js"));
if (global.WIDGETS && WIDGETS["alarm"]) {
WIDGETS["alarm"].reload();
Bangle.drawWidgets();
}
Bangle.emit("alarmReload");
};
// Factory that creates a new alarm with default values
exports.newDefaultAlarm = function () {

View File

@ -1,7 +1,7 @@
{
"id": "sched",
"name": "Scheduler",
"version": "0.22",
"version": "0.24",
"description": "Scheduling library for alarms and timers",
"icon": "app.png",
"type": "scheduler",

View File

@ -71,7 +71,7 @@ function showAlarm(alarm) {
const pattern = alarm.vibrate || (alarm.timer ? settings.defaultTimerPattern : settings.defaultAlarmPattern);
require("buzz").pattern(pattern).then(() => {
if (buzzCount--) {
if (buzzCount == null || buzzCount--) {
setTimeout(buzz, settings.buzzIntervalMillis);
} else if (alarm.as) { // auto-snooze
buzzCount = settings.buzzCount;

View File

@ -43,12 +43,13 @@
},
/*LANG*/"Buzz Count": {
value: settings.buzzCount,
min: 5,
value: settings.buzzCount == null ? 4 : settings.buzzCount,
min: 4,
max: 15,
step: 1,
format: v => v === 4 ? "Forever" : v,
onchange: v => {
settings.buzzCount = v;
settings.buzzCount = v === 4 ? null : v;
require("sched").setSettings(settings);
}
},

View File

@ -77,4 +77,5 @@ of 'Select Clock'
calibration was done.
0.67: Rename 'Wake on BTN1/Touch' to 'Wake on Button/Tap' on Bangle.js 2
0.68: Fix syntax error
0.69: Add option to wake on double tap
0.69: Add option to wake on double tap
0.70: Fix load() typo

View File

@ -1,7 +1,7 @@
{
"id": "setting",
"name": "Settings",
"version": "0.69",
"version": "0.70",
"description": "A menu for setting up Bangle.js",
"icon": "settings.png",
"tags": "tool,system",

View File

@ -641,7 +641,7 @@ function showUtilMenu() {
storage.writeJSON("setting.json",s);
E.showAlert(/*LANG*/"Calibrated!").then(() => load("setting.app.js"));
} else {
E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("settings.app.js"));
E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("setting.app.js"));
}
});
};

View File

@ -10,4 +10,5 @@
0.12: Improve README, option to add functions triggered by status changes or time periods, remove old log (<0.10) conversion
0.13: Prevent to stay in consecutive sleep if not worn, correct trigger calling, add trigger object itself as argument to the fn function
0.14: Add "Delete all logfiles before" to interface.html, display all logfiles in the interface
0.15: Issue newline before GB commands (solves issue with console.log and ignored commands)
0.15: Issue newline before GB commands (solves issue with console.log and ignored commands)
0.16: Only write logs if we have a non-empty log to write

View File

@ -169,7 +169,8 @@ exports = {
// check if before this fortnight period
if (firstDay < thisFirstDay) {
// write log in seperate file
require("Storage").writeJSON("sleeplog_" + this.msToFn(firstDay) + ".log", log);
if(log.length > 0)
require("Storage").writeJSON("sleeplog_" + this.msToFn(firstDay) + ".log", log);
// set last day as first
firstDay = lastDay;
} else {

View File

@ -2,7 +2,7 @@
"id":"sleeplog",
"name":"Sleep Log",
"shortName": "SleepLog",
"version": "0.15",
"version": "0.16",
"description": "Log and view your sleeping habits. This app is using the built in movement calculation.",
"icon": "app.png",
"type": "app",

View File

@ -8,8 +8,6 @@ const hs = require('./heatshrink.js');
if (pc) {
fs = require('fs');
var print=console.log;
} else {
}
function writeDir(json) {

27
apps/swipeinv/README.md Normal file
View File

@ -0,0 +1,27 @@
# Swipe Inversion
Inverts swipe direction globally or per app, see settings. If global inversion is enabled, you can unselect the inversion per app and vice versa.
## Limitations
Swipe Inversion can only invert directions on apps that use `Bangle.setUI` to set up swipes. Swipes set up with `Bangle.on("swipe", ...)` is currently not managed.
Swiping behavior that uses the `drag` event is not altered either.
## TODO
- Try to handle swipes from `Bangle.on("swipe", ...)`
- alternatively refactor apps using that to only use `Bangle.setUI` for setting up swipes.
- Think about how to accommodate e.g. `touch` or `back` handlers set up in `Layout` library calls. They are removed if we refactor some `Bangle.on("swipe", ...)` to `Bangle.setUI`. (Is it maybe resolved if we call `Bangle.setUI` before the `Layout` call? - have not tested that yet.)
- Add bootloader apps and widgets to the list of apps that can be individually toggled in settings?
## Requests
Bug reports and feature requests should be done to the espruino/BangleApps github issue tracker.
## Creator
nxdefiant
## Contributors

BIN
apps/swipeinv/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

19
apps/swipeinv/boot.js Normal file
View File

@ -0,0 +1,19 @@
{
const settings = Object.assign({
global: false,
apps: []
}, require("Storage").readJSON("swipeinv.json", true) || {});
if (settings.global || settings.apps.length > 0) {
const setURIOrig = Bangle.setUI;
Bangle.setUI = (mode, callback) => {
if (typeof mode === "object" && mode.swipe) {
if (settings.global ^ settings.apps.includes(global.__FILE__)) {
const origSwipeCb = mode.swipe;
mode.swipe = (dirLR, dirUD) => origSwipeCb(dirLR*-1, dirUD*-1);
}
}
return setURIOrig(mode, callback);
};
}
}

View File

@ -0,0 +1,18 @@
{
"id": "swipeinv",
"name": "Swipe inversion",
"shortName":"Swipe inv.",
"icon": "app.png",
"version":"0.01",
"description": "Inverts swipe direction globally or per app, see settings. If global inversion is enabled, you can unselect the inversion per app and vice versa.",
"readme":"README.md",
"type": "bootloader",
"tags": "system",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"swipeinv.boot.js","url":"boot.js"},
{"name":"swipeinv.settings.js","url":"settings.js"}
],
"data": [{"name":"swipeinv.json"}]
}

58
apps/swipeinv/settings.js Normal file
View File

@ -0,0 +1,58 @@
(function(back) {
var FILE = "swipeinv.json";
// Load settings
const settings = Object.assign({
global: false,
apps: []
}, require("Storage").readJSON(FILE, true) || {});
function writeSettings() {
require('Storage').writeJSON(FILE, settings);
}
function appMenu() {
menu = {
"" : { "title" : /*LANG*/"Swipe inversion apps" },
"< Back" : () => { writeSettings(); mainMenu();}
};
require("Storage").list(/\.info$/).map(app=>require("Storage").readJSON(app,1)).filter(app => app.type === "app" || !app.type).sort((a,b) => {
if (a.name<b.name) return -1;
if (a.name>b.name) return 1;
return 0;
}).forEach(app => {
menu[app.name] = {
value: settings.apps.includes(app.src),
onchange: v => {
if (v) {
settings.apps.push(app.src);
} else {
const idx = settings.apps.indexOf(app.src);
if (idx !== -1) {
settings.apps.splice(idx, 1);
}
}
}
};
});
E.showMenu(menu);
}
function mainMenu() {
E.showMenu({
"" : { "title" : /*LANG*/"Swipe inversion" },
"< Back" : () => back(),
/*LANG*/'Invert globally': {
value: !!settings.global,
onchange: v => {
settings.global = v;
writeSettings();
}
},
/*LANG*/'Select apps': () => appMenu()
});
}
mainMenu();
})

View File

@ -972,8 +972,7 @@ function activateItem () {
animateToClock();
break;
case 0: // food
if (tama.sleep) {
} else {
if (!tama.sleep) {
// evolution = 0;
mode = 'food';
lightSelect = 0;
@ -983,8 +982,7 @@ function activateItem () {
mode = 'light';
break;
case 2: // game
if (tama.sleep) {
} else {
if (!tama.sleep) {
animateToGame();
}
break;

View File

@ -1 +1,2 @@
0.01: Moved out of 'alarm' app
0.02: Decouple reloading of widget when alarms change

View File

@ -1,7 +1,7 @@
{
"id": "widalarm",
"name": "Alarms Widget",
"version": "0.01",
"version": "0.02",
"description": "Displays an alarm icon in the widgets bar if any alarm is active",
"icon": "app.png",
"type": "widget",

View File

@ -6,3 +6,9 @@ WIDGETS["alarm"]={area:"tl",width:0,draw:function() {
}
};
WIDGETS["alarm"].reload();
Bangle.on("alarmReload", () => {
if (WIDGETS["alarm"]) {
WIDGETS["alarm"].reload();
Bangle.drawWidgets();
}
});

View File

@ -12,3 +12,4 @@
0.08: Selectable font. Allow to disable hour padding.
0.09: Match draw() API e.g. to allow wid_edit to alter this widget
0.10: Change 4x5 font to 6x8, teletext is now default font
0.11: Bugfix: handle changes in alarms (e.g. done without a load, such as via fastload)

View File

@ -2,7 +2,7 @@
"id": "widalarmeta",
"name": "Alarm & Timer ETA",
"shortName": "Alarm ETA",
"version": "0.10",
"version": "0.11",
"description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).",
"icon": "widget.png",
"type": "widget",

View File

@ -19,7 +19,11 @@
loadSettings();
function getNextAlarm(date) {
const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true);
const alarms = require("sched")
.getAlarms()
// more precise filtering is done using getTimeToAlarm() below
.filter(alarm => alarm.on && alarm.hidden !== true);
WIDGETS["widalarmeta"].numActiveAlarms = alarms.length;
if (alarms.length > 0) {
const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY);
@ -116,16 +120,18 @@
} /* draw */
if (config.maxhours > 0) {
// add your widget
WIDGETS["widalarmeta"]={
area:"tl",
width: 0, // hide by default = assume no timer
draw:draw,
reload: () => {
reload: function () {
this.nextAlarm = undefined;
loadSettings();
g.clear();
Bangle.drawWidgets();
},
};
Bangle.on("alarmReload", () => WIDGETS["widalarmeta"].reload());
}
})();

View File

@ -150,10 +150,13 @@ apps.forEach((app,appIdx) => {
} else {
var changeLog = fs.readFileSync(appDir+"ChangeLog").toString();
var versions = changeLog.match(/\d+\.\d+:/g);
if (!versions) ERROR(`No versions found in ${app.id} ChangeLog (${appDir}ChangeLog)`, {file:metadataFile});
var lastChangeLog = versions.pop().slice(0,-1);
if (lastChangeLog != app.version)
ERROR(`App ${app.id} app version (${app.version}) and ChangeLog (${lastChangeLog}) don't agree`, {file:appDirRelative+"ChangeLog", line:changeLog.split("\n").length-1});
if (!versions) {
ERROR(`No versions found in ${app.id} ChangeLog (${appDir}ChangeLog)`, {file:metadataFile});
} else {
var lastChangeLog = versions.pop().slice(0,-1);
if (lastChangeLog != app.version)
ERROR(`App ${app.id} app version (${app.version}) and ChangeLog (${lastChangeLog}) don't agree`, {file:appDirRelative+"ChangeLog", line:changeLog.split("\n").length-1});
}
}
}
if (!app.description) ERROR(`App ${app.id} has no description`, {file:metadataFile});

View File

@ -14,7 +14,7 @@
{"code":"pt_PT","name":"Portuguese","url":"pt_PT.json"},
{"code":"pt_BR","name":"Portuguese Brasil","url":"pt_BR.json"},
{"code":"bg_BG","name":"Bulgarian","url":"bg_BG.json", "disabled":"Characters not in ISO Latin codepage"},
{"code":"da_DA","name":"Danish","url":"da_DA.json"},
{"code":"da_DK","name":"Danish","url":"da_DK.json"},
{"code":"el_EL","name":"Greek","url":"el_EL.json", "disabled":"Characters not in ISO Latin codepage"},
{"code":"et_ET","name":"Estonian","url":"et_ET.json"},
{"code":"lt_LT","name":"Lithuanian","url":"lt_LT.json"},

View File

@ -87,7 +87,7 @@ declare module Sched {
defaultSnoozeMillis: number,
defaultAutoSnooze: boolean,
defaultDeleteExpiredTimers: boolean,
buzzCount: number,
buzzCount: number | null, // null means buzz forever
buzzIntervalMillis: number,
defaultAlarmPattern: string,
defaultTimerPattern: string,