mirror of https://github.com/espruino/BangleApps
Merge branch 'master' of github.com:espruino/BangleApps
commit
5bc4ecac48
|
@ -11,3 +11,4 @@ tests/Layout/bin/tmp.*
|
|||
tests/Layout/testresult.bmp
|
||||
apps.local.json
|
||||
_site
|
||||
.jekyll-cache
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Set Bangle.js 2 compatible
|
||||
0.03: Add setting to hide the widget
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
"id": "gpsautotime",
|
||||
"name": "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.",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
"tags": "widget,gps",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"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"}]
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
|
@ -1,6 +1,13 @@
|
|||
(() => {
|
||||
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) {
|
||||
if (fix.fix) {
|
||||
var curTime = fix.time.getTime()/1000;
|
||||
|
@ -14,8 +21,9 @@
|
|||
// add your widget
|
||||
WIDGETS["gpsAutoTime"]={
|
||||
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() {
|
||||
if (!show) return;
|
||||
g.reset(); // reset the graphics context to defaults (color/font/etc)
|
||||
g.setFont("6x8");
|
||||
if ((getTime() - lastTimeSet) <= 60) {
|
||||
|
@ -27,7 +35,9 @@
|
|||
}
|
||||
};
|
||||
|
||||
setInterval(function() {
|
||||
WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]);
|
||||
}, 1*60000); // update every minute
|
||||
})()
|
||||
if (show) {
|
||||
setInterval(function() {
|
||||
WIDGETS["gpsAutoTime"].draw(WIDGETS["gpsAutoTime"]);
|
||||
}, 1*60000); // update every minute
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Introduced settings to customize the layout and functionality of the keyboard.
|
||||
|
|
|
@ -2,6 +2,17 @@
|
|||
|
||||
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
|
||||
|
||||
In your app's metadata, add:
|
||||
|
|
|
@ -69,13 +69,24 @@ var KEYEXTRA = [
|
|||
String.fromCharCode(27,91,53,126), // 0x84 page up
|
||||
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
|
||||
const R = Bangle.appRect;
|
||||
var kbx = 0, kby = 0, kbdx = 0, kbdy = 0, kbShift = false, flashToggle = false;
|
||||
const PX=12, PY=16, DRAGSCALE=24;
|
||||
var xoff = 3, yoff = g.getHeight()-PY*4;
|
||||
const PX=12, PY=16, DRAGSCALE=settings.speedScaling;
|
||||
var xoff = 3, yoff = g.getHeight()-PY*(4+5*settings.offsetKeyboard);
|
||||
|
||||
function draw() {
|
||||
"ram";
|
||||
var map = kbShift ? KEYMAPUPPER : KEYMAPLOWER;
|
||||
//g.drawImage(KEYIMG,0,yoff);
|
||||
g.reset().setFont("6x8:2");
|
||||
|
@ -88,9 +99,9 @@ function draw() {
|
|||
g.drawString(map[1],xoff,yoff+PY);
|
||||
g.drawString(map[2],xoff,yoff+PY*2);
|
||||
g.drawString(map[3],xoff,yoff+PY*3);
|
||||
var l = g.setFont("6x8:4").wrapString(text+(flashToggle?"_":" "), R.w-8);
|
||||
if (l.length>2) l=l.slice(-2);
|
||||
g.drawString(l.join("\n"),R.x+4,R.y+4);
|
||||
var l = g.setFont(settings.textSize ? "6x8:4":"6x8:2").wrapString(text+(flashToggle?"_":" "), R.w-8);
|
||||
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 +82*settings.offsetKeyboard);
|
||||
|
||||
g.flip();
|
||||
}
|
||||
|
@ -104,24 +115,49 @@ function draw() {
|
|||
return new Promise((resolve,reject) => {
|
||||
|
||||
Bangle.setUI({mode:"custom", drag:e=>{
|
||||
kbdx += e.dx;
|
||||
kbdy += e.dy;
|
||||
var dx = Math.round(kbdx/DRAGSCALE), dy = Math.round(kbdy/DRAGSCALE);
|
||||
kbdx -= dx*DRAGSCALE;
|
||||
kbdy -= dy*DRAGSCALE;
|
||||
if (dx || dy) {
|
||||
kbx = (kbx+dx+15)%15;
|
||||
kby = (kby+dy+4)%4;
|
||||
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;
|
||||
kbdy += e.dy;
|
||||
var dx = Math.round(kbdx/DRAGSCALE), dy = Math.round(kbdy/DRAGSCALE);
|
||||
kbdx -= dx*DRAGSCALE;
|
||||
kbdy -= dy*DRAGSCALE;
|
||||
if (dx || dy) {
|
||||
if (settings.loopAround) {
|
||||
kbx = (kbx+dx+15)%15;
|
||||
kby = (kby+dy+4)%4;
|
||||
} else {
|
||||
kbx = Math.max(Math.min((kbx+dx),13),0);
|
||||
kby = Math.max(Math.min((kby+dy),3),0);
|
||||
}
|
||||
}
|
||||
}
|
||||
draw();
|
||||
|
||||
if (!e.b && e.y>Bangle.appRect.y && 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();
|
||||
}
|
||||
},touch:()=>{
|
||||
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();
|
||||
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:()=>{
|
||||
clearInterval(flashInterval);
|
||||
Bangle.setUI();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ "id": "kbtouch",
|
||||
"name": "Touch keyboard",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "A library for text input via onscreen keyboard",
|
||||
"icon": "app.png",
|
||||
"type":"textinput",
|
||||
|
@ -9,6 +9,7 @@
|
|||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"textinput","url":"lib.js"}
|
||||
{"name":"textinput","url":"lib.js"},
|
||||
{"name":"kbtouch.settings.js","url":"settings.js"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
})
|
|
@ -5,3 +5,4 @@
|
|||
0.05: Refactor decodeTime() to scheduling library
|
||||
0.06: Add logging
|
||||
use Layout library and display ETA
|
||||
0.07: Add check for day of week
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Sleep Phase Alarm
|
||||
|
||||
The alarm must be in the next 24h.
|
||||
|
||||
The display shows:
|
||||
|
||||
- the current time
|
||||
|
|
|
@ -51,8 +51,10 @@ active.forEach(alarm => {
|
|||
if (dateAlarm < now) { // dateAlarm in the past, add 24h
|
||||
dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000));
|
||||
}
|
||||
if (nextAlarm === undefined || dateAlarm < nextAlarm) {
|
||||
nextAlarm = dateAlarm;
|
||||
if ((alarm.dow >> dateAlarm.getDay()) & 1) { // check valid day of week
|
||||
if (nextAlarm === undefined || dateAlarm < nextAlarm) {
|
||||
nextAlarm = dateAlarm;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -80,7 +82,7 @@ function drawApp() {
|
|||
layout.date.label = locale.time(now, BANGLEJS2 && Bangle.isLocked() ? 1 : 0); // hide seconds on bangle 2
|
||||
const diff = nextAlarm - now;
|
||||
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.render();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "sleepphasealarm",
|
||||
"name": "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.",
|
||||
"icon": "app.png",
|
||||
"tags": "alarm",
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: Initial version
|
||||
0.02: Do not warn multiple times for the same exceedance
|
||||
0.03: Fix crash
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widbaroalarm",
|
||||
"name": "Barometer Alarm Widget",
|
||||
"shortName": "Barometer Alarm",
|
||||
"version": "0.02",
|
||||
"version": "0.03",
|
||||
"description": "A widget that can alarm on when the pressure reaches defined thresholds.",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
saveSetting("lastHighWarningTs", 0);
|
||||
}
|
||||
|
||||
if (!alreadyWarned) {
|
||||
if (history3.length > 0 && !alreadyWarned) {
|
||||
// 3h change detection
|
||||
const drop3halarm = setting("drop3halarm");
|
||||
const raise3halarm = setting("raise3halarm");
|
||||
|
|
Loading…
Reference in New Issue