Merge branch 'master' into messages-home-assistant-logo

pull/1488/head
Gordon Williams 2022-02-22 10:12:01 +00:00 committed by GitHub
commit d13631f4be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 1159 additions and 221 deletions

View File

@ -0,0 +1,356 @@
/*
7x7DotsClock
by Peter Kuppelwieser
*/
let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {});
// position on screen
var Xs = 0, Ys = 30,Xe = 175, Ye=175;
//const Xs = 0, Ys = 0,Xe = 175, Ye=175;
var SegH = (Ye-Ys)/2,SegW = (Xe-Xs)/2;
var Dx = SegW/14, Dy = SegH/16;
const hColor = [1,1,1];
const mColor = [0.3,0.3,1];
const bColor = [0.2,0.2,0.2];
const Font = [
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,0,0],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[0,0,0,1,1,1,1],
[0,0,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[1,1,0,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,1,1,0,0],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0]
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,0,0],
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[1,1,0,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1]
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1]
],
[
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1]
],
];
// Global Vars
var dho = -1, eho = -1, dmo = -1, emo = -1;
function drawHSeg(x1,y1,x2,y2,Num,dColor,Size) {
g.setColor(0,0,0);
g.fillRect(x1, y1, x2, y2);
for (let i = 1; i < 8; i++) {
for (let j = 1; j < 8; j++) {
if (Font[Num][j-1][i-1] == 1) {
g.setColor(dColor[0],dColor[1],dColor[2]);
g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,Size);
} else {
g.setColor(bColor[0],bColor[1],bColor[2]);
g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,1);
}
}
}
}
function drawSSeg(x1,y1,x2,y2,Num,dColor,Size) {
for (let i = 1; i < 8; i++) {
for (let j = 1; j < 8; j++) {
if (Font[Num][j-1][i-1] == 1) {
g.setColor(dColor[0],dColor[1],dColor[2]);
g.fillCircle(x1+(i-1)*(x2-x1)/7,y1+(j-1)*(y2-y1)/7,Size);
}
}
}
}
function ShowSecons() {
g.setColor(1,1,1);
g.fillRect((Xe-Xs) / 2 - 14 + Xs -3,
(Ye-Ys) / 2 - 7 + Ys -3,
(Xe-Xs) / 2 + 14 + Xs +1,
(Ye-Ys) / 2 + 7 + Ys +1);
drawSSeg( (Xe-Xs) / 2 - 14 + Xs -1,
(Ye-Ys) / 2 - 7 + Ys ,
(Xe-Xs) / 2 + Xs -1,
(Ye-Ys) / 2 + 7 + Ys,
ds,mColor,1);
drawSSeg( (Xe-Xs) / 2 + Xs +1,
(Ye-Ys) / 2 - 7 + Ys,
(Xe-Xs) / 2 + 14 + Xs +1,
(Ye-Ys) / 2 + 7 + Ys,
es,mColor,1);
}
function draw() {
// work out how to display the current time
var d = new Date();
var h = d.getHours(), m = d.getMinutes(), s = d.getSeconds();
dh = Math.floor(h/10);
eh = h - dh * 10;
dm = Math.floor(m/10);
em = m - dm * 10;
ds = Math.floor(s/10);
es = s - ds * 10;
// Reset the state of the graphics library
g.reset();
if (dh != dho) {
g.setColor(1,1,1);
drawHSeg(Xs, Ys, Xs+SegW, Ys+SegH,dh,hColor,4);
dho = dh;
}
if (eh != eho) {
g.setColor(1,1,1);
drawHSeg(Xs+SegW+Dx, Ys, Xs+SegW*2, Ys+SegH,eh,hColor,4);
eho = eh;
}
if (dm != dmo) {
g.setColor(0.3,0.3,1);
drawHSeg(Xs, Ys+SegH+Dy, Xs+SegW, Ys+SegH*2,dm,mColor,4);
dmo = dm;
}
if (em != emo) {
g.setColor(0.3,0.3,1);
drawHSeg(Xs+SegW+Dx, Ys+SegH+Dy, Xs+SegW*2, Ys+SegH*2,em,mColor,4);
emo = em;
}
if (!Bangle.isLocked()) ShowSecons();
}
function actions(v){
if(BTN1.read() === true) {
print("BTN pressed");
Bangle.showLauncher();
}
if(v==-1){
print("up swipe event");
if(settings.swupApp != "") load(settings.swupApp);
print(settings.swupApp);
} else if(v==1) {
print("down swipe event");
if(settings.swdownApp != "") load(settings.swdownApp);
print(settings.swdownApp);
} else {
print("touch event");
}
}
// Get Messages status
var messages = require("Storage").readJSON("messages.json",1)||[];
//var BTconnected = NRF.getSecurityStatus().connected;
//NRF.on('connect',BTconnected = NRF.getSecurityStatus().connected);
//NRF.on('disconnect',BTconnected = NRF.getSecurityStatus().connected);
function drawWidgeds() {
//Bluetooth
//print(BluetoothDevice.connected);
var x1Bt = 160;
var y1Bt = 0;
var x2Bt = x1Bt + 30;
var y2Bt = y2Bt;
if (NRF.getSecurityStatus().connected)
g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f"));
else
g.setColor(g.theme.dark ? "#666" : "#999");
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),x1Bt,y1Bt);
//Battery
//print(E.getBattery());
//print(Bangle.isCharging());
var x1B = 130;
var y1B = 2;
var x2B = x1B + 20;
var y2B = y1B + 15;
g.setColor(g.theme.bg);
g.clearRect(x1B,y1B,x2B,y2B);
g.setColor(g.theme.fg);
g.drawRect(x1B,y1B,x2B,y2B);
g.fillRect(x1B,y1B,x1B+(E.getBattery()*(x2B-x1B)/100),y2B);
g.fillRect(x2B,y1B+(y2B-y1B)/2-3,x2B+4,y1B+(y2B-y1B)/2+3);
//Messages
var x1M = 100;
var y1M = y1B;
var x2M = x1M + 30;
var y2M = y2B;
if (messages.some(m=>m.new)) {
g.setColor(g.theme.fg);
g.fillRect(x1M,y1M,x2M,y2M);
g.setColor(g.theme.bg);
g.drawLine(x1M,y1M,x1M+(x2M-x1M)/2,y1M+(y2M-y1M)/2);
g.drawLine(x1M+(x2M-x1M)/2,y1M+(y2M-y1M)/2,x2M,y1M);
}
var strDow = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
var d = new Date();
var dow = d.getDay(),day = d.getDate(), month = d.getMonth() + 1, year = d.getFullYear();
print(strDow[dow] + ' ' + day + '.' + month + ' ' + year);
g.setFontAlign(-1, -1,0);
g.setFont("Vector", 20);
g.drawString(strDow[dow] + ' ' + day, 0, 0, true);
}
function SetFull(on) {
dho = -1; eho = -1; dmo = -1; emo = -1;
g.clear();
if (on === true) {
Ys = 0;
Bangle.setUI("clock");
Bangle.on('swipe', function(direction) { });
} else {
Ys = 30;
Bangle.setUI("updown",actions);
Bangle.on('swipe', function(direction) {
switch (direction) {
case 1:
print("swipe left event");
if(settings.swleftApp != "") load(settings.swleftApp);
print(settings.swleftApp);
break;
case -1:
print("swipe right event");
if(settings.swrightApp != "") load(settings.swrightApp);
print(settings.swrightApp);
break;
default:
print("swipe undefined event");
}
});
}
SegH = (Ye-Ys)/2;
Dy = SegH/16;
draw();
if (on != true) {
//Bangle.loadWidgets();
//Bangle.drawWidgets();
drawWidgeds();
}
}
Bangle.on('lock', function(on) {
SetFull(on);
});
SetFull(Bangle.isLocked());
var secondInterval = setInterval(draw, 1000);

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkEBAkTmEzkAHDmcjmQBBmcTmICCgMAiMAkE/+P/mEQgMQgH/n/zAIP/l/yA4QvXC4kDkEjFgIACkcSmMTkMyBoQHBI4kvI6wXBn8wA4c/mfzl8y+cfEoIaBVa5HBAAMQF4UgIoIBBBgJNBAwQ3BkfygSnJSQIUBkECiBoCL48DmCPFAA6PCX40jX4hYEU4LNBX4JHIkBHCBgJHBianKj8wO4IvHgSnBmJ3CHYqGCABcRcYTXLAA5KCFAJfCC4KnDX4anNgUgiSnMkQQBO5hvCl8yO4pHEd4oyBH4QBBU5TXHkcimUTkLXFL44HEiTbBO4MhBoQHBI4KECR45HGBoIFBU4y/BC4c/mYXGMQJHFiBHLEAIHCf5gAKhWg1UB0IEBjUA0MB0EAjQKCiANCCQOg0cxmcSmWjU4MqmcDmSnDBASkBmejCQIXFmYXEmYXHicyhRLC0AEBAIJFBAIIFCBAYHDF65fXR66vImUCnS8IkeinUBgERgEgcIMBgRHDBgLvCBYMQmcjBYIAHfwL7JiQLBichkcSnUSO4MhI4MxI5MSmMjPgMinCnCkRHGIgJHFiUgkUalUCAgMRkUCkIvIkUSkMC0EiBxAAI0UKkBHCkCPDgA+CI5Z3BmYPBAB53CV4MSEgcSiCnOR4cyR5JQEgBHCC4I0BC4UjC4MCxQXGF4IlBxRHB0UAlUK0BMBkIEBI5ILB0ZHBF4czlTXHI4mjCQIXOH4KnDC4MKgGqgGgAgIBBIoJHJBoQ="))

View File

@ -0,0 +1,65 @@
(function(back) {
let settings = Object.assign({ swupApp: "",swdownApp: "", swleftApp: "", swrightApp: ""}, require("Storage").readJSON("7x7dotsclock.json", true) || {});
function showMainMenu() {
const mainMenu = {
"": {"title": "7x7 Dots Clock Settings"},
"< Back": ()=>load(),
"sw-up": ()=>showSelAppMenu("swupApp"),
"sw-down": ()=>showSelAppMenu("swdownApp"),
"sw-left": ()=>showSelAppMenu("swleftApp"),
"sw-right": ()=>showSelAppMenu("swrightApp")
};
E.showMenu(mainMenu);
}
function setSetting(key,value) {
print("call " + key + " = " + value);
settings[key] = value;
print("storing settings 7x7dotsclock.json");
storage.write('7x7dotsclock.json', settings);
}
function showSelAppMenu(key) {
var Apps = require("Storage").list(/\.info$/)
.map(app => {var a=storage.readJSON(app, 1);return (
a&&a.name != "Launcher"
&& a&&a.name != "Bootloader"
&& a&&a.type != "clock"
&& a&&a.type !="widget"
)?a:undefined})
.filter(app => app) // filter out any undefined apps
.sort((a, b) => a.sortorder - b.sortorder);
const SelAppMenu = {
'': {
'title': /*LANG*/'Select App',
},
'< Back': ()=>showMainMenu(),
};
Apps.forEach((app, index) => {
var label = app.name;
if (settings[key] === app.src) {
label = "* " + label;
}
SelAppMenu[label] = () => {
if (settings[key] !== app.src) {
setSetting(key,app.src);
showMainMenu();
}
};
});
if (Apps.length === 0) {
SelAppMenu[/*LANG*/"No Apps Found"] = () => { };
}
return E.showMenu(SelAppMenu);
}
showMainMenu();
})

View File

@ -0,0 +1 @@
0.01: Initial version for upload

View File

@ -0,0 +1,17 @@
# 7x7 dots clock
![](dotsfontclock.png)
looks best with dark theme so far
* A Clock with big numbers made of 7x7 dots
* system widgeds ar not (yet) supported
* when screen is locked it shows hours and minutes in full screen mode
![](dotsfontclock-scr1.png)
* when screen is unlocked it shows additional info: bluetooth, battery, new message, date and seconds
* you can configure a app per swipe direction
* when swiping the configured apps are launced
* button press opens launcher

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,17 @@
{ "id": "7x7dotsclock",
"name": "7x7 Dots Clock",
"shortName":"7x7 Dots Clock",
"version":"0.01",
"description": "A clock with a big 7x7 dots Font",
"icon": "dotsfontclock.png",
"tags": "clock",
"type": "clock",
"supports" : ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"7x7dotsclock.app.js","url":"7x7dotsclock.app.js"},
{"name":"7x7dotsclock.settings.js","url":"7x7dotsclock.settings.js"},
{"name":"7x7dotsclock.img","url":"7x7dotsclock.img.js","evaluate":true}
],
"data": [{"name":"7x7dotsclock.json"}]
}

View File

@ -7,4 +7,5 @@
when weekday name "On": weekday name is cut at 6th position and .#<week num> is added
0.06: fixes #1271 - wrong settings name
when weekday name and calendar weeknumber are on then display is <weekday short> #<calweek>
week is buffered until date or timezone changes
week is buffered until date or timezone changes
0.07: align default settings with app.js (otherwise the initial displayed settings will be confusing to users)

View File

@ -1,7 +1,7 @@
{
"id": "antonclk",
"name": "Anton Clock",
"version": "0.06",
"version": "0.07",
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
"readme":"README.md",
"icon": "app.png",

View File

@ -38,7 +38,7 @@
},
"< Back": () => back(),
"Seconds...": () => E.showMenu(secmenu),
"Date": stringInSettings("dateOnMain", ["Short", "Long", "ISO8601"]),
"Date": stringInSettings("dateOnMain", ["Long", "Short", "ISO8601"]),
"Show Weekday": {
value: (settings.weekDay !== undefined ? settings.weekDay : true),
format: v => v ? "On" : "Off",
@ -56,7 +56,7 @@
}
},
"Uppercase": {
value: (settings.upperCase !== undefined ? settings.upperCase : false),
value: (settings.upperCase !== undefined ? settings.upperCase : true),
format: v => v ? "On" : "Off",
onchange: v => {
settings.upperCase = v;
@ -81,7 +81,7 @@
"< Back": () => E.showMenu(mainmenu),
"Show": stringInSettings("secondsMode", ["Never", "Unlocked", "Always"]),
"With \":\"": {
value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : false),
value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : true),
format: v => v ? "On" : "Off",
onchange: v => {
settings.secondsWithColon = v;
@ -89,14 +89,14 @@
}
},
"Color": {
value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false),
value: (settings.secondsColoured !== undefined ? settings.secondsColoured : true),
format: v => v ? "On" : "Off",
onchange: v => {
settings.secondsColoured = v;
writeSettings();
}
},
"Date": stringInSettings("dateOnSecs", ["No", "Year", "Weekday"])
"Date": stringInSettings("dateOnSecs", ["Year", "Weekday", "No"])
};
// Actually display the menu

View File

@ -1,2 +1,3 @@
0.01: New game! BTN4- Hit card, BTN5- Stand
0.02: ignore buttons on pauses
0.02: Ignore buttons on pauses
0.03: Support Bangle.js 2

207
apps/blackjack/appb2.js Normal file
View File

@ -0,0 +1,207 @@
var Clubs = require("heatshrink").decompress(atob("j0ewcBkmSpICipEAiQLHwA3BBY8gBQMEEA1AJwQgGyAKChILGBQUCFgxwDJpEAO5AVCII44CAQI1GAAg1GAAZQCWxCDEAAqJBQYQAFRIJWCAApcCR4YADPoRWCgQdBPopfCwAdBTw47BcBAvBU44vDfBDUIRIbUHATuQ"));
var Spades = require("heatshrink").decompress(atob("j0ewcBkmSpICuoALJIQILHpAKBJQ+QLIUJBYsgMoY1GBQcCBYmAPgkSEBEAgggIKApBDIg4KFHAZiCAAgsDBQw4DFitJFhQ4FTwplBgRoCSQoRBBYJ6EF4jgUwDUHAVOQA=="));
var Hearts = require("heatshrink").decompress(atob("j0ewY96gMkyAEByVIBQcSpILBhMkBYkEyQLBAQYKCCIQLEEwQgCBYuAEBFJkBBCBYw4CEA44CgQLHIYQsHLJsAEBJEHSQhxENwQADMQoAEKAdAWowLCYJESXggAFGowA/AAQ"));
var Diamonds = require("heatshrink").decompress(atob("j0ewY1ykgKJhIKJiVIEBOSoAKHpILBBQ+SBYOQBIsBCgILBwAKEgQgCAQIKEggICAQMgKwgUDAQI1GBY4IFLgoLGJpGSPoo4EMoxNIMoqSHiR6HLgizIPoLgfAFA"));
var deck = [];
var player = {Hand:[]};
var computer = {Hand:[]};
var ctx = {ready:true};
function createDeck() {
var suits = ["Spades", "Hearts", "Diamonds", "Clubs"];
var values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"];
var dck = [];
for (var i = 0 ; i < values.length; i++) {
for(var x = 0; x < suits.length; x++) {
dck.push({ Value: values[i], Suit: suits[x] });
}
}
return dck;
}
function shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
function EndGameMessdage(msg){
ctx.ready = false;
g.clearRect(0,160,176,176);
g.setColor(255,255,255);
g.fillRect(0,160,176,176);
g.setColor(0,0,0);
g.drawString(msg, 12, 155);
setTimeout(function(){
startGame();
}, 2500);
}
function hitMe() {
if (!ctx.ready) return;
player.Hand.push(deck.pop());
renderOnScreen(1);
var playerWeight = calcWeight(player.Hand, 0);
if(playerWeight == 21)
EndGameMessdage('WINNER');
else if(playerWeight > 21)
EndGameMessdage('LOSER');
}
function calcWeight(hand, hideCard) {
if(hideCard === 1) {
if (hand[0].Value == "J" || hand[0].Value == "Q" || hand[0].Value == "K")
return "10 +";
else if (hand[0].Value == "A")
return "11 +";
else
return parseInt(hand[0].Value) +" +";
}
else {
var weight = 0;
for(i=0; i<hand.length; i++){
if (hand[i].Value == "J" || hand[i].Value == "Q" || hand[i].Value == "K") {
weight += 10;
}
else if (hand[i].Value == "A") {
weight += 1;
}
else
weight += parseInt(hand[i].Value);
}
// Find count of aces because it may be 11 or 1
var numOfAces = hand.filter(function(x){ return x.Value === "A"; }).length;
for (var j = 0; j < numOfAces; j++) {
if (weight + 10 <= 21) {
weight +=10;
}
}
return weight;
}
}
function stand(){
if (!ctx.ready) return;
ctx.ready = false;
function sleepFor( sleepDuration ){
console.log("Sleeping...");
var now = new Date().getTime();
while(new Date().getTime() < now + sleepDuration){ /* do nothing */ }
}
renderOnScreen(0);
var playerWeight = calcWeight(player.Hand, 0);
var bangleWeight = calcWeight(computer.Hand, 0);
while(bangleWeight<17){
sleepFor(500);
computer.Hand.push(deck.pop());
renderOnScreen(0);
bangleWeight = calcWeight(computer.Hand, 0);
}
if (bangleWeight == playerWeight)
EndGameMessdage('TIES');
else if(playerWeight==21 || bangleWeight > 21 || bangleWeight < playerWeight)
EndGameMessdage('WINNER');
else if(bangleWeight > playerWeight)
EndGameMessdage('LOOSER');
}
function renderOnScreen(HideCard) {
const fontName = "6x8";
g.clear(); // clear screen
g.reset(); // default draw styles
g.setFont(fontName, 1);
g.setColor(255,255,255);
g.fillRect(Bangle.appRect);
g.setColor(0,0,0);
g.drawString('Hit', 176/4-10, 160);
g.drawString('Stand', 176/4+176/2-10, 160);
g.setFont(fontName, 3);
for(i=0; i<computer.Hand.length; i++){
g.drawImage(eval(computer.Hand[i].Suit), i*40, -1);
if(i == 1 && HideCard == 1)
g.drawString("?", i*40+8, 30);
else
g.drawString(computer.Hand[i].Value, i*40+8, 30);
}
g.setFont(fontName, 2);
g.drawString('AI has '+ calcWeight(computer.Hand, HideCard), 5, 55);
g.setFont(fontName, 3);
for(i=0; i<player.Hand.length; i++){
g.drawImage(eval(player.Hand[i].Suit), i*40, 83);
g.drawString(player.Hand[i].Value, i*40+8, 110);
}
g.setFont(fontName, 2);
g.drawString('You have ' + calcWeight(player.Hand, 0), 5, 133);
}
function dealHands() {
player.Hand= [];
computer.Hand= [];
ctx.ready = false;
setTimeout(function(){
player.Hand.push(deck.pop());
renderOnScreen(0);
}, 500);
setTimeout(function(){
computer.Hand.push(deck.pop());
renderOnScreen(1);
}, 1000);
setTimeout(function(){
player.Hand.push(deck.pop());
renderOnScreen(1);
}, 1500);
setTimeout(function(){
computer.Hand.push(deck.pop());
renderOnScreen(1);
ctx.ready = true;
}, 2000);
}
function startGame(){
deck = createDeck();
deck = shuffle(deck);
dealHands();
}
Bangle.on('touch', function(btn, e){
var left = parseInt(g.getWidth() * 0.2);
var right = g.getWidth() - left;
var is_left = e.x < left;
var is_right = e.x > right;
if(is_left){
hitMe();
} else if(is_right){
stand();
}
});
setWatch(startGame, BTN1, {repeat:true, edge:"falling"});
startGame();

View File

@ -2,15 +2,16 @@
"id": "blackjack",
"name": "Black Jack game",
"shortName": "Black Jack game",
"version": "0.02",
"version": "0.03",
"description": "Simple implementation of card game Black Jack",
"icon": "blackjack.png",
"tags": "game",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS","BANGLEJS2"],
"screenshots": [{"url":"bangle1-black-jack-game-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"blackjack.app.js","url":"blackjack.app.js"},
{"name":"blackjack.app.js","url":"blackjack.app.js","supports": ["BANGLEJS"]},
{"name":"blackjack.app.js","url":"appb2.js","supports": ["BANGLEJS2"]},
{"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true}
]
}

View File

@ -2,3 +2,4 @@
0.03: Tweak for more efficient rendering, and firmware 2v06
0.04: Work with themes, smaller screens
0.05: Adjust hand lengths to be within 'tick' points
0.06: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up".

View File

@ -129,14 +129,6 @@ Bangle.on('lcdPower', (on) => {
clearTimers();
}
});
Bangle.on('faceUp',function(up){
//console.log("faceUp: " + up + " LCD: " + Bangle.isLCDOn());
if (up && !Bangle.isLCDOn()) {
//console.log("faceUp and LCD off");
clearTimers();
Bangle.setLCDPower(true);
}
});
g.clear();
Bangle.loadWidgets();

View File

@ -1,7 +1,7 @@
{
"id": "boldclk",
"name": "Bold Clock",
"version": "0.05",
"version": "0.06",
"description": "Simple, readable and practical clock",
"icon": "bold_clock.png",
"screenshots": [{"url":"screenshot_bold.png"}],

View File

@ -4,3 +4,4 @@
0.22: Changed timing code, original "Nunito" Font is back!
0.23: Customizer! Unused fonts no longer take up precious memory.
0.24: Added previews to the customizer.
0.25: Fixed a bug that would let widgets change the color of the clock.

View File

@ -10,6 +10,7 @@ if (settings.fontIndex==undefined) {
function draw() {
var date = new Date();
// Draw day of the week
g.reset();
g.setFont("Teletext10x18Ascii");
g.clearRect(0,138,g.getWidth()-1,176);
g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18);

View File

@ -1,7 +1,7 @@
{ "id": "contourclock",
"name": "Contour Clock",
"shortName" : "Contour Clock",
"version":"0.24",
"version":"0.25",
"icon": "app.png",
"description": "A Minimalist clockface with large Digits. Now with more fonts!",
"screenshots" : [{"url":"cc-screenshot-1.png"},{"url":"cc-screenshot-2.png"}],

View File

@ -7,3 +7,5 @@
0.07: Fix "previous" button image
0.08: Fix scrolling title background color
0.09: Move event listener from widget to boot code, stops music from showing up in messages
0.10: Simplify touch events
Remove date+time

View File

@ -3,9 +3,10 @@
If you have an Android phone with Gadgetbridge, this app allows you to view
and control music playback.
| Bangle.js 1 | Bangle.js 2 |
|:-------------------------------------------|:-------------------------------------------|
| ![Screenshot: Bangle 1](screenshot_v1.png) | ![Screenshot: Bangle 2](screenshot_v2.png) |
| Bangle.js 1 | Bangle.js 2 |
|:---------------------------------------------------------|:---------------------------------------------------------|
| ![Screenshot: Bangle 1 Dark theme](screenshot_v1_d.png) | ![Screenshot: Bangle 2 Darm theme](screenshot_v2_d.png) |
| ![Screenshot: Bangle 1 Light theme](screenshot_v1_l.png) | ![Screenshot: Bangle 2 Light theme](screenshot_v2_l.png) |
Download the [latest Gadgetbridge for Android here](https://f-droid.org/packages/nodomain.freeyourgadget.gadgetbridge/).
@ -14,7 +15,6 @@ Download the [latest Gadgetbridge for Android here](https://f-droid.org/packages
* Dynamic colors based on Track/Artist/Album name
* Scrolling display for long titles
* Automatic start when music plays
* Time and date display
## Settings
@ -40,9 +40,7 @@ Disable double/triple pressing Middle Button: always simply toggle play/pause.
* Button 3 (*Bangle.js 1*): Volume down
### Touch
* Left: Pause/previous song
* Right: Next song/resume
* Center: Toggle play/pause
* Touch: Toggle play/pause
* Swipe left/right: Next/previous song
* Swipe up/down (*Bangle.js 2*): Volume up/down

View File

@ -10,15 +10,15 @@ const BANGLE2 = process.env.HWVERSION===2;
/**
* @param {string} text
* @return {number} Maximum font size to make text fit on screen
* @param {number} w Width to fit text in
* @return {number} Maximum font size to make text fit
*/
function fitText(text) {
function fitText(text, w) {
if (!text.length) {
return Infinity;
}
// make a guess, then shrink/grow until it fits
const w = Bangle.appRect.w,
test = (s) => g.setFont("Vector", s).stringWidth(text);
const test = (s) => g.setFont("Vector", s).stringWidth(text);
let best = Math.floor(100*w/test(100));
if (test(best)===w) { // good guess!
return best;
@ -106,7 +106,7 @@ function rTitle(l) {
rScroller(l); // already scrolling
return;
}
let size = fitText(l.label);
let size = fitText(l.label, l.w);
if (size<l.h/2) {
// the title is too long: start the scroller
scrollStart();
@ -119,7 +119,7 @@ function rTitle(l) {
* @param l
*/
function rInfo(l) {
let size = fitText(l.label);
let size = fitText(l.label, l.w);
if (size>l.h) {
size = l.h;
}
@ -182,23 +182,17 @@ function makeUI() {
type: "v", c: [
{
type: "h", fillx: 1, c: [
{id: "time", type: "txt", label: "88:88", valign: -1, halign: -1, font: "8%", bgCol: g.theme.bg},
{fillx: 1},
{id: "num", type: "txt", label: "88:88", valign: -1, halign: 1, font: "12%", bgCol: g.theme.bg},
BANGLE2 ? {} : {id: "up", type: "txt", label: " +", font: "6x8:2"},
{id: "num", type: "txt", label: "", valign: -1, halign: -1, font: "12%", bgCol: g.theme.bg},
BANGLE2 ? {} : {id: "up", type: "txt", label: " +", halign: 1, font: "6x8:2"},
],
},
{id: "title", type: "custom", label: "", fillx: 1, filly: 2, offset: null, font: "Vector:20%", render: rTitle, bgCol: g.theme.bg},
{id: "artist", type: "custom", label: "", fillx: 1, filly: 1, size: 30, render: rInfo, bgCol: g.theme.bg},
{id: "album", type: "custom", label: "", fillx: 1, filly: 1, size: 20, render: rInfo, bgCol: g.theme.bg},
{height: 10},
{
type: "h", c: [
{width: 3},
{id: "prev", type: "custom", height: 15, width: 15, icon: "previous", render: rIcon, bgCol: g.theme.bg},
{id: "date", type: "txt", halign: 0, valign: 1, label: "", font: "8%", fillx: 1, bgCol: g.theme.bg},
{id: "next", type: "custom", height: 15, width: 15, icon: "next", render: rIcon, bgCol: g.theme.bg},
BANGLE2 ? {width: 3} : {id: "down", type: "txt", label: " -", font: "6x8:2"},
{id: "album", type: "custom", label: "", fillx: 1, filly: 1, size: 20, render: rInfo, bgCol: g.theme.bg},
BANGLE2 ? {} : {id: "down", type: "txt", label: " -", font: "6x8:2"},
],
},
{height: 10},
@ -211,20 +205,6 @@ function makeUI() {
// Self-repeating timeouts
///////////////////////
// Clock
let tock = -1;
function tick() {
if (!BANGLE2 && !Bangle.isLCDOn()) {
return;
}
const now = new Date();
if (now.getHours()*60+now.getMinutes()!==tock) {
drawDateTime();
tock = now.getHours()*60+now.getMinutes();
}
setTimeout(tick, 1000); // we only show minute precision anyway
}
// Fade out while paused and auto closing
let fade = null;
function fadeOut() {
@ -271,40 +251,12 @@ function scrollStop() {
////////////////////
// Drawing functions
////////////////////
/**
* Draw date and time
*/
function drawDateTime() {
const now = new Date();
const l = require("locale");
const is12 = (require("Storage").readJSON("setting.json", 1) || {})["12hour"];
if (is12) {
const d12 = new Date(now.getTime());
const hour = d12.getHours();
if (hour===0) {
d12.setHours(12);
} else if (hour>12) {
d12.setHours(hour-12);
}
layout.time.label = l.time(d12, true)+l.meridian(now);
} else {
layout.time.label = l.time(now, true);
}
layout.date.label = require("locale").date(now, true);
layout.render();
}
function drawControls() {
let l = layout;
if (BANGLE2) return;
const cc = a => (a ? "#f00" : "#0f0"); // control color: red for active, green for inactive
if (!BANGLE2) {
l.up.col = cc("volumeup" in tCommand);
l.down.col = cc("volumedown" in tCommand);
}
l.prev.icon = (stat==="play") ? "pause" : "previous";
l.prev.col = cc("prev" in tCommand || "pause" in tCommand);
l.next.icon = (stat==="play") ? "next" : "play";
l.next.col = cc("next" in tCommand || "play" in tCommand);
layout.up.col = cc("volumeup" in tCommand);
layout.down.col = cc("volumedown" in tCommand);
layout.render();
}
@ -339,6 +291,7 @@ function info(info) {
layout.album.col = infoColor("album");
layout.artist.col = infoColor("artist");
layout.num.label = formatNum(info);
layout.update();
layout.render();
rTitle(layout.title); // force redraw of title, or scroller might break
// reset auto exit interval
@ -473,37 +426,16 @@ function sendCommand(command) {
drawControls();
}
// touch/swipe: navigation
function togglePlay() {
sendCommand(stat==="play" ? "pause" : "play");
}
function pausePrev() {
sendCommand(stat==="play" ? "pause" : "previous");
}
function nextPlay() {
sendCommand(stat==="play" ? "next" : "play");
}
/**
* Setup touch+swipe for Bangle.js 1
*/
function touch1() {
Bangle.on("touch", side => {
if (!Bangle.isLCDOn()) {return;} // for <2v10 firmware
switch(side) {
case 1:
pausePrev();
break;
case 2:
nextPlay();
break;
default:
togglePlay();
break;
}
});
Bangle.on("touch", togglePlay);
Bangle.on("swipe", dir => {
if (!Bangle.isLCDOn()) {return;} // for <2v10 firmware
sendCommand(dir===1 ? "previous" : "next");
});
}
@ -511,16 +443,7 @@ function touch1() {
* Setup touch+swipe for Bangle.js 2
*/
function touch2() {
Bangle.on("touch", (side, xy) => {
const ar = Bangle.appRect;
if (xy.x<ar.x+ar.w/3) {
pausePrev();
} else if (xy.x>ar.x+ar.w*2/3) {
nextPlay();
} else {
togglePlay();
}
});
Bangle.on("touch", togglePlay);
// swiping
let drag;
Bangle.on("drag", e => {
@ -595,7 +518,6 @@ function startWatches() {
function start() {
makeUI();
startWatches();
tick();
startEmulator();
}

View File

@ -2,10 +2,11 @@
"id": "gbmusic",
"name": "Gadgetbridge Music Controls",
"shortName": "Music Controls",
"version": "0.09",
"version": "0.10",
"description": "Control the music on your Gadgetbridge-connected phone",
"icon": "icon.png",
"screenshots": [{"url":"screenshot_v1.png"},{"url":"screenshot_v2.png"}],
"screenshots": [{"url":"screenshot_v1_d.png"},{"url":"screenshot_v1_l.png"},
{"url":"screenshot_v2_d.png"},{"url":"screenshot_v2_l.png"}],
"type": "app",
"tags": "tools,bluetooth,gadgetbridge,music",
"supports": ["BANGLEJS","BANGLEJS2"],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -32,3 +32,5 @@
0.20: Allow tapping on the body to show a scrollable view of the message and title in a bigger font (fix #1405, #1031)
0.21: Improve list readability on dark theme
0.22: Add Home Assistant icon
0.22: Allow repeat to be switched Off, so there is no buzzing repetition.
Also gave the widget a pixel more room to the right

View File

@ -125,7 +125,7 @@ function getMessageImageCol(msg,def) {
"telegram": "#0088cc",
"twitter": "#1da1f2",
"whatsapp": "#4fce5d",
"wordfeud": "#dcc8bd",
"wordfeud": "#e7d3c7",
}[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg);
}

View File

@ -2,7 +2,7 @@
"id": "messages",
"name": "Messages",
"version": "0.22",
"description": "App to display notifications from iOS and Gadgetbridge",
"description": "App to display notifications from iOS and Gadgetbridge/Android",
"icon": "app.png",
"type": "app",
"tags": "tool,system",

View File

@ -4,6 +4,7 @@
if (settings.vibrate===undefined) settings.vibrate=".";
if (settings.repeat===undefined) settings.repeat=4;
if (settings.unreadTimeout===undefined) settings.unreadTimeout=60;
settings.maxUnreadTimeout=240;
return settings;
}
function updateSetting(setting, value) {
@ -13,7 +14,6 @@
}
var vibPatterns = [/*LANG*/"Off", ".", "-", "--", "-.-", "---"];
var currentVib = settings().vibrate;
var mainmenu = {
"" : { "title" : /*LANG*/"Messages" },
"< Back" : back,
@ -27,13 +27,13 @@
},
/*LANG*/'Repeat': {
value: settings().repeat,
min: 2, max: 10,
format: v => v+"s",
min: 0, max: 10,
format: v => v?v+"s":/*LANG*/"Off",
onchange: v => updateSetting("repeat", v)
},
/*LANG*/'Unread timer': {
value: settings().unreadTimeout,
min: 0, max: 240, step : 10,
min: 0, max: settings().maxUnreadTimeout, step : 10,
format: v => v?v+"s":/*LANG*/"Off",
onchange: v => updateSetting("unreadTimeout", v)
},

View File

@ -1,12 +1,12 @@
WIDGETS["messages"]={area:"tl", width:0, iconwidth:23,
WIDGETS["messages"]={area:"tl", width:0, iconwidth:24,
draw:function() {
Bangle.removeListener('touch', this.touch);
if (!this.width) return;
var c = (Date.now()-this.t)/1000;
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth);
g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y);
//if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
console.log("dingen ", typeof(settings.repeat), settings.repeat)
if (settings.repeat===undefined) settings.repeat = 4;
if (c<120 && (Date.now()-this.l)>settings.repeat*1000) {
this.l = Date.now();

View File

@ -1,2 +1,4 @@
0.01: Initial release
0.02: Optional fullscreen mode
0.02: Optional fullscreen mode
0.03: Optional show lock status via color
0.04: Ensure that widgets are always hidden in fullscreen mode

View File

@ -21,4 +21,7 @@ Shows the current date as DD MM on touch and reverts back to time after 5 second
### Fullscreen
Shows the watchface in fullscreen mode.
Note: In fullscreen mode, widgets are hidden, but still loaded.
Note: In fullscreen mode, widgets are hidden, but still loaded.
### Show lock status
If enabled, color changes when unlocked to detect the lock state easily.

View File

@ -2,7 +2,7 @@
"id": "neonx",
"name": "Neon X & IO X Clock",
"shortName": "Neon X Clock",
"version": "0.02",
"version": "0.04",
"description": "Pebble Neon X & Neon IO X for Bangle.js",
"icon": "neonx.png",
"type": "clock",

View File

@ -8,6 +8,19 @@
* Created: February 2022
*/
let settings = {
thickness: 4,
io: 0,
showDate: 1,
fullscreen: false,
showLock: false,
};
let saved_settings = require('Storage').readJSON('neonx.json', 1) || settings;
for (const key in saved_settings) {
settings[key] = saved_settings[key]
}
const digits = {
0:[[15,15,85,15,85,85,15,85,15,15]],
1:[[85,15,85,85]],
@ -21,6 +34,7 @@ const digits = {
9:[[15,50,15,15,85,15,85,85,15,85]],
};
const colors = {
x: [
["#FF00FF", "#00FFFF"],
@ -31,17 +45,14 @@ const colors = {
["#00FF00", "#00FFFF"]
]
};
const is12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false;
const screenWidth = g.getWidth();
const screenHeight = g.getHeight();
const halfWidth = screenWidth / 2;
const scale = screenWidth / 240;
const REFRESH_RATE = 10E3;
let interval = 0;
let showingDate = false;
function drawLine(poly, thickness){
for (let i = 0; i < poly.length; i = i + 2){
if (poly[i + 2] === undefined) {
@ -59,31 +70,27 @@ function drawLine(poly, thickness){
}
}
let settings = {
thickness: 4,
io: 0,
showDate: 1,
fullscreen: false,
};
let saved_settings = require('Storage').readJSON('neonx.json', 1) || settings;
for (const key in saved_settings) {
settings[key] = saved_settings[key]
}
function drawClock(num){
let tx, ty;
if(settings.fullscreen){
g.clearRect(0,0,screenWidth,screenHeight);
} else {
g.clearRect(0,24,240,240);
}
for (let x = 0; x <= 1; x++) {
for (let y = 0; y <= 1; y++) {
const current = ((y + 1) * 2 + x - 1);
let newScale = scale;
g.setColor(colors[settings.io ? 'io' : 'x'][y][x]);
let xc = settings.showLock && !Bangle.isLocked() ? Math.abs(x-1) : x;
let c = colors[settings.io ? 'io' : 'x'][y][xc];
g.setColor(c);
if (!settings.io) {
newScale *= settings.fullscreen ? 1.18 : 1.0;
newScale *= settings.fullscreen ? 1.20 : 1.0;
let dx = settings.fullscreen ? 0 : 18
tx = (x * 100 + dx) * newScale;
ty = (y * 100 + dx*2) * newScale;
@ -101,68 +108,81 @@ function drawClock(num){
}
}
function draw(date){
queueDraw();
// Depending on the settings, we clear all widgets or draw those.
if(settings.fullscreen){
for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";}
} else {
Bangle.drawWidgets();
}
// Now lets draw the time/date
let d = new Date();
let l1, l2;
showingDate = date;
if (date) {
setUpdateInt(0);
l1 = ('0' + (new Date()).getDate()).substr(-2);
l2 = ('0' + ((new Date()).getMonth() + 1)).substr(-2);
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
setTimeout(_ => {
draw();
setUpdateInt(1);
}, 5000);
} else {
l1 = ('0' + (d.getHours() % (is12hour ? 12 : 24))).substr(-2);
l2 = ('0' + d.getMinutes()).substr(-2);
}
if(settings.fullscreen){
g.clearRect(0,0,screenWidth,screenHeight);
} else {
g.clearRect(0,24,240,240);
}
drawClock([l1, l2]);
}
function setUpdateInt(set){
if (interval) {
clearInterval(interval);
}
if (set) {
interval = setInterval(draw, REFRESH_RATE);
}
/*
* Draw watch face
*/
var drawTimeout;
function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
}
g.clear(1);
Bangle.setUI("clock");
setUpdateInt(1);
draw();
/*
* Event handlers
*/
if (settings.showDate) {
Bangle.on('touch', () => draw(!showingDate));
}
Bangle.on('lcdPower', function(on){
if (on){
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
if (on) {
draw();
setUpdateInt(1);
} else setUpdateInt(0);
}
});
Bangle.on('lock', function(isLocked) {
draw();
});
/*
* Draw first time
*/
g.clear(1);
Bangle.setUI("clock");
Bangle.loadWidgets();
if(settings.fullscreen){
for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";}
} else {
Bangle.drawWidgets();
}
draw();

View File

@ -9,6 +9,7 @@
io: 0,
showDate: 1,
fullscreen: false,
showLock: false,
};
updateSettings();
@ -58,6 +59,14 @@
updateSettings();
},
},
'Show lock': {
value: false | neonXSettings.showLock,
format: () => (neonXSettings.showLock ? 'Yes' : 'No'),
onchange: () => {
neonXSettings.showLock = !neonXSettings.showLock;
updateSettings();
},
},
};
E.showMenu(menu);
})

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

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwhC/AH4A/ABl3ABQVJg4WLC/QWMC/4X/U7NVqIXTgtVC4MXC6QWBAAQYLCxQAGqByJIoQAKC8IWMJBIuNGBIXvCxxgIC/4XH1QAO0AX/C/4X/C/4X/C6Q"))

56
apps/pie/app.js Normal file
View File

@ -0,0 +1,56 @@
function end(){
clearInterval(m);
clearWatch(w);
gfx.clear();
gfx.setColor(1,0,0);
gfx.setFont("Vector30");
gfx.drawString('Game over!\n Score: '+score+'\nPress BTN1', gfx.getWidth()*0.15,gfx.getHeight()*0.4);
setWatch(function(){init();}, BTN1);
}
function scrollX(){
gfx.clearRect(0,gfx.getHeight()*(1/4),gfx.getWidth(),0);
gfx.scroll(0,gfx.getHeight()/4);
score++;
if(typeof(m) != undefined && score>0){
clearInterval(m);
m = setInterval(scrollY,Math.abs(100/score+15-0.1*score));}
gfx.setColor(1,1,1);
gfx.drawString(score,gfx.getWidth()*(4.2/5),gfx.getHeight()*(0.5/5));
gfx.setColor(Math.random(),Math.random(),Math.random());
gfx.setColor(col[0],col[1],col[2]);
gfx.fillRect(colm[0],colm[1],colm[2],colm[3]);
col = [Math.random(),Math.random(),Math.random()];
gfx.setColor(col[0],col[1],col[2]);
block[0] = gfx.getWidth();
}
function scrollY(){
block[0] -= 2;
block[2] = block[0]+colm[2]-colm[0];
gfx.clearRect(block[2], block[1], gfx.getWidth(), block[3]);
gfx.fillRect(block[0],block[1],block[2],block[3]);
if(block[2]<colm[0])end();
}
function coldet(){
if(block[0]<colm[2]){
gfx.clearRect(block[0],block[1],block[2],block[3]);
if(colm[2]>block[2] && colm[0]<block[2])colm[2]=block[2];
if(colm[0]<block[0] && block[0]<colm[2])colm[0]=block[0];
scrollX();
}else{end();}
}
function init(){
gfx = Graphics.getInstance();
col = [Math.random(),Math.random(),Math.random()];
gfx.clear();
colm = [gfx.getWidth()*(1/5),gfx.getHeight()*(3/4),gfx.getWidth()*(4/5),gfx.getHeight()/2];
block = [gfx.getWidth(),gfx.getHeight()/4,gfx.getWidth(),gfx.getHeight()/2];
score = -3;
gfx.setFont("Vector15");
gfx.fillPoly(colm);
scrollX();
scrollX();
scrollX();
w = setWatch(coldet, BTN1, {repeat:true});
m = setInterval(scrollY,110);
}
init();

BIN
apps/pie/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

14
apps/pie/metadata.json Normal file
View File

@ -0,0 +1,14 @@
{ "id": "pie",
"name": "In this game you need to make highest pie",
"shortName":"Pie maker",
"version":"0.01",
"description": "In this game you will be making pie out of different pieces",
"icon": "app.png",
"type": "app",
"tags": "game",
"supports" : ["BANGLEJS"],
"storage": [
{"name":"pie.app.js","url":"app.js"},
{"name":"pie.img","url":"app-icon.js","evaluate":true}
]
}

View File

@ -5,3 +5,4 @@
0.04: Use the exstats module, and make what is displayed configurable
0.05: exstats updated so update 'distance' label is updated, option for 'speed'
0.06: Add option to record a run using the recorder app automatically
0.07: Fix crash if an odd number of active boxes are configured (fix #1473)

View File

@ -62,14 +62,14 @@ for (var i=0;i<statIDs.length;i+=2) {
var sa = exs.stats[statIDs[i+0]];
var sb = exs.stats[statIDs[i+1]];
lc.push({ type:"h", filly:1, c:[
{type:"txt", font:fontHeading, label:sa.title.toUpperCase(), fillx:1, col:headingCol },
{type:"txt", font:fontHeading, label:sb.title.toUpperCase(), fillx:1, col:headingCol }
sa?{type:"txt", font:fontHeading, label:sa.title.toUpperCase(), fillx:1, col:headingCol }:{},
sb?{type:"txt", font:fontHeading, label:sb.title.toUpperCase(), fillx:1, col:headingCol }:{}
]}, { type:"h", filly:1, c:[
{type:"txt", font:fontValue, label:sa.getString(), id:sa.id, fillx:1 },
{type:"txt", font:fontValue, label:sb.getString(), id:sb.id, fillx:1 }
sa?{type:"txt", font:fontValue, label:sa.getString(), id:sa.id, fillx:1 }:{},
sb?{type:"txt", font:fontValue, label:sb.getString(), id:sb.id, fillx:1 }:{}
]});
sa.on('changed', e=>layout[e.id].label = e.getString());
sb.on('changed', e=>layout[e.id].label = e.getString());
if (sa) sa.on('changed', e=>layout[e.id].label = e.getString());
if (sb) sb.on('changed', e=>layout[e.id].label = e.getString());
}
// At the bottom put time/GPS state/etc
lc.push({ type:"h", filly:1, c:[

View File

@ -1,6 +1,6 @@
{ "id": "run",
"name": "Run",
"version":"0.06",
"version":"0.07",
"description": "Displays distance, time, steps, cadence, pace and more for runners.",
"icon": "app.png",
"tags": "run,running,fitness,outdoors,gps",

View File

@ -1 +1,2 @@
0.01: first release
0.02: Adjust for touch events outside of screen g dimensions

View File

@ -1,7 +1,7 @@
{
"id": "stopwatch",
"name": "Stopwatch Touch",
"version": "0.01",
"version": "0.02",
"description": "A touch based stop watch for Bangle JS 2",
"icon": "stopwatch.png",
"screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}],

View File

@ -185,17 +185,27 @@ resetBtn.setImage(pause_img);
Bangle.on('touch', function(button, xy) {
var x = xy.x;
var y = xy.y;
// adjust for outside the dimension of the screen
// http://forum.espruino.com/conversations/371867/#comment16406025
if (y > h) y = h;
if (y < 0) y = 0;
if (x > w) x = w;
if (x < 0) x = 0;
// not running, and reset
if (!running && tCurrent == tTotal && bigPlayPauseBtn.check(xy.x, xy.y)) return;
if (!running && tCurrent == tTotal && bigPlayPauseBtn.check(x, y)) return;
// paused and hit play
if (!running && tCurrent != tTotal && smallPlayPauseBtn.check(xy.x, xy.y)) return;
if (!running && tCurrent != tTotal && smallPlayPauseBtn.check(x, y)) return;
// paused and press reset
if (!running && tCurrent != tTotal && resetBtn.check(xy.x, xy.y)) return;
if (!running && tCurrent != tTotal && resetBtn.check(x, y)) return;
// must be running
if (running && bigPlayPauseBtn.check(xy.x, xy.y)) return;
if (running && bigPlayPauseBtn.check(x, y)) return;
});
// Stop updates when LCD is off, restart when on

View File

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

View File

@ -0,0 +1,9 @@
# Terminal clock
A clock displayed as a terminal cli.
It can display :
- time
- date
- hrm
- activity
- steps

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwghC/AHsHu93uAX/C+wACsAaTC/4Xiu1mswXRCYNnDQQxTgwX/C8QABuAaTg4X/C7Z3Xa/4Xds1ms4XUCgV2DYIXUsBdTC/4AEg4VCC61wIiYX/C74A/AGIA=="))

138
apps/terminalclock/app.js Normal file
View File

@ -0,0 +1,138 @@
var locale = require("locale");
var fontColor = g.theme.dark ? "#0f0" : "#000";
var startY = 24;
var paddingY = 2;
var font6x8At4Size = 32;
var font6x8At2Size = 18;
var heartRate = 0;
function setFontSize(pos){
if(pos == 1)
g.setFont("6x8", 4);
else
g.setFont("6x8", 2);
}
function clearField(pos){
var yStartPos = startY +
paddingY * (pos - 1) +
font6x8At4Size * Math.min(1, pos-1) +
font6x8At2Size * Math.max(0, pos-2);
var yEndPos = startY +
paddingY * (pos - 1) +
font6x8At4Size * Math.min(1, pos) +
font6x8At2Size * Math.max(0, pos-1);
g.clearRect(0, yStartPos, 240, yEndPos);
}
function clearWatchIfNeeded(now){
if(now.getMinutes() % 10 == 0)
g.clearRect(0, startY, 240, 240);
}
function drawLine(line, pos){
setFontSize(pos);
var yPos = startY +
paddingY * (pos - 1) +
font6x8At4Size * Math.min(1, pos-1) +
font6x8At2Size * Math.max(0, pos-2);
g.drawString(line, 5, yPos, true);
}
function drawTime(now, pos){
var h = now.getHours();
var m = now.getMinutes();
var time = ">" + (""+h).substr(-2) + ":" + ("0"+m).substr(-2);
drawLine(time, pos);
}
function drawDate(now, pos){
var dow = locale.dow(now, 1);
var date = locale.date(now, 1).substr(0,6) + locale.date(now, 1).substr(-2);
var locale_date = ">" + dow + " " + date;
drawLine(locale_date, pos);
}
function drawInput(now, pos){
clearField(pos);
drawLine(">", pos);
}
function drawStepCount(pos){
var health = Bangle.getHealthStatus("day");
var steps_formated = ">Steps: " + health.steps;
drawLine(steps_formated, pos);
}
function drawHRM(pos){
clearField(pos);
if(heartRate != 0)
drawLine(">HR: " + parseInt(heartRate), pos);
else
drawLine(">HR: unknown", pos);
}
function drawActivity(pos){
clearField(pos);
var health = Bangle.getHealthStatus('last');
var steps_formated = ">Activity: " + parseInt(health.movement/10);
drawLine(steps_formated, pos);
}
function draw(){
var curPos = 1;
g.reset();
g.setFontAlign(-1, -1);
g.setColor(fontColor);
var now = new Date();
clearWatchIfNeeded(now); // mostly to not have issues when changing days
drawTime(now, curPos);
curPos++;
if(settings.showDate){
drawDate(now, curPos);
curPos++;
}
if(settings.showHRM){
drawHRM(curPos);
curPos++;
}
if(settings.showActivity){
drawActivity(curPos);
curPos++;
}
if(settings.showStepCount){
drawStepCount(curPos);
curPos++;
}
drawInput(now, curPos);
}
Bangle.on('HRM',function(hrmInfo) {
if(hrmInfo.confidence >= settings.HRMinConfidence)
heartRate = hrmInfo.bpm;
});
// Clear the screen once, at startup
g.clear();
// load the settings
var settings = Object.assign({
// default values
HRMinConfidence: 50,
showDate: true,
showHRM: true,
showActivity: true,
showStepCount: true,
}, require('Storage').readJSON("terminalclock.json", true) || {});
// draw immediately at first
draw();
// Show launcher when middle button pressed
Bangle.setUI("clock");
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
var secondInterval = setInterval(draw, 10000);

BIN
apps/terminalclock/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

View File

@ -0,0 +1,24 @@
{
"id": "terminalclock",
"name": "Terminal Clock",
"shortName":"Terminal Clock",
"description": "A terminal cli like clock displaying multiple sensor data",
"version":"0.01",
"icon": "app.png",
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name": "terminalclock.app.js","url": "app.js"},
{"name": "terminalclock.settings.js","url": "settings.js"},
{"name": "terminalclock.img","url": "app-icon.js","evaluate": true}
],
"data": [
{"name": "terminalclock.json"}
],
"screenshots": [
{"url": "screenshot1.png"},
{"url": "screenshot2.png"}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,61 @@
(function(back) {
var FILE = "terminalclock.json";
// Load settings
var settings = Object.assign({
HRMinConfidence: 50,
showDate: true,
showHRM: true,
showActivity: true,
showStepCount: true,
}, require('Storage').readJSON(FILE, true) || {});
function writeSettings() {
require('Storage').writeJSON(FILE, settings);
}
// Show the menu
E.showMenu({
"" : { "title" : "Terminal Clock" },
"< Back" : () => back(),
'HR confidence': {
value: 50|settings.HRMinConfidence, // 0| converts undefined to 0
min: 0, max: 100,
onchange: v => {
settings.HRMinConfidence = v;
writeSettings();
}
},
'Show date': {
value: !!settings.showDate,
format: v => v?"Yes":"No",
onchange: v => {
settings.showDate = v;
writeSettings();
}
},
'Show HRM': {
value: !!settings.showHRM,
format: v => v?"Yes":"No",
onchange: v => {
settings.showHRM = v;
writeSettings();
}
},
'Show Activity': {
value: !!settings.showActivity,
format: v => v?"Yes":"No",
onchange: v => {
settings.showActivity = v;
writeSettings();
}
},
'Show Steps': {
value: !!settings.showStepCount,
format: v => v?"Yes":"No",
onchange: v => {
settings.showStepCount = v;
writeSettings();
}
}
});
})

View File

@ -6,4 +6,5 @@
-> locale: weekday name (first two characters) from locale
-> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default])
0.03: a lot of more settings for outline, colors and highlights
0.04: finalized README, fixed settings cancel, fixed border-setting
0.04: finalized README, fixed settings cancel, fixed border-setting
0.05: bugfix: default settings

View File

@ -1,7 +1,7 @@
{ "id": "timecal",
"name": "TimeCal",
"shortName":"TimeCal",
"version":"0.04",
"version":"0.05",
"description": "TimeCal shows the date/time along with a 3 week calendar",
"icon": "icon.png",
"type": "clock",

View File

@ -2,7 +2,7 @@
(function(exit) {
ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var FILE = "timecal.validSttngs.json";
var FILE = "timecal.settings.json";
const DEFAULTS = {
shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week
@ -19,14 +19,14 @@
calBrdr:false
};
validSttngs = require("Storage").readJSON("timecal.validSttngs.json", 1) || {};
validSttngs = require("Storage").readJSON(FILE, 1) || {};
for (const k in validSttngs) if (!DEFAULTS.hasOwnProperty(k)) delete this.validSttngs[k]; //remove invalid settings
for (const k in DEFAULTS) if(!validSttngs.hasOwnProperty(k)) validSttngs[k] = DEFAULTS[k]; //assign missing defaults
for (const k in DEFAULTS) if(!validSttngs.hasOwnProperty(k)) validSttngs[k] = DEFAULTS[k]; //assign missing defaults fixed
var changedSttngs = Object.assign({}, validSttngs);
var chngdSttngs = Object.assign({}, validSttngs);
var saveExitSettings = () => {
require('Storage').writeJSON(FILE, changedSttngs);
require('Storage').writeJSON(FILE, chngdSttngs);
exit();
};
@ -42,27 +42,27 @@
},
/*LANG*/"< Save": () => saveExitSettings(),
/*LANG*/"Show date": {
value: validSttngs.shwDate,
value: chngdSttngs.shwDate,
min: 0, max: 3,
format: v => [/*LANG*/"none", /*LANG*/"locale", /*LANG*/"M", /*LANG*/"m.Y #W"][v],
onchange: v => validSttngs.shwDate = v
onchange: v => chngdSttngs.shwDate = v
},
/*LANG*/"Start wday": {
value: validSttngs.wdStrt,
value: chngdSttngs.wdStrt,
min: -1, max: 6,
format: v => v>=0 ? ABR_DAY[v] : /*LANG*/"today",
onchange: v => validSttngs.wdStrt = v
onchange: v => chngdSttngs.wdStrt = v
},
/*LANG*/"Su color": {
value: validSttngs.suClr,
value: chngdSttngs.suClr,
min: 0, max: 3,
format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v],
onchange: v => validSttngs.suClr = v
onchange: v => chngdSttngs.suClr = v
},
/*LANG*/"Border": {
value: validSttngs.calBrdr,
value: chngdSttngs.calBrdr,
format: v => v ? /*LANG*/"show" : /*LANG*/"none",
onchange: v => validSttngs.calBrdr = v
onchange: v => chngdSttngs.calBrdr = v
},
/*LANG*/"Today settings": () => {
showTodayMenu();
@ -78,28 +78,28 @@
},
"< Back": () => showMainMenu(),
/*LANG*/"Color": {
value: validSttngs.tdyNumClr,
value: chngdSttngs.tdyNumClr,
min: 0, max: 3,
format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v],
onchange: v => validSttngs.tdyNumClr = v
onchange: v => chngdSttngs.tdyNumClr = v
},
/*LANG*/"Marker": {
value: validSttngs.tdyMrkr,
value: chngdSttngs.tdyMrkr,
min: 0, max: 3,
format: v => [/*LANG*/"none", /*LANG*/"circle", /*LANG*/"rectangle", /*LANG*/"filled"][v],
onchange: v => validSttngs.tdyMrkr = v
onchange: v => chngdSttngs.tdyMrkr = v
},
/*LANG*/"Mrk.Color": {
value: validSttngs.tdyMrkClr,
value: chngdSttngs.tdyMrkClr,
min: 0, max: 2,
format: v => [/*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v],
onchange: v => validSttngs.tdyMrkClr = v
onchange: v => chngdSttngs.tdyMrkClr = v
},
/*LANG*/"Mrk.Size": {
value: validSttngs.tdyMrkPxl,
value: chngdSttngs.tdyMrkPxl,
min: 1, max: 10,
format: v => v+"px",
onchange: v => validSttngs.tdyMrkPxl = v
onchange: v => chngdSttngs.tdyMrkPxl = v
},
/*LANG*/"< Cancel": () => cancelExitSettings()
});

View File

@ -232,7 +232,7 @@ Layout.prototype.render = function (l) {
function render(l) {"ram"
g.reset();
if (l.col) g.setColor(l.col);
if (l.col!==undefined) g.setColor(l.col);
if (l.bgCol!==undefined) g.setBgColor(l.bgCol).clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1);
cb[l.type](l);
}
@ -264,7 +264,7 @@ Layout.prototype.render = function (l) {
x,y+4
], bg = l.selected?g.theme.bgH:g.theme.bg2;
g.setColor(bg).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawPoly(poly);
if (l.col) g.setColor(l.col);
if (l.col!==undefined) g.setColor(l.col);
if (l.src) g.setBgColor(bg).drawImage("function"==typeof l.src?l.src():l.src, l.x + 10 + (0|l.pad), l.y + 8 + (0|l.pad));
else g.setFont("6x8",2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2);
}, "img":function(l){

View File

@ -207,7 +207,6 @@ exports.getStats = function(statIDs, options) {
};
}
if (statIDs.includes("caden")) {
needGPS = true;
stats["caden"]={
title : "Cadence",
getValue : function() { return state.stepsPerMin; },