1
0
Fork 0

Merge branch 'master' of github.com:espruino/BangleApps

master
Gordon Williams 2022-05-03 12:29:38 +01:00
commit 5bc4ecac48
17 changed files with 189 additions and 36 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ tests/Layout/bin/tmp.*
tests/Layout/testresult.bmp tests/Layout/testresult.bmp
apps.local.json apps.local.json
_site _site
.jekyll-cache

View File

@ -1,2 +1,3 @@
0.01: New App! 0.01: New App!
0.02: Set Bangle.js 2 compatible 0.02: Set Bangle.js 2 compatible
0.03: Add setting to hide the widget

View File

@ -2,13 +2,15 @@
"id": "gpsautotime", "id": "gpsautotime",
"name": "GPS auto time", "name": "GPS auto time",
"shortName": "GPS auto time", "shortName": "GPS auto time",
"version": "0.02", "version": "0.03",
"description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.", "description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",
"tags": "widget,gps", "tags": "widget,gps",
"supports": ["BANGLEJS","BANGLEJS2"], "supports": ["BANGLEJS","BANGLEJS2"],
"storage": [ "storage": [
{"name":"gpsautotime.wid.js","url":"widget.js"} {"name":"gpsautotime.wid.js","url":"widget.js"},
] {"name":"gpsautotime.settings.js","url":"settings.js"}
],
"data": [{"name":"gpsautotime.json"}]
} }

View File

@ -0,0 +1,25 @@
(function(back) {
var FILE = "gpsautotime.json";
// Load settings
var settings = Object.assign({
show: true,
}, require('Storage').readJSON(FILE, true) || {});
function writeSettings() {
require('Storage').writeJSON(FILE, settings);
}
// Show the menu
E.showMenu({
"" : { "title" : "GPS auto time" },
"< Back" : () => back(),
'Show widget?': {
value: !!settings.show, // !! converts undefined to false
format: v => v?"Show":"Hide",
onchange: v => {
settings.show = v;
writeSettings();
}
},
});
})

View File

@ -1,6 +1,13 @@
(() => { (() => {
var lastTimeSet = 0; var lastTimeSet = 0;
var settings = Object.assign({
// default values
show: true,
}, require('Storage').readJSON("gpsautotime.json", true) || {});
const show = settings.show;
delete settings;
Bangle.on('GPS',function(fix) { Bangle.on('GPS',function(fix) {
if (fix.fix) { if (fix.fix) {
var curTime = fix.time.getTime()/1000; var curTime = fix.time.getTime()/1000;
@ -14,8 +21,9 @@
// add your widget // add your widget
WIDGETS["gpsAutoTime"]={ WIDGETS["gpsAutoTime"]={
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right) area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
width: 28, // width of the widget width: show ? 4*6+2 : 0, // width of the widget
draw: function() { draw: function() {
if (!show) return;
g.reset(); // reset the graphics context to defaults (color/font/etc) g.reset(); // reset the graphics context to defaults (color/font/etc)
g.setFont("6x8"); g.setFont("6x8");
if ((getTime() - lastTimeSet) <= 60) { if ((getTime() - lastTimeSet) <= 60) {
@ -27,7 +35,9 @@
} }
}; };
if (show) {
setInterval(function() { setInterval(function() {
WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]); WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]);
}, 1*60000); // update every minute }, 1*60000); // update every minute
})() }
})();

View File

@ -1 +1,2 @@
0.01: New App! 0.01: New App!
0.02: Introduced settings to customize the layout and functionality of the keyboard.

View File

@ -2,6 +2,17 @@
A library that provides an on-screen keyboard for text input. A library that provides an on-screen keyboard for text input.
## Settings
Text size - small or big text font. Default=Big. Suggested=Small.
Offset keyboard - display the keyboard on top, making it faster to see what character you have selected. Default=No. Suggested=Yes.
Loop around - should the keyboard highlight loop around when going past the edges? Default=Yes. Suggested=No.
One-to-one input and release to select - should the input correspond directly to discrete areas on the screen, instead of being handled by scaled relative changes in position on swipes? Default=No. Suggested=Yes.
Speed scaling - how much should a swipe move the highligt on the keyboard? Higher number corresponds to slower movement. Not applicable if using one-to-one input. Default=24. Suggested=15.
## Usage ## Usage
In your app's metadata, add: In your app's metadata, add:

View File

@ -69,13 +69,24 @@ var KEYEXTRA = [
String.fromCharCode(27,91,53,126), // 0x84 page up String.fromCharCode(27,91,53,126), // 0x84 page up
String.fromCharCode(27,91,54,126), // 0x85 page down String.fromCharCode(27,91,54,126), // 0x85 page down
]; ];
var settings = Object.assign({
// default values
textSize: 1,
offsetKeyboard: 0,
loopAround: 1,
oneToOne: 0,
speedScaling: 24
}, require('Storage').readJSON("kbtouch.settings.json", true) || {});
// state // state
const R = Bangle.appRect; const R = Bangle.appRect;
var kbx = 0, kby = 0, kbdx = 0, kbdy = 0, kbShift = false, flashToggle = false; var kbx = 0, kby = 0, kbdx = 0, kbdy = 0, kbShift = false, flashToggle = false;
const PX=12, PY=16, DRAGSCALE=24; const PX=12, PY=16, DRAGSCALE=settings.speedScaling;
var xoff = 3, yoff = g.getHeight()-PY*4; var xoff = 3, yoff = g.getHeight()-PY*(4+5*settings.offsetKeyboard);
function draw() { function draw() {
"ram";
var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER; var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER;
//g.drawImage(KEYIMG,0,yoff); //g.drawImage(KEYIMG,0,yoff);
g.reset().setFont("6x8:2"); g.reset().setFont("6x8:2");
@ -88,9 +99,9 @@ function draw() {
g.drawString(map[1],xoff,yoff+PY); g.drawString(map[1],xoff,yoff+PY);
g.drawString(map[2],xoff,yoff+PY*2); g.drawString(map[2],xoff,yoff+PY*2);
g.drawString(map[3],xoff,yoff+PY*3); g.drawString(map[3],xoff,yoff+PY*3);
var l = g.setFont("6x8:4").wrapString(text+(flashToggle?"_":" "), R.w-8); var l = g.setFont(settings.textSize ? "6x8:4":"6x8:2").wrapString(text+(flashToggle?"_":" "), R.w-8);
if (l.length>2) l=l.slice(-2); if (l.length>2+2*settings.textSize) l=l.slice(-(2+2*settings.textSize));
g.drawString(l.join("\n"),R.x+4,R.y+4); g.drawString(l.join("\n"),R.x+4,R.y+4 +82*settings.offsetKeyboard);
g.flip(); g.flip();
} }
@ -104,17 +115,31 @@ function draw() {
return new Promise((resolve,reject) => { return new Promise((resolve,reject) => {
Bangle.setUI({mode:"custom", drag:e=>{ Bangle.setUI({mode:"custom", drag:e=>{
if (settings.oneToOne) {
kbx = Math.max(Math.min(Math.floor((e.x-16) / (6*2)) , 13) , 0);
kby = Math.max(Math.min(Math.floor((e.y-120) / (8*2)) , 3) , 0);
//print(e.y, kby, e.x, kbx);
}
if (!settings.oneToOne) {
kbdx += e.dx; kbdx += e.dx;
kbdy += e.dy; kbdy += e.dy;
var dx = Math.round(kbdx/DRAGSCALE), dy = Math.round(kbdy/DRAGSCALE); var dx = Math.round(kbdx/DRAGSCALE), dy = Math.round(kbdy/DRAGSCALE);
kbdx -= dx*DRAGSCALE; kbdx -= dx*DRAGSCALE;
kbdy -= dy*DRAGSCALE; kbdy -= dy*DRAGSCALE;
if (dx || dy) { if (dx || dy) {
if (settings.loopAround) {
kbx = (kbx+dx+15)%15; kbx = (kbx+dx+15)%15;
kby = (kby+dy+4)%4; kby = (kby+dy+4)%4;
draw(); } else {
kbx = Math.max(Math.min((kbx+dx),13),0);
kby = Math.max(Math.min((kby+dy),3),0);
} }
},touch:()=>{ }
}
draw();
if (!e.b && e.y>Bangle.appRect.y && settings.oneToOne /*&& settings.releaseToSelect*/) {
var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER; var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER;
var ch = map[kby][kbx]; var ch = map[kby][kbx];
if (ch=="\2") kbShift=!kbShift; if (ch=="\2") kbShift=!kbShift;
@ -122,6 +147,17 @@ function draw() {
else text += ch; else text += ch;
Bangle.buzz(20); Bangle.buzz(20);
draw(); draw();
}
},touch:()=>{
if ( !settings.oneToOne /*|| !settings.releaseToSelect*/) {
var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER;
var ch = map[kby][kbx];
if (ch=="\2") kbShift=!kbShift;
else if (ch=="\b") text = text.slice(0,-1);
else text += ch;
Bangle.buzz(20);
draw();
}
},back:()=>{ },back:()=>{
clearInterval(flashInterval); clearInterval(flashInterval);
Bangle.setUI(); Bangle.setUI();

View File

@ -1,6 +1,6 @@
{ "id": "kbtouch", { "id": "kbtouch",
"name": "Touch keyboard", "name": "Touch keyboard",
"version":"0.01", "version":"0.02",
"description": "A library for text input via onscreen keyboard", "description": "A library for text input via onscreen keyboard",
"icon": "app.png", "icon": "app.png",
"type":"textinput", "type":"textinput",
@ -9,6 +9,7 @@
"screenshots": [{"url":"screenshot.png"}], "screenshots": [{"url":"screenshot.png"}],
"readme": "README.md", "readme": "README.md",
"storage": [ "storage": [
{"name":"textinput","url":"lib.js"} {"name":"textinput","url":"lib.js"},
{"name":"kbtouch.settings.js","url":"settings.js"}
] ]
} }

59
apps/kbtouch/settings.js Normal file
View File

@ -0,0 +1,59 @@
(function(back) {
function settings() {
let settings = require('Storage').readJSON("kbtouch.settings.json", true) || {};
if (settings.textSize===undefined) settings.textSize=1;
if (settings.offsetKeyboard===undefined) settings.offsetKeyboard=0;
if (settings.loopAround===undefined) settings.loopAround=1;
if (settings.oneToOne===undefined) settings.oneToOne=0;
if (settings.speedScaling===undefined) settings.speedScaling=24;
return settings;
}
function updateSetting(setting, value) {
let settings = require('Storage').readJSON("kbtouch.settings.json", true) || {};
settings[setting] = value;
require('Storage').writeJSON("kbtouch.settings.json", settings);
}
var mainmenu = {
"" : { "title" : /*LANG*/"Touch Keyboard" },
"< Back" : back,
/*LANG*/'Text size': {
value: settings().textSize,
min: 0, max: 1,
format: v => [/*LANG*/"Small",/*LANG*/"Big"][v],
onchange: v => updateSetting("textSize", v)
},
/*LANG*/'Offset keyboard': {
value: settings().offsetKeyboard,
min: 0, max: 1,
format: v => [/*LANG*/"No",/*LANG*/"Yes"][v],
onchange: v => updateSetting("offsetKeyboard", v)
},
/*LANG*/'Loop around': {
value: settings().loopAround,
min: 0, max: 1,
format: v => [/*LANG*/"No",/*LANG*/"Yes"][v],
onchange: v => updateSetting("loopAround", v)
},
/*LANG*/'One-to-one input and release to select': {
value: settings().oneToOne,
min: 0, max: 1,
format: v => [/*LANG*/"No",/*LANG*/"Yes"][v],
onchange: v => updateSetting("oneToOne", v)
},
/*LANG*/'Speed scaling': {
value: settings().speedScaling,
min: 1, max: 24, step : 1,
format: v => v,
onchange: v => updateSetting("speedScaling", v)
}
///*LANG*/'Release to select': {
// value: 1|settings().fontSize,
// min: 0, max: 1,
// format: v => [/*LANG*/"No",/*LANG*/"Yes"][v],
// onchange: v => updateSetting("releaseToSelect", v)
//}
};
E.showMenu(mainmenu);
})

View File

@ -5,3 +5,4 @@
0.05: Refactor decodeTime() to scheduling library 0.05: Refactor decodeTime() to scheduling library
0.06: Add logging 0.06: Add logging
use Layout library and display ETA use Layout library and display ETA
0.07: Add check for day of week

View File

@ -1,5 +1,7 @@
# Sleep Phase Alarm # Sleep Phase Alarm
The alarm must be in the next 24h.
The display shows: The display shows:
- the current time - the current time

View File

@ -51,9 +51,11 @@ active.forEach(alarm => {
if (dateAlarm < now) { // dateAlarm in the past, add 24h if (dateAlarm < now) { // dateAlarm in the past, add 24h
dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000));
} }
if ((alarm.dow >> dateAlarm.getDay()) & 1) { // check valid day of week
if (nextAlarm === undefined || dateAlarm < nextAlarm) { if (nextAlarm === undefined || dateAlarm < nextAlarm) {
nextAlarm = dateAlarm; nextAlarm = dateAlarm;
} }
}
}); });
var layout = new Layout({ var layout = new Layout({
@ -80,7 +82,7 @@ function drawApp() {
layout.date.label = locale.time(now, BANGLEJS2 && Bangle.isLocked() ? 1 : 0); // hide seconds on bangle 2 layout.date.label = locale.time(now, BANGLEJS2 && Bangle.isLocked() ? 1 : 0); // hide seconds on bangle 2
const diff = nextAlarm - now; const diff = nextAlarm - now;
const diffHour = Math.floor((diff % 86400000) / 3600000).toString(); const diffHour = Math.floor((diff % 86400000) / 3600000).toString();
const diffMinutes = Math.round(((diff % 86400000) % 3600000) / 60000).toString(); const diffMinutes = Math.floor(((diff % 86400000) % 3600000) / 60000).toString();
layout.eta.label = "ETA: -"+ diffHour + ":" + diffMinutes.padStart(2, '0'); layout.eta.label = "ETA: -"+ diffHour + ":" + diffMinutes.padStart(2, '0');
layout.render(); layout.render();
} }

View File

@ -2,7 +2,7 @@
"id": "sleepphasealarm", "id": "sleepphasealarm",
"name": "SleepPhaseAlarm", "name": "SleepPhaseAlarm",
"shortName": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm",
"version": "0.06", "version": "0.07",
"description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.",
"icon": "app.png", "icon": "app.png",
"tags": "alarm", "tags": "alarm",

View File

@ -1,2 +1,3 @@
0.01: Initial version 0.01: Initial version
0.02: Do not warn multiple times for the same exceedance 0.02: Do not warn multiple times for the same exceedance
0.03: Fix crash

View File

@ -2,7 +2,7 @@
"id": "widbaroalarm", "id": "widbaroalarm",
"name": "Barometer Alarm Widget", "name": "Barometer Alarm Widget",
"shortName": "Barometer Alarm", "shortName": "Barometer Alarm",
"version": "0.02", "version": "0.03",
"description": "A widget that can alarm on when the pressure reaches defined thresholds.", "description": "A widget that can alarm on when the pressure reaches defined thresholds.",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",

View File

@ -104,7 +104,7 @@
saveSetting("lastHighWarningTs", 0); saveSetting("lastHighWarningTs", 0);
} }
if (!alreadyWarned) { if (history3.length > 0 && !alreadyWarned) {
// 3h change detection // 3h change detection
const drop3halarm = setting("drop3halarm"); const drop3halarm = setting("drop3halarm");
const raise3halarm = setting("raise3halarm"); const raise3halarm = setting("raise3halarm");