Merge branch 'master' into master

pull/1003/head
Gordon Williams 2021-12-06 08:35:55 +00:00 committed by GitHub
commit 69c1d66a7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 331 additions and 34 deletions

View File

@ -104,7 +104,7 @@
"id": "launch",
"name": "Launcher",
"shortName": "Launcher",
"version": "0.09",
"version": "0.10",
"description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
"icon": "app.png",
"type": "launch",
@ -112,8 +112,10 @@
"supports": ["BANGLEJS","BANGLEJS2"],
"storage": [
{"name":"launch.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]},
{"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]}
{"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]},
{"name":"launch.settings.js","url":"settings.js","supports":["BANGLEJS2"]}
],
"data": [{"name":"launch.json"}],
"sortorder": -10
},
{
@ -4449,7 +4451,7 @@
"shortName": "AuthWatch",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],
"version": "0.03",
"version": "0.04",
"description": "Google Authenticator compatible tool.",
"tags": "tool",
"interface": "interface.html",
@ -4687,6 +4689,21 @@
"supports": ["BANGLEJS","BANGLEJS2"],
"storage": [
{"name":"widChargingStatus.wid.js","url":"widget.js"}
]
},
{
"id": "flow",
"name": "FLOW",
"shortName": "FLOW",
"version": "0.01",
"description": "A game where you have to help a flow avoid white obstacles thing by tapping! This is a demake of an app which I forgot the name of. Press BTN(1) to restart. See if you can get to 2500 score!",
"icon": "app.png",
"tags": "game",
"supports" : ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name": "flow.app.js", "url": "app.js" },
{"name": "flow.img", "url": "app-icon.js","evaluate": true }
]
}
]

View File

@ -1,3 +1,4 @@
0.04: Fix tapping at very bottom of list, exit on inactivity
0.03: Add "Calculating" placeholder, update JSON save format
0.02: Fix JSON save format
0.01: First release

View File

@ -10,6 +10,8 @@ const calculating = "Calculating";
const notokens = "No tokens";
const notsupported = "Not supported";
// sample settings:
// {tokens:[{"algorithm":"SHA1","digits":6,"period":30,"issuer":"","account":"","secret":"Bbb","label":"Aaa"}],misc:{}}
var settings = require("Storage").readJSON("authentiwatch.json", true) || {tokens:[],misc:{}};
if (settings.data ) tokens = settings.data ; /* v0.02 settings */
if (settings.tokens) tokens = settings.tokens; /* v0.03+ settings */
@ -146,14 +148,14 @@ function drawToken(id, r) {
// counter - draw triangle as swipe hint
let yc = (y1 + y2) / 2;
g.fillPoly([0, yc, 10, yc - 10, 10, yc + 10, 0, yc]);
adj = 5;
adj = 10;
}
// digits just below label
sz = 30;
do {
g.setFont("Vector", sz--);
} while (g.stringWidth(state.otp) > (r.w - adj));
g.drawString(state.otp, (x1 + x2) / 2 + adj, y1 + 16, false);
g.drawString(state.otp, (x1 + adj + x2) / 2, y1 + 16, false);
}
// shaded lines top and bottom
g.setColor(0.5, 0.5, 0.5);
@ -163,6 +165,8 @@ function drawToken(id, r) {
}
function draw() {
var timerfn = exitApp;
var timerdly = 10000;
var d = new Date();
if (state.curtoken != -1) {
var t = tokens[state.curtoken];
@ -203,17 +207,13 @@ function draw() {
y += tokenentryheight;
}
if (drewcur) {
// the current token has been drawn - draw it again in 1sec
if (state.drawtimer) {
clearTimeout(state.drawtimer);
}
var dly;
// the current token has been drawn - schedule a redraw
if (tokens[state.curtoken].period > 0) {
dly = (state.otp == calculating) ? 1 : 1000;
timerdly = (state.otp == calculating) ? 1 : 1000; // timed
} else {
dly = state.nexttime - d.getTime();
timerdly = state.nexttime - d.getTime(); // counter
}
state.drawtimer = setTimeout(draw, dly);
timerfn = draw;
if (tokens[state.curtoken].period <= 0) {
state.hide = 0;
}
@ -230,12 +230,16 @@ function draw() {
g.setFontAlign(0, 0, 0);
g.drawString(notokens, Bangle.appRect.x + Bangle.appRect.w / 2, Bangle.appRect.y + Bangle.appRect.h / 2, false);
}
if (state.drawtimer) {
clearTimeout(state.drawtimer);
}
state.drawtimer = setTimeout(timerfn, timerdly);
}
function onTouch(zone, e) {
if (e) {
var id = Math.floor((state.listy + (e.y - Bangle.appRect.y)) / tokenentryheight);
if (id == state.curtoken || tokens.length == 0) {
if (id == state.curtoken || tokens.length == 0 || id >= tokens.length) {
id = -1;
}
if (state.curtoken != id) {
@ -254,26 +258,20 @@ function onTouch(zone, e) {
state.nextTime = 0;
state.curtoken = id;
state.hide = 2;
draw();
}
}
draw();
}
function onDrag(e) {
if (e.x > g.getWidth() || e.y > g.getHeight()) return;
if (e.dx == 0 && e.dy == 0) return;
var newy = Math.min(state.listy - e.dy, tokens.length * tokenentryheight - Bangle.appRect.h);
newy = Math.max(0, newy);
if (newy != state.listy) {
state.listy = newy;
draw();
}
state.listy = Math.max(0, newy);
draw();
}
function onSwipe(e) {
if (e == 1) {
Bangle.showLauncher();
}
if (e == -1 && state.curtoken != -1 && tokens[state.curtoken].period <= 0) {
tokens[state.curtoken].period--;
let newsettings={tokens:tokens,misc:settings.misc};
@ -281,8 +279,8 @@ function onSwipe(e) {
state.nextTime = 0;
state.otp = "";
state.hide = 2;
draw();
}
draw();
}
function bangle1Btn(e) {
@ -302,16 +300,22 @@ function bangle1Btn(e) {
state.curtoken = -1;
state.nextTime = 0;
onTouch(0, fakee);
} else {
draw(); // resets idle timer
}
}
function exitApp() {
Bangle.showLauncher();
}
Bangle.on('touch', onTouch);
Bangle.on('drag' , onDrag );
Bangle.on('swipe', onSwipe);
if (typeof BTN2 == 'number') {
setWatch(function(){bangle1Btn(-1); }, BTN1, {edge:"rising", debounce:50, repeat:true});
setWatch(function(){Bangle.showLauncher();}, BTN2, {edge:"rising", debounce:50, repeat:true});
setWatch(function(){bangle1Btn( 1); }, BTN3, {edge:"rising", debounce:50, repeat:true});
setWatch(function(){bangle1Btn(-1);}, BTN1, {edge:"rising", debounce:50, repeat:true});
setWatch(function(){exitApp(); }, BTN2, {edge:"rising", debounce:50, repeat:true});
setWatch(function(){bangle1Btn( 1);}, BTN3, {edge:"rising", debounce:50, repeat:true});
}
Bangle.loadWidgets();

12
apps/flow/README.md Normal file
View File

@ -0,0 +1,12 @@
# FLOW
This is a game where you have to help a flow avoid white obstacles thing by tapping!
This is a demake of an app which I forgot the name of.
Press BTN(1) to restart.
See if you can get to 2500 score!
## Screenshots
![](screenshot1.png)
![](screenshot2.png)
![](screenshot3.png)

1
apps/flow/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEw4X/AwX48EHgEC1WgCQkVqoDBBfuqBQcBqoLagEqGAguBqALaGAOoAoQuEBbEAKgIMBBQNUBbgMCyoKHBbBVBBYIKGBbEBtNVrQLfOgNaT4gLagp0CPQOABbcBFwNAgEKBgILbitVqAFClWq0ALZFwTDFGAQLZFwYwDBfg"))

220
apps/flow/app.js Normal file
View File

@ -0,0 +1,220 @@
const isB2 = process.env.HWVERSION === 2;
// Bangle.js 1 runs just too fast in direct mode??? (also no getPixel)
if (!isB2) Bangle.setLCDMode("120x120");
const options = Bangle.getOptions();
options.lockTimeout = 0;
options.lcdPowerTimeout = 0;
Bangle.setOptions(options);
g.reset();
g.setBgColor(0, 0, 0);
g.setColor(255, 255, 255);
g.clear();
const h = g.getHeight();
function trigToCoord(ret) {
return ((ret + 1) * h) / 2;
}
function trigToLen(ret) {
return (ret * h) / 2;
}
let i = 0.2;
let speedCoef = 0.014;
let flowFile = require("Storage").readJSON("flow.json");
let highestI = (flowFile && flowFile.hiscore) || 0.1;
let colorA = [255, 255, 0];
let colorB = [0, 255, 255];
let x = 0;
let xt = 0;
let safeMode = false;
let lost = false;
function offsetRect(g, x, y, w) {
g.fillRect(x, y, x + w, y + w);
}
function getColor(num) {
return [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 1, 0],
[0, 1, 1],
[1, 0, 1],
[0.5, 0.5, 1],
[1, 0.5, 0],
[0, 1, 0.5],
[0.5, 0.5, 0.5],
][num];
}
function calculateColor(num) {
colorA = getColor(Math.floor((num % 1) * 10));
colorB = getColor(Math.floor((num % 10) - (num % 1)));
}
calculateColor(highestI);
Bangle.on("touch", () => (safeMode = !safeMode));
function resetGame() {
x = xt = 0;
safeMode = lost = false;
i = 0.2;
speedCoef = 0.014;
obstaclePeriod = 150;
obstacleMode = 1;
g.clear();
shownScore = false;
intervalId = setInterval(draw);
}
function checkCollision() {
lost = g.getPixel(trigToCoord(+x), (h * 2) / 3 - 4) !== 0;
if (lost) {
scoringI = i;
speedCoef = Math.min(speedCoef, 0.02);
g.setFont(isB2 ? "6x15" : "4x6", 3);
g.setColor(colorA[0], colorA[1], colorA[2])
.drawString(
"Game over",
trigToCoord(0) - g.stringWidth("Game over") / 2,
trigToCoord(0)
)
.setColor(1, 1, 1);
}
}
function drawPlayer() {
if (!safeMode) xt = Math.cos(i * Math.PI * 4) / 7.5;
else xt = -Math.cos(i * Math.PI * 2) / 20 + 0.35;
x = x * 0.8 + xt * 0.2;
if (highestI > 250) calculateColor(i);
g.setColor(colorA[0], colorA[1], colorA[2]);
offsetRect(g, trigToCoord(+x), (h * 2) / 3, 3);
g.setColor(colorB[0], colorB[1], colorB[2]);
offsetRect(g, trigToCoord(-x), (h * 2) / 3, 3);
}
let obstaclePeriod = 150;
let obstacleMode = 1;
function drawObstracle() {
g.setColor(1, 1, 1);
switch (obstacleMode) {
case 0:
offsetRect(g, trigToCoord(-0.15), 0, trigToLen(0.3));
break;
case 1:
offsetRect(g, trigToCoord(0.2), 0, trigToLen(0.2));
offsetRect(g, trigToCoord(-0.4), 0, trigToLen(0.2));
break;
case 2:
break;
}
obstaclePeriod--;
if (obstaclePeriod <= 0) {
// If we are off cooldown mode, pick a random actual mode
if (obstacleMode === 2) {
obstaclePeriod = Math.random() * 50 + 50;
obstacleMode = Math.round(Math.random());
} else if (Math.random() > 0.5) {
// Give it a chance to repeat with no cooldown
obstaclePeriod = 25 + 2.5 * speedCoef;
obstacleMode = 2;
}
}
}
let shownScore = false;
let scoringI = 0;
function draw() {
if (!lost) {
drawPlayer();
checkCollision();
speedCoef *= 1.0005;
drawObstracle();
} else {
speedCoef /= 1.05;
if (speedCoef <= 0.005) {
clearInterval(intervalId);
i -= speedCoef;
g.setFont(isB2 ? "6x15" : "4x6", 1);
const str = "Hiscore: " + Math.round(highestI * 10);
g.setColor(
scoringI > highestI ? 0 : 255,
0,
scoringI > highestI ? 255 : 0
)
.drawString(
str,
trigToCoord(0) - g.stringWidth(str) / 2,
trigToCoord(0)
)
.setColor(255, 255, 255);
if (scoringI > highestI) {
highestI = scoringI;
require("Storage").writeJSON("flow.json", {
hiscore: highestI,
});
calculateColor(highestI);
}
setTimeout(resetGame, 3000);
} else if (speedCoef <= 0.01 && !shownScore) {
shownScore = true;
g.setFont(isB2 ? "6x15" : "4x6", 2);
const str = "Score: " + Math.round(scoringI * 10);
g.setColor(colorB[0], colorB[1], colorB[2])
.drawString(
str,
trigToCoord(0) - g.stringWidth(str) / 2,
trigToCoord(0)
)
.setColor(1, 1, 1);
}
}
i += speedCoef;
g.scroll(0, speedCoef * h);
g.flip();
}
let intervalId;
if (BTN.read()) {
for (let i = 0; i < 10; i++) {
color = getColor(i);
g.setColor(color[0], color[1], color[2]);
g.fillRect((i / 10) * h, 0, ((i + 1) / 10) * h, h);
}
g.setColor(0);
g.setFont("Vector", 9);
let str = "Welcome to the debug screen!";
g.drawString(
str,
trigToCoord(0) - g.stringWidth(str) / 2,
trigToCoord(0) - 9
);
str = "Don't hold BTN while opening to play!";
g.drawString(str, trigToCoord(0) - g.stringWidth(str) / 2, trigToCoord(0));
g.flip();
setInterval(() => {
g.scroll(0, 0.014 * h);
i += 0.014;
calculateColor(i);
g.setColor(colorA[0], colorA[1], colorA[2]);
g.fillRect(0, 0, trigToCoord(0), 0.014 * h);
g.setColor(colorB[0], colorB[1], colorB[2]);
g.fillRect(trigToCoord(0), 0, trigToCoord(1), 0.014 * h);
}, 1000 / 30);
} else intervalId = setInterval(draw, 1000 / 30);

BIN
apps/flow/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

BIN
apps/flow/screenshot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

BIN
apps/flow/screenshot2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
apps/flow/screenshot3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -8,3 +8,4 @@
0.08: Merge Bangle.js 1 and 2 launchers
0.09: Bangle.js 2 - pressing the button goes back to clock (fix #971)
After 10s of being locked, the launcher goes back to the clock screen
0.10: added in selectable font in settings including scalable vector font

View File

@ -1,4 +1,22 @@
var s = require("Storage");
let fonts = g.getFonts();
var scaleval = 1;
var vectorval = 20;
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
let settings = require('Storage').readJSON("launch.json", true) || {};
if ("vectorsize" in settings) {
vectorval = parseInt(settings.vectorsize);
}
if ("font" in settings){
if(settings.font == "Vector"){
scaleval = vectorval/20;
font = "Vector"+(vectorval).toString();
}
else{
font = settings.font;
scaleval = (font.split('x')[1])/20;
}
}
var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type));
apps.sort((a,b)=>{
var n=(0|a.sortorder)-(0|b.sortorder);
@ -11,8 +29,6 @@ apps.forEach(app=>{
if (app.icon)
app.icon = s.read(app.icon); // should just be a link to a memory area
});
// FIXME: not needed after 2v11
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
// FIXME: check not needed after 2v11
if (g.wrapString) {
g.setFont(font);
@ -22,9 +38,9 @@ if (g.wrapString) {
function drawApp(i, r) {
var app = apps[i];
if (!app) return;
g.clearRect(r.x,r.y,r.x+r.w-1, r.y+r.h-1);
g.setFont(font).setFontAlign(-1,0).drawString(app.name,64,r.y+32);
if (app.icon) try {g.drawImage(app.icon,8,r.y+8);} catch(e){}
g.clearRect((r.x),(r.y),(r.x+r.w-1), (r.y+r.h-1));
g.setFont(font).setFontAlign(-1,0).drawString(app.name,64*scaleval,r.y+(32*scaleval));
if (app.icon) try {g.drawImage(app.icon,8*scaleval, r.y+(8*scaleval), {scale: scaleval});} catch(e){}
}
g.clear();
@ -32,7 +48,7 @@ Bangle.loadWidgets();
Bangle.drawWidgets();
E.showScroller({
h : 64, c : apps.length,
h : 64*scaleval, c : apps.length,
draw : drawApp,
select : i => {
var app = apps[i];

25
apps/launch/settings.js Normal file
View File

@ -0,0 +1,25 @@
// make sure to enclose the function in parentheses
(function(back) {
let settings = require('Storage').readJSON('launch.json',1)||{};
let fonts = g.getFonts();
function save(key, value) {
settings[key] = value;
require('Storage').write('launch.json',settings);
}
const appMenu = {
'': {'title': 'Launcher Settings'},
'< Back': back,
'Font': {
value: fonts.includes(settings.font)? fonts.indexOf(settings.font) : fonts.indexOf("12x20"),
min:0, max:fonts.length-1, step:1,wrap:true,
onchange: (m) => {save('font', fonts[m])},
format: v => fonts[v]
},
'Vector font size': {
value: settings.vectorsize || 10,
min:10, max: 20,step:1,wrap:true,
onchange: (m) => {save('vectorsize', m)}
}
};
E.showMenu(appMenu);
});

2
core

@ -1 +1 @@
Subproject commit 23854083e0c3f83c649073a2d85e8079efc471d3
Subproject commit 59f80bb52a38da12cb272f9106cb3951b49dab2e