Merge branch 'master' into master
|
@ -45,7 +45,7 @@ var AppInfo = {
|
||||||
storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${js});`;
|
storageFile.cmd = `\x10require('Storage').write(${toJS(storageFile.name)},${js});`;
|
||||||
});
|
});
|
||||||
resolve(fileContents);
|
resolve(fileContents);
|
||||||
});
|
}).catch(err => reject(err));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
94
apps.json
|
@ -82,6 +82,28 @@
|
||||||
{"name":"*astroid","url":"asteroids-icon.js","evaluate":true}
|
{"name":"*astroid","url":"asteroids-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "clickms",
|
||||||
|
"name": "Click Master",
|
||||||
|
"icon": "click-master.png",
|
||||||
|
"description": "Get several friends to start the game, then compete to see who can press BTN1 the most!",
|
||||||
|
"tags": "game",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+clickms","url":"click-master.json"},
|
||||||
|
{"name":"-clickms","url":"click-master.js"},
|
||||||
|
{"name":"*clickms","url":"click-master-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "id": "horsey",
|
||||||
|
"name": "Horse Race!",
|
||||||
|
"icon": "horse-race.png",
|
||||||
|
"description": "Get several friends to start the game, then compete to see who can press BTN1 the most!",
|
||||||
|
"tags": "game",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+horsey","url":"horse-race.json"},
|
||||||
|
{"name":"-horsey","url":"horse-race.js"},
|
||||||
|
{"name":"*horsey","url":"horse-race-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "compass",
|
{ "id": "compass",
|
||||||
"name": "Compass",
|
"name": "Compass",
|
||||||
"icon": "compass.png",
|
"icon": "compass.png",
|
||||||
|
@ -213,6 +235,17 @@
|
||||||
{"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true}
|
{"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "hidbkbd",
|
||||||
|
"name": "Binary Bluetooth Keyboard",
|
||||||
|
"icon": "hid-binary-keyboard.png",
|
||||||
|
"description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want",
|
||||||
|
"tags": "bluetooth",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+hidbkbd","url":"hid-binary-keyboard.json"},
|
||||||
|
{"name":"-hidbkbd","url":"hid-binary-keyboard.js"},
|
||||||
|
{"name":"*hidbkbd","url":"hid-binary-keyboard-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "animals",
|
{ "id": "animals",
|
||||||
"name": "Animals Game",
|
"name": "Animals Game",
|
||||||
"icon": "animals.png",
|
"icon": "animals.png",
|
||||||
|
@ -350,6 +383,30 @@
|
||||||
{"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true}
|
{"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "hrings",
|
||||||
|
"name": "Hypno Rings",
|
||||||
|
"icon": "hypno-rings.png",
|
||||||
|
"description": "Experiment with trippy rings, press buttons for change",
|
||||||
|
"tags": "rings,hypnosis,psychadelic",
|
||||||
|
"type":"app",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+hrings","url":"hypno-rings.json"},
|
||||||
|
{"name":"-hrings","url":"hypno-rings.js"},
|
||||||
|
{"name":"*hrings","url":"hypno-rings-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "id": "morse",
|
||||||
|
"name": "Morse Code",
|
||||||
|
"icon": "morse-code.png",
|
||||||
|
"description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!",
|
||||||
|
"tags": "morse,sound,visual,input",
|
||||||
|
"type":"app",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+morse","url":"morse-code.json"},
|
||||||
|
{"name":"-morse","url":"morse-code.js"},
|
||||||
|
{"name":"*morse","url":"morse-code-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "blescan",
|
"id": "blescan",
|
||||||
"name": "BLE Scanner",
|
"name": "BLE Scanner",
|
||||||
|
@ -408,5 +465,42 @@
|
||||||
{"name":"-miclock","url":"clock-mixed.js"},
|
{"name":"-miclock","url":"clock-mixed.js"},
|
||||||
{"name":"*miclock","url":"clock-mixed-icon.js","evaluate":true}
|
{"name":"*miclock","url":"clock-mixed-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{ "id": "bclock",
|
||||||
|
"name": "Binary Clock",
|
||||||
|
"icon": "clock-binary.png",
|
||||||
|
"description": "A simple binary clock watch face",
|
||||||
|
"tags": "clock",
|
||||||
|
"type":"clock",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+bclock","url":"clock-binary.json"},
|
||||||
|
{"name":"-bclock","url":"clock-binary.js"},
|
||||||
|
{"name":"*bclock","url":"clock-binary-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "id": "clotris",
|
||||||
|
"name": "Clock-Tris",
|
||||||
|
"icon": "clock-tris.png",
|
||||||
|
"description": "A fully functional clone of a classic game of falling blocks",
|
||||||
|
"tags": "",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+clotris","url":"clock-tris.json"},
|
||||||
|
{"name":"-clotris","url":"clock-tris.js"},
|
||||||
|
{"name":"*clotris","url":"clock-tris-icon.js","evaluate":true},
|
||||||
|
{"name":".trishig","url":"clock-tris-high"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpsinfo",
|
||||||
|
"name": "GPS Info",
|
||||||
|
"icon": "gps-info.png",
|
||||||
|
"description": "An application that displays information about altitude, lat/lon, satellites and time",
|
||||||
|
"tags": "gps",
|
||||||
|
"type": "app",
|
||||||
|
"storage": [
|
||||||
|
{"name": "+gpsinfo","url": "gps-info.json"},
|
||||||
|
{"name": "-gpsinfo","url": "gps-info.js"},
|
||||||
|
{"name": "*gpsinfo","url": "gps-info-icon.js","evaluate": true}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -73,7 +73,7 @@ if (startapp) {
|
||||||
setWatch(function() { // run
|
setWatch(function() { // run
|
||||||
if (!apps[selected].src) return;
|
if (!apps[selected].src) return;
|
||||||
clearWatch();
|
clearWatch();
|
||||||
g.clear();
|
g.clear(1);
|
||||||
g.setFont("6x8",2);
|
g.setFont("6x8",2);
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.drawString("Loading...",120,120);
|
g.drawString("Loading...",120,120);
|
||||||
|
@ -84,6 +84,10 @@ if (startapp) {
|
||||||
// re-add the menu button if we're going to the clock
|
// re-add the menu button if we're going to the clock
|
||||||
if (apps[selected].type=="clock") {
|
if (apps[selected].type=="clock") {
|
||||||
setWatch(displayMenu, BTN2, {repeat:false,edge:"falling"});
|
setWatch(displayMenu, BTN2, {repeat:false,edge:"falling"});
|
||||||
|
WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};
|
||||||
|
WIDGETS={};
|
||||||
|
require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget)));
|
||||||
|
setTimeout(drawWidgets,100);
|
||||||
} else {
|
} else {
|
||||||
delete WIDGETS;
|
delete WIDGETS;
|
||||||
delete WIDGETPOS;
|
delete WIDGETPOS;
|
||||||
|
@ -95,15 +99,15 @@ if (startapp) {
|
||||||
var WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};
|
var WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};
|
||||||
var WIDGETS={};
|
var WIDGETS={};
|
||||||
function drawWidgets() {
|
function drawWidgets() {
|
||||||
Object.keys(WIDGETS).forEach(k=>WIDGETS[k].draw());
|
for (var w of WIDGETS) w.draw();
|
||||||
}
|
}
|
||||||
var clockApp = require("Storage").list().filter(a=>a[0]=='+').map(app=>{
|
var clockApps = require("Storage").list().filter(a=>a[0]=='+').map(app=>{
|
||||||
try { return require("Storage").readJSON(app); }
|
try { return require("Storage").readJSON(app); }
|
||||||
catch (e) {}
|
catch (e) {}
|
||||||
}).find(app=>app.type=="clock");
|
}).filter(app=>app.type=="clock").sort((a, b) => a.sortorder - b.sortorder);
|
||||||
if (clockApp) eval(require("Storage").read(clockApp.src));
|
if (clockApps && clockApps.length > 0) eval(require("Storage").read(clockApps[0].src));
|
||||||
else E.showMessage("No Clock Found");
|
else E.showMessage("No Clock Found");
|
||||||
delete clockApp;
|
delete clockApps;
|
||||||
require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget)));
|
require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget)));
|
||||||
setTimeout(drawWidgets,100);
|
setTimeout(drawWidgets,100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AHmIAAIWThAXCwAuVGCYuCkQwTCYOE7tIGCQSBkf/mgXUof/nsoF6kzJAQXSlvd7vSC4/d6B3L7vUC40NBQKnJwQMB7sgFwwXJGAVNBoI+ECoQJGGApgCBoZECC5YwBMAQ+C6AXFJBJWFCgoXQ6AXIJBJZGC7xIOC8Jg/C9ZIMC8RIMFhIXMU5HTnoLBJBQXIn/zRykNC5ruJn5HBRqnT9q8hXZalKCxoyICx4yFRJIA/AH4AQA=="))
|
|
@ -0,0 +1,50 @@
|
||||||
|
var ME = "-= ME =-";
|
||||||
|
var mycounter = 0;
|
||||||
|
var players = {};
|
||||||
|
setWatch(x=>{
|
||||||
|
mycounter++;
|
||||||
|
updateAdvertising();
|
||||||
|
},BTN1,{repeat:true});
|
||||||
|
|
||||||
|
function updateAdvertising() {
|
||||||
|
try {
|
||||||
|
NRF.setAdvertising({},{
|
||||||
|
manufacturer: 0x0590,
|
||||||
|
manufacturerData: new Uint8Array([mycounter>>8,mycounter&255])
|
||||||
|
});
|
||||||
|
} catch(e){}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPlayers() {
|
||||||
|
g.clear(1);
|
||||||
|
g.setFont("6x8",2);
|
||||||
|
var l = [{name:ME,cnt:mycounter}];
|
||||||
|
for (p of players) l.push(p);
|
||||||
|
l.sort((a,b)=>a.cnt-b.cnt);
|
||||||
|
var y=0;
|
||||||
|
l.forEach(player=>{
|
||||||
|
if (player.name==ME) g.setColor(1,0,0);
|
||||||
|
else g.setColor(1,1,1);
|
||||||
|
g.drawString(player.name,10,y);
|
||||||
|
g.drawString(player.cnt,180,y);
|
||||||
|
y+=16;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function doScan() {
|
||||||
|
NRF.findDevices(devs=>{
|
||||||
|
devs.forEach(dev => {
|
||||||
|
players[dev.id] = {
|
||||||
|
name : dev.id.substr(12,5),
|
||||||
|
cnt : (dev.manufacturerData[0]<<8)|dev.manufacturerData[1]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
drawPlayers();
|
||||||
|
doScan();
|
||||||
|
},{timeout : 1000, filters : [{ manufacturerData:{0x0590:{}} }] });
|
||||||
|
}
|
||||||
|
|
||||||
|
drawPlayers();
|
||||||
|
try { NRF.wake(); } catch (e) {}
|
||||||
|
doScan();
|
||||||
|
updateAdvertising();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name":"Click Master",
|
||||||
|
"icon": "*clickms",
|
||||||
|
"src":"-clickms"
|
||||||
|
}
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -1,18 +1,23 @@
|
||||||
g.clear();
|
(function(){
|
||||||
|
g.clear();
|
||||||
|
const p = Math.PI/2;
|
||||||
|
const PRad = Math.PI/180;
|
||||||
|
|
||||||
var minuteDate = new Date();
|
let intervalRefMin = null;
|
||||||
var secondDate = new Date();
|
let intervalRefSec = null;
|
||||||
|
|
||||||
function seconds(angle, r) {
|
let minuteDate = new Date();
|
||||||
var a = angle*Math.PI/180;
|
let secondDate = new Date();
|
||||||
var x = 120+Math.sin(a)*r;
|
|
||||||
var y = 120-Math.cos(a)*r;
|
function seconds(angle, r) {
|
||||||
|
const a = angle*PRad;
|
||||||
|
const x = 120+Math.sin(a)*r;
|
||||||
|
const y = 120-Math.cos(a)*r;
|
||||||
g.fillRect(x-1,y-1,x+1,y+1);
|
g.fillRect(x-1,y-1,x+1,y+1);
|
||||||
}
|
}
|
||||||
function hand(angle, r1,r2) {
|
function hand(angle, r1,r2) {
|
||||||
var a = angle*Math.PI/180;
|
const a = angle*PRad;
|
||||||
var r3 = 3;
|
const r3 = 3;
|
||||||
var p = Math.PI/2;
|
|
||||||
g.fillPoly([
|
g.fillPoly([
|
||||||
120+Math.sin(a)*r1,
|
120+Math.sin(a)*r1,
|
||||||
120-Math.cos(a)*r1,
|
120-Math.cos(a)*r1,
|
||||||
|
@ -22,19 +27,19 @@ function hand(angle, r1,r2) {
|
||||||
120-Math.cos(a)*r2,
|
120-Math.cos(a)*r2,
|
||||||
120+Math.sin(a-p)*r3,
|
120+Math.sin(a-p)*r3,
|
||||||
120-Math.cos(a-p)*r3]);
|
120-Math.cos(a-p)*r3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawAll() {
|
function drawAll() {
|
||||||
g.clear();
|
g.clear();
|
||||||
g.setColor(0,0,0.6);
|
g.setColor(0,0,0.6);
|
||||||
for (var i=0;i<60;i++)
|
for (let i=0;i<60;i++)
|
||||||
seconds(360*i/60, 90);
|
seconds(360*i/60, 90);
|
||||||
secondDate = minuteDate = new Date();
|
secondDate = minuteDate = new Date();
|
||||||
onSecond();
|
onSecond();
|
||||||
onMinute();
|
onMinute();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSecond() {
|
function onSecond() {
|
||||||
g.setColor(0,0,0.6);
|
g.setColor(0,0,0.6);
|
||||||
seconds(360*secondDate.getSeconds()/60, 90);
|
seconds(360*secondDate.getSeconds()/60, 90);
|
||||||
g.setColor(1,0,0);
|
g.setColor(1,0,0);
|
||||||
|
@ -42,26 +47,53 @@ function onSecond() {
|
||||||
seconds(360*secondDate.getSeconds()/60, 90);
|
seconds(360*secondDate.getSeconds()/60, 90);
|
||||||
g.setColor(1,1,1);
|
g.setColor(1,1,1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMinute() {
|
function onMinute() {
|
||||||
g.setColor(0,0,0);
|
g.setColor(0,0,0);
|
||||||
hand(360*minuteDate.getHours()/12, -10, 50);
|
hand(360*minuteDate.getHours()/12, -10, 50);
|
||||||
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
||||||
oldMinute = new Date();
|
minuteDate = new Date();
|
||||||
g.setColor(1,1,1);
|
g.setColor(1,1,1);
|
||||||
hand(360*minuteDate.getHours()/12, -10, 50);
|
hand(360*minuteDate.getHours()/12, -10, 50);
|
||||||
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
||||||
}
|
if(minuteDate.getHours() >= 0 && minuteDate.getMinutes() === 0) {
|
||||||
|
Bangle.buzz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setInterval(onSecond,1000);
|
function clearTimers() {
|
||||||
setInterval(onMinute,60*1000);
|
if(intervalRefMin) {clearInterval(intervalRefMin);}
|
||||||
drawAll();
|
if(intervalRefSec) {clearInterval(intervalRefSec);}
|
||||||
|
}
|
||||||
|
|
||||||
Bangle.on('lcdPower',function(on) {
|
function startTimers() {
|
||||||
|
minuteDate = new Date();
|
||||||
|
secondDate = new Date();
|
||||||
|
intervalRefSec = setInterval(onSecond,1000);
|
||||||
|
intervalRefMin = setInterval(onMinute,60*1000);
|
||||||
|
drawAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
startTimers();
|
||||||
|
|
||||||
|
Bangle.on('lcdPower',function(on) {
|
||||||
if (on) {
|
if (on) {
|
||||||
g.clear();
|
g.clear();
|
||||||
drawAll();
|
startTimers();
|
||||||
drawWidgets();
|
drawWidgets();
|
||||||
|
}else {
|
||||||
|
clearTimers();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Bangle.on('gesture',function(gesture){
|
||||||
|
if (gesture && !Bangle.isLCDOn()) {
|
||||||
|
clearTimers();
|
||||||
|
Bangle.setLCDTimeout(30);
|
||||||
|
Bangle.setLCDPower(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAAAAMGAAAAAAYDAAAAAAwBgAAAABgAwAAAABAAQAAAABAAQAAAABAAQAAAABAAQAAAABAAQAAAABgAwAAAAAwBgAAAAAYDAAAAAAMGAAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAAAAP+AAAAAAf/AAAAAA//gAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAA//gAAAAAf/AAAAAAP+AAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
|
@ -0,0 +1,106 @@
|
||||||
|
(() => {
|
||||||
|
const canvasWidth = 290;
|
||||||
|
const numberOfColumns = 6;
|
||||||
|
const drawFullGrid = false;
|
||||||
|
|
||||||
|
const colpos = canvasWidth / numberOfColumns - 10;
|
||||||
|
const binSize = (canvasWidth / numberOfColumns) / 3;
|
||||||
|
|
||||||
|
const findBinary = target => {
|
||||||
|
return [
|
||||||
|
[0, 0, 0, 0], // 0
|
||||||
|
[1, 0, 0, 0], // 1
|
||||||
|
[0, 1, 0, 0], // 2
|
||||||
|
[1, 1, 0, 0], // 3
|
||||||
|
[0, 0, 1, 0], // 4
|
||||||
|
[1, 0, 1, 0], // 5
|
||||||
|
[0, 1, 1, 0], // 6
|
||||||
|
[1, 1, 1, 0], // 7
|
||||||
|
[0, 0, 0, 1], // 8
|
||||||
|
[1, 0, 0, 1], // 9
|
||||||
|
][target];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentTime = () => {
|
||||||
|
const flattenArray = (array = []) => [].concat.apply([], array);
|
||||||
|
const format = number => {
|
||||||
|
const numberStr = number.toString();
|
||||||
|
return numberStr.length === 1 ? ["0", numberStr] : numberStr.split("");
|
||||||
|
};
|
||||||
|
const now = new Date();
|
||||||
|
return flattenArray([now.getHours(), now.getMinutes(), now.getSeconds()].map(format));
|
||||||
|
};
|
||||||
|
|
||||||
|
let prevFrame = [];
|
||||||
|
const drawColumn = (position = 0, column = [0, 0, 0, 0]) => {
|
||||||
|
const maxDotsPerColumn = [2, 4, 3, 4, 3, 4];
|
||||||
|
|
||||||
|
const columnPos = position * colpos;
|
||||||
|
let pos = colpos / 2 + 45;
|
||||||
|
const frame = column.reverse();
|
||||||
|
const drawDot = fn => g[fn]((columnPos + colpos / 2), pos, binSize);
|
||||||
|
|
||||||
|
for (let i = 0; i < frame.length; i += 1) {
|
||||||
|
if (i + maxDotsPerColumn[position] >= 4 || drawFullGrid) {
|
||||||
|
if (prevFrame && prevFrame[position] && prevFrame[position][i]) {
|
||||||
|
if (frame[i] !== prevFrame[position][i]) {
|
||||||
|
// subsequent draw
|
||||||
|
g.clearRect((columnPos + colpos / 2) - 15, pos - 15, (columnPos + colpos / 2) + 20, pos + 20);
|
||||||
|
if (frame[i]) {
|
||||||
|
drawDot('fillCircle');
|
||||||
|
} else {
|
||||||
|
drawDot('drawCircle');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// First draw
|
||||||
|
if (frame[i]) {
|
||||||
|
drawDot('fillCircle');
|
||||||
|
} else {
|
||||||
|
drawDot('drawCircle');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += colpos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawClock = () => {
|
||||||
|
const data = getCurrentTime().map(findBinary);
|
||||||
|
for (let i = 0; i < data.length; i += 1) {
|
||||||
|
drawColumn(i, data[i]);
|
||||||
|
}
|
||||||
|
prevFrame = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Themes
|
||||||
|
const drawTheme = (idx) => () => {
|
||||||
|
idx += 1;
|
||||||
|
const themes = [
|
||||||
|
[[0, 0, 0], [1, 1, 1]],
|
||||||
|
[[1, 1, 1], [0, 0, 0]],
|
||||||
|
[[0, 0, 0], [1, 0, 0]],
|
||||||
|
[[0, 0, 0], [0, 1, 0]],
|
||||||
|
[[0, 0, 0], [0, 0, 1]],
|
||||||
|
];
|
||||||
|
if (idx >= themes.length) idx = 0;
|
||||||
|
const color = themes[idx];
|
||||||
|
g.setBgColor.apply(g, color[0]);
|
||||||
|
g.setColor.apply(g, color[1]);
|
||||||
|
g.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
const nextTheme = drawTheme(0);
|
||||||
|
setWatch(() => {
|
||||||
|
prevFrame = [];
|
||||||
|
Bangle.beep();
|
||||||
|
nextTheme();
|
||||||
|
}, BTN1, { repeat: true });
|
||||||
|
|
||||||
|
Bangle.on('lcdPower', on => {
|
||||||
|
if (on) drawClock();
|
||||||
|
});
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
setInterval(() => { drawClock(); }, 1000);
|
||||||
|
})();
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name":"Binary Clock",
|
||||||
|
"type":"clock",
|
||||||
|
"icon":"*bclock",
|
||||||
|
"src":"-bclock"
|
||||||
|
}
|
||||||
|
|
After Width: | Height: | Size: 743 B |
|
@ -0,0 +1 @@
|
||||||
|
0
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwiBC/AH4A/AHOQzYBNJ/5f/L/5P/L/5f/J/5f/L/5P/L/4A/AH6/haP5f/L/5f/L/5f/L/5f/L/5f/L/4A/AFP/ABy/lL/5f/L/5f/L/5f/L/5f/L/5f/L/4A/VtK/jL/5f/L/5f/L/5f/L/5f/L/5f/L/4A/X/7RxEa5f/L/5f/L/5f/L/5f/L/5f/L/5ffAH4A/AHYA="))
|
|
@ -0,0 +1,309 @@
|
||||||
|
Bangle.setLCDMode("doublebuffered");
|
||||||
|
|
||||||
|
const storage = require("Storage");
|
||||||
|
|
||||||
|
var BTN_L = BTN1;
|
||||||
|
var BTN_R = BTN3;
|
||||||
|
var BTN_ROT = BTN2;
|
||||||
|
var BTN_DOWN = BTN5;
|
||||||
|
var BTN_PAUSE = BTN4;
|
||||||
|
|
||||||
|
const W = g.getWidth();
|
||||||
|
const H = g.getHeight();
|
||||||
|
const CX = W / 2;
|
||||||
|
const CY = H / 2;
|
||||||
|
|
||||||
|
const HEIGHT_BUFFER = 4;
|
||||||
|
|
||||||
|
const LINES = 20;
|
||||||
|
const COLUMNS = 11;
|
||||||
|
const CELL_SIZE = Math.floor((H - HEIGHT_BUFFER) / (LINES + 1));
|
||||||
|
|
||||||
|
const BOARD_X = Math.floor((W - CELL_SIZE * COLUMNS) / 2) + 2;
|
||||||
|
const BOARD_Y = Math.floor((H - CELL_SIZE * (LINES + 1)) / 2);
|
||||||
|
const BOARD_W = COLUMNS * CELL_SIZE;
|
||||||
|
const BOARD_H = LINES * CELL_SIZE;
|
||||||
|
|
||||||
|
const TEXT_X = BOARD_X + BOARD_W + 10;
|
||||||
|
|
||||||
|
const BLOCKS = [
|
||||||
|
[
|
||||||
|
[2, 7],
|
||||||
|
[2, 6, 2],
|
||||||
|
[0, 7, 2],
|
||||||
|
[2, 3, 2]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[1, 3, 2],
|
||||||
|
[6, 3]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 3, 1],
|
||||||
|
[3, 6]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 2, 6],
|
||||||
|
[0, 7, 1],
|
||||||
|
[3, 2, 2],
|
||||||
|
[4, 7]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 2, 3],
|
||||||
|
[1, 7],
|
||||||
|
[6, 2, 2],
|
||||||
|
[0, 7, 4]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 2, 2, 2],
|
||||||
|
[0, 15]
|
||||||
|
],
|
||||||
|
[[3, 3]]
|
||||||
|
];
|
||||||
|
|
||||||
|
const COLOR_WHITE = 0b1111111111111111;
|
||||||
|
const COLOR_BLACK = 0b0000000000000000;
|
||||||
|
|
||||||
|
const BLOCK_COLORS = [
|
||||||
|
//0brrrrrggggggbbbbb
|
||||||
|
0b0111100000001111,
|
||||||
|
0b0000011111100000,
|
||||||
|
0b1111100000000011,
|
||||||
|
0b0111100111100000,
|
||||||
|
0b0000000000011111,
|
||||||
|
0b0000001111111111,
|
||||||
|
0b1111111111100000
|
||||||
|
];
|
||||||
|
|
||||||
|
const EMPTY_LINE = 0b00000000000000;
|
||||||
|
const BOUNDARY = 0b10000000000010;
|
||||||
|
const FULL_LINE = 0b01111111111100;
|
||||||
|
|
||||||
|
let gameOver = false;
|
||||||
|
let paused = false;
|
||||||
|
let currentBlock = 0;
|
||||||
|
let nextBlock = 0;
|
||||||
|
let x, y;
|
||||||
|
let points;
|
||||||
|
let level;
|
||||||
|
let lines;
|
||||||
|
let board;
|
||||||
|
let rotation = 0;
|
||||||
|
let ticker = null;
|
||||||
|
let needDraw = true;
|
||||||
|
let highScore = parseInt(storage.read(".trishig") || 0, 10);
|
||||||
|
|
||||||
|
function getBlock(a, c, d) {
|
||||||
|
const block = BLOCKS[a % 7];
|
||||||
|
return block[(a + c) % block.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawBlock(block, screenX, screenY, x, y) {
|
||||||
|
for (let row in block) {
|
||||||
|
let mask = block[row];
|
||||||
|
for (let col = 0; mask; mask >>= 1, col++) {
|
||||||
|
if (mask % 2) {
|
||||||
|
const dx = screenX + (x + col) * CELL_SIZE;
|
||||||
|
const dy = screenY + (y + row) * CELL_SIZE;
|
||||||
|
g.fillRect(dx, dy, dx + CELL_SIZE - 3, dy + CELL_SIZE - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawBoard() {
|
||||||
|
g.setColor(COLOR_WHITE);
|
||||||
|
g.drawRect(BOARD_X - 3, BOARD_Y - 3, BOARD_X + BOARD_W, BOARD_Y + BOARD_H);
|
||||||
|
drawBlock(board, BOARD_X, BOARD_Y, -2, 0);
|
||||||
|
|
||||||
|
g.setColor(BLOCK_COLORS[currentBlock]);
|
||||||
|
drawBlock(getBlock(currentBlock, rotation), BOARD_X, BOARD_Y, x - 2, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawNextBlock() {
|
||||||
|
g.setFontAlign(0, -1, 0);
|
||||||
|
g.setColor(COLOR_WHITE);
|
||||||
|
g.drawString("NEXT BLOCK", BOARD_X / 2, 10);
|
||||||
|
g.setColor(BLOCK_COLORS[nextBlock]);
|
||||||
|
drawBlock(getBlock(nextBlock, 0), BOARD_X / 2 - 2 * CELL_SIZE, 25, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTextLine(text, line) {
|
||||||
|
g.drawString(text, TEXT_X, 10 + line * 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGameState() {
|
||||||
|
g.setFontAlign(-1, -1, 0);
|
||||||
|
g.setColor(COLOR_WHITE);
|
||||||
|
let ln = 0;
|
||||||
|
drawTextLine("CLOCK-TRIS", ln++);
|
||||||
|
ln++;
|
||||||
|
drawTextLine("LVL " + level, ln++);
|
||||||
|
drawTextLine("LNS " + lines, ln++);
|
||||||
|
drawTextLine("PTS " + points, ln++);
|
||||||
|
drawTextLine("TOP " + highScore, ln++);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawBanner(text) {
|
||||||
|
g.setFontAlign(0, 0, 0);
|
||||||
|
g.setColor(COLOR_BLACK);
|
||||||
|
g.fillRect(CX - 46, CY - 11, CX + 46, CY + 9);
|
||||||
|
g.setColor(COLOR_WHITE);
|
||||||
|
g.drawRect(CX - 45, CY - 10, CX + 45, CY + 8);
|
||||||
|
g.drawString(text, CX, CY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPaused() {
|
||||||
|
drawBanner("PAUSED");
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGameOver() {
|
||||||
|
drawBanner("GAME OVER");
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
g.clear();
|
||||||
|
g.setFont("6x8");
|
||||||
|
drawBoard();
|
||||||
|
drawNextBlock();
|
||||||
|
drawGameState();
|
||||||
|
if (paused) {
|
||||||
|
drawPaused();
|
||||||
|
}
|
||||||
|
if (gameOver) {
|
||||||
|
drawGameOver();
|
||||||
|
}
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNextBlock() {
|
||||||
|
currentBlock = nextBlock;
|
||||||
|
nextBlock = (Math.random() * BLOCKS.length) | 0;
|
||||||
|
x = 6;
|
||||||
|
y = 0;
|
||||||
|
rotation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function landBlock(a) {
|
||||||
|
const block = getBlock(currentBlock, rotation);
|
||||||
|
for (let row in block) {
|
||||||
|
board[y + (row | 0)] |= block[row] << x;
|
||||||
|
}
|
||||||
|
|
||||||
|
let clearedLines = 0;
|
||||||
|
let keepLine = LINES;
|
||||||
|
for (let line = LINES - 1; line >= 0; line--) {
|
||||||
|
if (board[line] === FULL_LINE) {
|
||||||
|
clearedLines++;
|
||||||
|
} else {
|
||||||
|
board[--keepLine] = board[line];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines += clearedLines;
|
||||||
|
if (lines > level * 10) {
|
||||||
|
level++;
|
||||||
|
setSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--keepLine > 0) {
|
||||||
|
board[keepLine] = EMPTY_LINE;
|
||||||
|
}
|
||||||
|
if (clearedLines) {
|
||||||
|
points += 100 * (1 << (clearedLines - 1));
|
||||||
|
needDraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNextBlock();
|
||||||
|
if (!checkMove(0, 0, 0)) {
|
||||||
|
gameOver = true;
|
||||||
|
needDraw = true;
|
||||||
|
highScore = Math.max(points, highScore);
|
||||||
|
storage.write(".trishig", highScore.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMove(dx, dy, rot) {
|
||||||
|
if (gameOver) {
|
||||||
|
startGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const block = getBlock(currentBlock, rotation + rot);
|
||||||
|
for (const row in block) {
|
||||||
|
const movedBlockRow = block[row] << (x + dx);
|
||||||
|
if (
|
||||||
|
row + y === LINES - 1 ||
|
||||||
|
movedBlockRow & board[y + dy + row] ||
|
||||||
|
movedBlockRow & BOUNDARY
|
||||||
|
) {
|
||||||
|
if (dy) {
|
||||||
|
landBlock();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rotation += rot;
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
needDraw = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLoop() {
|
||||||
|
if (needDraw) {
|
||||||
|
needDraw = false;
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
setTimeout(drawLoop, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gameTick() {
|
||||||
|
if (!gameOver) {
|
||||||
|
checkMove(0, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSpeed() {
|
||||||
|
if (ticker) {
|
||||||
|
clearInterval(ticker);
|
||||||
|
}
|
||||||
|
ticker = setInterval(gameTick, 1000 - level * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePause() {
|
||||||
|
if (!gameOver) {
|
||||||
|
paused = !paused;
|
||||||
|
needDraw = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startGame() {
|
||||||
|
board = [];
|
||||||
|
for (let i = 0; i < LINES; i++) {
|
||||||
|
board[i] = EMPTY_LINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameOver = false;
|
||||||
|
points = 0;
|
||||||
|
lines = 0;
|
||||||
|
level = 0;
|
||||||
|
getNextBlock();
|
||||||
|
setSpeed();
|
||||||
|
needDraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindButton(btn, dx, dy, r) {
|
||||||
|
setWatch(checkMove.bind(null, dx, dy, r), btn, { repeat: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
bindButton(BTN_L, -1, 0, 0);
|
||||||
|
bindButton(BTN_R, 1, 0, 0);
|
||||||
|
bindButton(BTN_ROT, 0, 0, 1);
|
||||||
|
bindButton(BTN_DOWN, 0, 1, 0);
|
||||||
|
|
||||||
|
setWatch(togglePause, BTN_PAUSE, { repeat: true });
|
||||||
|
|
||||||
|
startGame();
|
||||||
|
drawLoop();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name":"Clock-Tris",
|
||||||
|
"icon":"*clotris",
|
||||||
|
"src":"-clotris"
|
||||||
|
}
|
After Width: | Height: | Size: 303 B |
|
@ -23,7 +23,7 @@ Bangle.on('mag', function(m) {
|
||||||
g.fillRect(70,0,170,24);
|
g.fillRect(70,0,170,24);
|
||||||
g.setColor(0xffff);
|
g.setColor(0xffff);
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.drawString((m.heading===undefined)?"---":Math.round(m.heading),120,12);
|
g.drawString(isNaN(m.heading)?"---":Math.round(m.heading),120,12);
|
||||||
g.setColor(0,0,0);
|
g.setColor(0,0,0);
|
||||||
arrow(oldHeading,0);
|
arrow(oldHeading,0);
|
||||||
arrow(oldHeading+180,0);
|
arrow(oldHeading+180,0);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwghC/AH4AKg9wC6t3u4uVC6wWBI6t3uJeVuMQCqcBLisAi4XLxAABFxAXKgc4DBAuBRhQXEDAq7MmYXEwBHEXZYXFGAOqAAKDMmczC4mIC62CC50PC4JIBkQABiIvRmURAAUSjQXSFwMoxGKC6CRFwUSVYgXLPIgXXwMYegoXLJAYXCGBnzGA0hPQIwMgYwGC6gwCC4ZIMC4gYBC604C4ZISmcRVgapQAAMhC6GIJIwXCMBcIxGDDBAuLC4IwGAARGMAAQWGmAXPJQoWMC4pwCCpoXJAB4XXAH4A/ABQA="))
|
|
@ -0,0 +1,55 @@
|
||||||
|
var img = require("heatshrink").decompress(atob("mEwghC/AH4AKg9wC6t3u4uVC6wWBI6t3uJeVuMQCqcBLisAi4XLxAABFxAXKgc4DBAuBRhQXEDAq7MmYXEwBHEXZYXFGAOqAAKDMmczC4mIC62CC50PC4JIBkQABiIvRmURAAUSjQXSFwMoxGKC6CRFwUSVYgXLPIgXXwMYegoXLJAYXCGBnzGA0hPQIwMgYwGC6gwCC4ZIMC4gYBC604C4ZISmcRVgapQAAMhC6GIJIwXCMBcIxGDDBAuLC4IwGAARGMAAQWGmAXPJQoWMC4pwCCpoXJAB4XXAH4A/ABQA="))
|
||||||
|
|
||||||
|
Bangle.setGPSPower(1);
|
||||||
|
Bangle.setLCDMode("doublebuffered");
|
||||||
|
|
||||||
|
var lastFix = {
|
||||||
|
fix: 0,
|
||||||
|
alt: 0,
|
||||||
|
lat: 0,
|
||||||
|
lon: 0,
|
||||||
|
time: 0,
|
||||||
|
satellites: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
function formatTime(now) {
|
||||||
|
var fd = now.toUTCString().split(" ");
|
||||||
|
var time = fd[4].substr(0, 5);
|
||||||
|
var date = [fd[0], fd[1], fd[2]].join(" ");
|
||||||
|
var year = now.getFullYear();
|
||||||
|
return time + " - " + date;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGPS(fix) {
|
||||||
|
lastFix = fix;
|
||||||
|
g.clear();
|
||||||
|
g.setFontAlign(-1, -1);
|
||||||
|
g.drawImage(img, 30, -6);
|
||||||
|
g.setFont("6x8");
|
||||||
|
g.setFontVector(22);
|
||||||
|
g.drawString("GPS Info", 80, 6);
|
||||||
|
if (fix.fix) {
|
||||||
|
var alt = fix.alt;
|
||||||
|
var lat = fix.lat;
|
||||||
|
var lon = fix.lon;
|
||||||
|
var time = formatTime(fix.time);
|
||||||
|
var satellites = fix.satellites;
|
||||||
|
|
||||||
|
var s = 12;
|
||||||
|
g.setFontVector(s+4);
|
||||||
|
g.drawString("Altitude: "+alt+" m",0,60);
|
||||||
|
g.setFontVector(s);
|
||||||
|
g.drawString("Lat: "+lat, 0, 60+20+s/2);
|
||||||
|
g.drawString("Lon: "+lon,0,60+40+s/2);
|
||||||
|
g.drawString("Time: "+time, 0, 60+60+s/2);
|
||||||
|
g.drawString("Satellites: "+satellites,0,60+80+s/2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g.setFontAlign(0, 1);
|
||||||
|
g.setFont("6x8", 2);
|
||||||
|
g.drawString("Waiting for GPS", 120, 80);
|
||||||
|
}
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
Bangle.on('GPS', onGPS);
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "GPS Info",
|
||||||
|
"type": "app",
|
||||||
|
"icon": "*gpsinfo",
|
||||||
|
"src": "-gpsinfo"
|
||||||
|
}
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -39,11 +39,16 @@ function readHRM() {
|
||||||
t.sort();
|
t.sort();
|
||||||
// average the middle 3
|
// average the middle 3
|
||||||
var mid = t.length>>1;
|
var mid = t.length>>1;
|
||||||
|
if (mid+2<t.length)
|
||||||
hrm = (t[mid]+t[mid+1]+t[mid+2])/3;
|
hrm = (t[mid]+t[mid+1]+t[mid+2])/3;
|
||||||
|
else if (mid<t.length)
|
||||||
|
hrm = t[mid];
|
||||||
|
else
|
||||||
|
hrm = 0;
|
||||||
g.setFontVector(40);
|
g.setFontVector(40);
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.clearRect(0,0,239,100);
|
g.clearRect(0,0,239,100);
|
||||||
var str = Math.round(hrm);
|
var str = hrm ? Math.round(hrm) : "?";
|
||||||
var px = 120;
|
var px = 120;
|
||||||
g.drawString(str,px,40);
|
g.drawString(str,px,40);
|
||||||
px += g.stringWidth(str)/2;
|
px += g.stringWidth(str)/2;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AH4A/AHeIDC+AC60IC/51ELoIXTCYMIDISLpC/67dxAAJHBYsLhAYKLhgXXHhWAdoQbBApAvhBgYcCAogXkI64XYhDtII/oMUERTyDABJ0FPI4A/AH4A/AGY="))
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
Binary search keyboard for typing with
|
||||||
|
the touchscreen
|
||||||
|
*/
|
||||||
|
|
||||||
|
var storage = require('Storage');
|
||||||
|
|
||||||
|
const settings = storage.readJSON('@setting') || { HID: false };
|
||||||
|
const KEY = {
|
||||||
|
A : 4 ,
|
||||||
|
B : 5 ,
|
||||||
|
C : 6 ,
|
||||||
|
D : 7 ,
|
||||||
|
E : 8 ,
|
||||||
|
F : 9 ,
|
||||||
|
G : 10,
|
||||||
|
H : 11,
|
||||||
|
I : 12,
|
||||||
|
J : 13,
|
||||||
|
K : 14,
|
||||||
|
L : 15,
|
||||||
|
M : 16,
|
||||||
|
N : 17,
|
||||||
|
O : 18,
|
||||||
|
P : 19,
|
||||||
|
Q : 20,
|
||||||
|
R : 21,
|
||||||
|
S : 22,
|
||||||
|
T : 23,
|
||||||
|
U : 24,
|
||||||
|
V : 25,
|
||||||
|
W : 26,
|
||||||
|
X : 27,
|
||||||
|
Y : 28,
|
||||||
|
Z : 29,
|
||||||
|
1 : 30,
|
||||||
|
2 : 31,
|
||||||
|
3 : 32,
|
||||||
|
4 : 33,
|
||||||
|
5 : 34,
|
||||||
|
6 : 35,
|
||||||
|
7 : 36,
|
||||||
|
8 : 37,
|
||||||
|
9 : 38,
|
||||||
|
0 : 39
|
||||||
|
};
|
||||||
|
|
||||||
|
function sendHID(code) {
|
||||||
|
return new Promise(resolve=>{
|
||||||
|
NRF.sendHIDReport([2,0,0,code,0,0,0,0,0], () => {
|
||||||
|
NRF.sendHIDReport([2,0,0,0,0,0,0,0,0], resolve);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function showChars(x,chars) {
|
||||||
|
var lines = Math.round(Math.sqrt(chars.length)*2);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
var sy = Math.round(200/lines);
|
||||||
|
var sx = sy;
|
||||||
|
g.setFont("Vector", sy-2);
|
||||||
|
var y = (240 - lines*sy);
|
||||||
|
var last = 0;
|
||||||
|
for (var i=0;i<lines;i++) {
|
||||||
|
var n = Math.round(chars.length*(i+1)/lines);
|
||||||
|
var xo = x + (120 - sx*(n-last-1))/2;
|
||||||
|
for (var j=last;j<n;j++)
|
||||||
|
g.drawString(chars[j], xo + (j-last)*sx, y + sy*i)
|
||||||
|
last = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show(chars,callback) {
|
||||||
|
g.clear();
|
||||||
|
if (chars.length==1) {
|
||||||
|
callback(chars);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var m = chars.length/2;
|
||||||
|
charl=chars.slice(0,m);
|
||||||
|
charr=chars.slice(m);
|
||||||
|
showChars(0,charl);
|
||||||
|
showChars(120,charr);
|
||||||
|
setWatch(() => {
|
||||||
|
clearWatch();
|
||||||
|
show(charl,callback);
|
||||||
|
}, BTN4);
|
||||||
|
setWatch(() => {
|
||||||
|
clearWatch();
|
||||||
|
show(charr,callback);
|
||||||
|
}, BTN5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCharacter() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
show("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startKeyboardHID() {
|
||||||
|
getCharacter().then(ch => {
|
||||||
|
return sendHID(KEY[ch]);
|
||||||
|
}).then(startKeyboardHID);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!settings.HID) {
|
||||||
|
E.showMessage('HID disabled');
|
||||||
|
setTimeout(load, 1000);
|
||||||
|
} else {
|
||||||
|
startKeyboardHID();
|
||||||
|
setWatch(() => {
|
||||||
|
sendHID(44); // space
|
||||||
|
}, BTN2, {repeat:true});
|
||||||
|
setWatch(() => {
|
||||||
|
sendHID(40); // enter
|
||||||
|
}, BTN3, {repeat:true});
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "Binary Keyboard","type":"app",
|
||||||
|
"icon": "*hidbkbd",
|
||||||
|
"src": "-hidbkbd"
|
||||||
|
}
|
After Width: | Height: | Size: 506 B |
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AVvNPp95F1tPqujF9IuCvPO5wspAAXHF84uFp4uBL84xEvPN5q+rqtiCBl6F7tiAAY9LvQDBF86cDvQvCGLYvEGAr7EF4IwDF7c4GQwuERwIACqpecrlcF4lWLw4ACF7s3F58rGDIvEA4VcFwtWL4ovSCwwvHFoiOHGCQXHXYdcBwQuIDIwsMI5QwEGIKNERgh6JFpIuKAAOAGIYvCqpYJAwUyFxaNIGAovEXBheOF5pfCrl6RYjoTVAYvMRwYOKF76NDwAveGBaNEF8AwLFzgvHeRovoqtWFxtVDQbwSF44KBqouLDYzAYqz8OPg5gSD6K9FGCIvJVoIdLdoxgUDop9NF7gcEPZwvZJgwvnbiwTHF54bLMCEsAAIvVTRBEOF7zBSF7StPGDB1HPpyMVDAgZFbxztWAH4A/AGw"))
|
|
@ -0,0 +1,85 @@
|
||||||
|
Bangle.setLCDMode("doublebuffered");
|
||||||
|
var img = {
|
||||||
|
width : 48, height : 48, bpp : 8,
|
||||||
|
transparent : 254,
|
||||||
|
buffer : require("heatshrink").decompress(atob("/wA/AH4A/ACl5p9PvIutp9V0YvpFwV553OFlIAC44vnFwtPFwJfnGIl55vNX1dVsQQMvQvdsQADHpd6AYIvnTgd6F4QxbF4gwFfYgvBGAYvbnAyGFwiOBAAVVLzlcrgvEqxeHAAQvdm4vPlYwZF4gHCrguFqxfFF6QWGF44tERw4wSC467DrgOCFxAZGFhhHKGAgxBRoiMEPRItJFxQABwAxDF4VVLBIGCmQuLRpAwFF4i4MLxwvNL4VcvSLEdCaoDF5iODBxQvfRoeAF7wwLRogvgGBYucF47yNF9FVqwuNqoaDeCQvHBQNVFxYbGYDFWfhx8HMCQfRXoowRF5KtBDpbtGMCgdFPpovcDgh7OF7JMGF87cWCY4vPDZZgQlgABF6qaIIhwveYKQvaVp4wYOo59ORioYEDIreOdqwA/AH4A2A"))
|
||||||
|
};
|
||||||
|
// ideally we'd just load the image file but it looks like NodeConf
|
||||||
|
// Bangle.js firmware had bug which meant that transparency in image
|
||||||
|
// strings wasn't used
|
||||||
|
//var img = require("Storage").read("*horsey");
|
||||||
|
var mycounter = 0;
|
||||||
|
var players = {};
|
||||||
|
setWatch(x=>{
|
||||||
|
mycounter++;
|
||||||
|
updateAdvertising();
|
||||||
|
},BTN1,{repeat:true});
|
||||||
|
|
||||||
|
function updateAdvertising() {
|
||||||
|
try {
|
||||||
|
NRF.setAdvertising({},{
|
||||||
|
manufacturer: 0x0590,
|
||||||
|
manufacturerData: new Uint8Array([mycounter>>8,mycounter&255]),
|
||||||
|
interval: 60
|
||||||
|
});
|
||||||
|
} catch(e){}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPlayers() {
|
||||||
|
g.setColor(0,0.3,0);
|
||||||
|
g.fillRect(0,0,240,160);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.setFont("6x8");
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
var max = mycounter;
|
||||||
|
var playerCount=0;
|
||||||
|
for (var player of players) {
|
||||||
|
max = Math.max(player.cnt, mycounter);
|
||||||
|
playerCount++;
|
||||||
|
}
|
||||||
|
var offset = 0;
|
||||||
|
if (max > 200)
|
||||||
|
offset = max-200;
|
||||||
|
|
||||||
|
var d = 63 - (offset&63);
|
||||||
|
g.fillRect(0,10,240,12);
|
||||||
|
for (var x=d;x<240;x+=64)
|
||||||
|
g.fillRect(x,12,x+2,12+20);
|
||||||
|
var y = 20;
|
||||||
|
var p = mycounter-offset;
|
||||||
|
g.drawString("You",p-16,y+20);
|
||||||
|
g.drawImage(img, p,y);
|
||||||
|
|
||||||
|
var spacing = (120-20)/(playerCount+1);
|
||||||
|
for (var player of players) {
|
||||||
|
y+=45;
|
||||||
|
var p = player.cnt-offset;
|
||||||
|
g.drawString(player.name,p-16,y+20);
|
||||||
|
g.drawImage(img, p,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
g.fillRect(0,150,240,152);
|
||||||
|
for (var x=d;x<240;x+=64)
|
||||||
|
g.fillRect(x,152,x+2,160);
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doScan() {
|
||||||
|
NRF.findDevices(devs=>{
|
||||||
|
devs.forEach(dev => {
|
||||||
|
players[dev.id] = {
|
||||||
|
name : dev.id.substr(12,5),
|
||||||
|
cnt : (dev.manufacturerData[0]<<8)|dev.manufacturerData[1]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
drawPlayers();
|
||||||
|
doScan();
|
||||||
|
},{timeout : 250, filters : [{ manufacturerData:{0x0590:{}} }] });
|
||||||
|
}
|
||||||
|
|
||||||
|
drawPlayers();
|
||||||
|
try { NRF.wake(); } catch (e) {}
|
||||||
|
doScan();
|
||||||
|
setInterval(drawPlayers, 100);
|
||||||
|
|
||||||
|
updateAdvertising();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name":"Horse Race",
|
||||||
|
"icon": "*horsey",
|
||||||
|
"src":"-horsey"
|
||||||
|
}
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwghC/AB8M5gAE4AWVDB4WCCAgHHCxIEBu4ACAoIYMCwUHCwYABuALDFxPACwQJDDAQMCFxAWHDAwuIBwQGBxAACDAYmCFxMAhAWDAAOADAIwIC4JuCFYYzDQAQXGAwIuCCwoYEEgLLGIwNwIoIHBgMRiMQDAWABoIRBIw8IK4IWCDAYJBJA6NCEoIWCBYYYCJAQSCLwpGCIYZLDJARgFC4RGDFwgwCJAYXFOweAgIuEGAUQC4Z4DAYJeEfY0AMAgXJIwxIDC/4X/U7DXW5gXDJA4GBC4fMC4t3hBgCGAkBLwWAu4XEgHMJ4JgDGAgdCLwQSCC4Z4BJAYYBAAQWBIwR2BC4h4EEoIYDJYRGBOwpgFBwIYCAAYHCLwxIFDAwFCIw4XDGARJBAAhnBFwQXGD4V3DAIrCGYYJCIwwwFDAQADA4IuIGAYYHCwQMCC44wBEQIYCAAaABFxIwDBgQWDEQYuJDAjLGCxgQEAAoWNDBAWPAH8AA"))
|
|
@ -0,0 +1,44 @@
|
||||||
|
class Ring {
|
||||||
|
constructor() {
|
||||||
|
this.alive = true;
|
||||||
|
this.radius = 0;
|
||||||
|
this.color = [
|
||||||
|
Math.random() > 0.5 ? 1 : 0, Math.random() > 0.5 ? 1 : 0, Math.random() > 0.5 ? 1 : 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const LIMIT = 10;
|
||||||
|
const RADIUS_LIMIT = 240;
|
||||||
|
const pool = [];
|
||||||
|
let RANDOM = 0;
|
||||||
|
let BUFFER = 0;
|
||||||
|
let BUFFER_SPREAD = 20;
|
||||||
|
|
||||||
|
const animate = () => {
|
||||||
|
if (pool.length < LIMIT && BUFFER === 0) {
|
||||||
|
const available = pool.filter(ring => !ring.alive);
|
||||||
|
const newRing = available.length ? available[0] : new Ring();
|
||||||
|
pool.push(newRing);
|
||||||
|
BUFFER = BUFFER_SPREAD;
|
||||||
|
}
|
||||||
|
g.clear();
|
||||||
|
if (BUFFER > 0) BUFFER--;
|
||||||
|
for (const ring of pool) {
|
||||||
|
if (ring.radius > RADIUS_LIMIT) {
|
||||||
|
ring.radius = 0;
|
||||||
|
ring.alive = false;
|
||||||
|
} else {
|
||||||
|
if (RANDOM) g.setColor(ring.color[0], ring.color[1], ring.color[2]);
|
||||||
|
else g.setColor(1, 1, 1);
|
||||||
|
g.drawCircle(120, 120, ring.radius++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(animate, 1000/60);
|
||||||
|
};
|
||||||
|
|
||||||
|
setWatch(() => (BUFFER_SPREAD += 5), BTN1, {repeat: true});
|
||||||
|
setWatch(() => (RANDOM = !RANDOM), BTN2, {repeat: true});
|
||||||
|
setWatch(() => (BUFFER_SPREAD -= 5), BTN3, {repeat: true});
|
||||||
|
|
||||||
|
animate();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name":"Hypno Rings","type":"app",
|
||||||
|
"icon":"*hrings",
|
||||||
|
"src":"-hrings"
|
||||||
|
}
|
After Width: | Height: | Size: 3.0 KiB |
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwkCIf4A/AH4A/AH4A/AA8RAAgHBgIHEiAXIp3uAAdQgEeA4ngC/4XoqlEAAaHBigHEoAQBgtVAAK4Thw2CC/4X/C8cBiIABC6YA/AH4A/AH4A/AHw"))
|
|
@ -0,0 +1,147 @@
|
||||||
|
/**
|
||||||
|
* Teach a user morse code
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Constants
|
||||||
|
*/
|
||||||
|
const FONT_NAME = 'Vector12';
|
||||||
|
const FONT_SIZE = 80;
|
||||||
|
const SCREEN_PIXELS = 240;
|
||||||
|
const UNIT = 100;
|
||||||
|
const MORSE_MAP = {
|
||||||
|
A: '.-',
|
||||||
|
B: '-...',
|
||||||
|
C: '-.-.',
|
||||||
|
D: '-..',
|
||||||
|
E: '.',
|
||||||
|
F: '..-.',
|
||||||
|
G: '--.',
|
||||||
|
H: '....',
|
||||||
|
I: '..',
|
||||||
|
J: '.---',
|
||||||
|
K: '-.-',
|
||||||
|
L: '.-..',
|
||||||
|
M: '--',
|
||||||
|
N: '-.',
|
||||||
|
O: '---',
|
||||||
|
P: '.--.',
|
||||||
|
Q: '--.-',
|
||||||
|
R: '.-.',
|
||||||
|
S: '...',
|
||||||
|
T: '-',
|
||||||
|
U: '..-',
|
||||||
|
V: '...-',
|
||||||
|
W: '.--',
|
||||||
|
X: '-..-',
|
||||||
|
Y: '-.--',
|
||||||
|
Z: '--..',
|
||||||
|
'1': '.----',
|
||||||
|
'2': '..---',
|
||||||
|
'3': '...--',
|
||||||
|
'4': '....-',
|
||||||
|
'5': '.....',
|
||||||
|
'6': '-....',
|
||||||
|
'7': '--...',
|
||||||
|
'8': '---..',
|
||||||
|
'9': '----.',
|
||||||
|
'0': '-----',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the local state
|
||||||
|
*/
|
||||||
|
let INDEX = 0;
|
||||||
|
let BEEPING = false;
|
||||||
|
let BUZZING = true;
|
||||||
|
let UNIT_INDEX = 0;
|
||||||
|
let UNITS = MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]].split('');
|
||||||
|
/**
|
||||||
|
* Utility functions for writing text, changing state
|
||||||
|
*/
|
||||||
|
const writeText = (txt) => {
|
||||||
|
g.clear();
|
||||||
|
const width = g.stringWidth(txt);
|
||||||
|
g.drawString(txt, (SCREEN_PIXELS / 2) - (width / 2), SCREEN_PIXELS / 2);
|
||||||
|
};
|
||||||
|
const writeLetter = () => {
|
||||||
|
writeText(Object.keys(MORSE_MAP)[INDEX]);
|
||||||
|
};
|
||||||
|
const writeCode = () => {
|
||||||
|
writeText(MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]]);
|
||||||
|
};
|
||||||
|
const setUnits = () => {
|
||||||
|
UNITS = MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]].split('');
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Bootstrapping
|
||||||
|
*/
|
||||||
|
g.clear();
|
||||||
|
g.setFont(FONT_NAME, FONT_SIZE);
|
||||||
|
g.setColor(0, 1, 0);
|
||||||
|
g.setFontAlign(-1, 0, 0);
|
||||||
|
/**
|
||||||
|
* The length of a dot is one unit
|
||||||
|
* The length of a dash is three units
|
||||||
|
* The length of a space is one unit
|
||||||
|
* The space between letters is three units
|
||||||
|
* The space between words is seven units
|
||||||
|
*/
|
||||||
|
const beepItOut = () => {
|
||||||
|
// If we are starting the beeps, use a timeout for pause of three units
|
||||||
|
const wait = UNIT_INDEX === 0 ? UNIT * 3 : 0;
|
||||||
|
setTimeout(() => {
|
||||||
|
Promise.all([
|
||||||
|
Bangle.beep(UNITS[UNIT_INDEX] === '.' ? UNIT : 3 * UNIT),
|
||||||
|
// Could make buzz optional or switchable potentially
|
||||||
|
BUZZING ? Bangle.buzz(UNITS[UNIT_INDEX] === '.' ? UNIT : 3 * UNIT) : null
|
||||||
|
])
|
||||||
|
.then(() => {
|
||||||
|
if (UNITS[UNIT_INDEX + 1]) {
|
||||||
|
setTimeout(() => {
|
||||||
|
UNIT_INDEX++;
|
||||||
|
beepItOut();
|
||||||
|
}, UNIT);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
BEEPING = false;
|
||||||
|
UNIT_INDEX = 0;
|
||||||
|
writeLetter();
|
||||||
|
}, 3 * UNIT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, wait);
|
||||||
|
};
|
||||||
|
const startBeep = () => {
|
||||||
|
if (BEEPING) return;
|
||||||
|
else {
|
||||||
|
BEEPING = true;
|
||||||
|
writeCode();
|
||||||
|
beepItOut();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const step = (positive) => () => {
|
||||||
|
if (BEEPING) return;
|
||||||
|
if (positive) {
|
||||||
|
INDEX = INDEX + 1;
|
||||||
|
if (INDEX > Object.keys(MORSE_MAP).length - 1) INDEX = 0;
|
||||||
|
} else {
|
||||||
|
INDEX = INDEX - 1;
|
||||||
|
if (INDEX < 0) INDEX = Object.keys(MORSE_MAP).length - 1;
|
||||||
|
}
|
||||||
|
setUnits();
|
||||||
|
writeLetter();
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleBuzzing = () => (BUZZING = !BUZZING);
|
||||||
|
|
||||||
|
writeLetter();
|
||||||
|
|
||||||
|
// Press the middle button to hear the morse code translation
|
||||||
|
setWatch(startBeep, BTN2, { repeat: true });
|
||||||
|
// Allow user to switch between letters
|
||||||
|
setWatch(step(true), BTN1, { repeat: true });
|
||||||
|
setWatch(step(false), BTN3, { repeat: true });
|
||||||
|
// Toggle buzzing/beeping with the touchscreen
|
||||||
|
setWatch(toggleBuzzing, BTN4, { repeat: true });
|
||||||
|
setWatch(toggleBuzzing, BTN5, { repeat: true });
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name":"Morse Code","type":"app",
|
||||||
|
"icon":"*morse",
|
||||||
|
"src":"-morse"
|
||||||
|
}
|
After Width: | Height: | Size: 413 B |
|
@ -13,14 +13,14 @@ Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQ
|
||||||
} else
|
} else
|
||||||
delete Bangle.HID;
|
delete Bangle.HID;
|
||||||
}
|
}
|
||||||
setTimeout(function() {
|
|
||||||
NRF.setServices({}, adv);
|
NRF.setServices({}, adv);
|
||||||
if (s.ble) NRF.wake();
|
// we just reset, so BLE should be on
|
||||||
else NRF.sleep();
|
try { // disable advertising if BLE should be off
|
||||||
},10);
|
if (!s.ble) NRF.sleep();
|
||||||
|
else NRF.wake();
|
||||||
if (!s.vibrate) Bangle.buzz=()=>Promise.resolve();
|
} catch(e) {}
|
||||||
if (!s.beep) Bangle.beep=()=>Promise.resolve();
|
if (!s.vibrate) Bangle.buzz=Promise.resolve;
|
||||||
|
if (!s.beep) Bangle.beep=Promise.resolve;
|
||||||
Bangle.setLCDTimeout(s.timeout);
|
Bangle.setLCDTimeout(s.timeout);
|
||||||
if (!s.timeout) Bangle.setLCDPower(1);
|
if (!s.timeout) Bangle.setLCDPower(1);
|
||||||
E.setTimeZone(s.timezone);
|
E.setTimeZone(s.timezone);
|
||||||
|
|
23
comms.js
|
@ -63,5 +63,28 @@ setTime : () => {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
disconnectDevice: () => {
|
||||||
|
var connection = Puck.getConnection();
|
||||||
|
|
||||||
|
if (!connection) return;
|
||||||
|
|
||||||
|
connection.close();
|
||||||
|
},
|
||||||
|
watchConnectionChange : cb => {
|
||||||
|
var connected = Puck.isConnected();
|
||||||
|
|
||||||
|
//TODO Switch to an event listener when Puck will support it
|
||||||
|
var interval = setInterval(() => {
|
||||||
|
if (connected === Puck.isConnected()) return;
|
||||||
|
|
||||||
|
connected = Puck.isConnected();
|
||||||
|
cb(connected);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
//stop watching
|
||||||
|
return () => {
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
background: #ddd;
|
background: #ddd;
|
||||||
}
|
}
|
||||||
#toastcontainer {
|
#toastcontainer {
|
||||||
position:absolute;
|
position:fixed;
|
||||||
bottom:8px;left:0px;right:0px;
|
bottom:8px;left:0px;right:0px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<!-- <a href="#" class="btn btn-link">...</a> -->
|
<!-- <a href="#" class="btn btn-link">...</a> -->
|
||||||
</section>
|
</section>
|
||||||
<section class="navbar-section">
|
<section class="navbar-section">
|
||||||
<button class="btn" id="connectmydevice" style="text-align: right;">Connect</button>
|
<button class="btn" id="connectmydevice">Connect</button>
|
||||||
</section>
|
</section>
|
||||||
<!--<section class="navbar-section">
|
<!--<section class="navbar-section">
|
||||||
<div class="input-group input-inline">
|
<div class="input-group input-inline">
|
||||||
|
|
32
index.js
|
@ -247,23 +247,39 @@ function refreshMyApps() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectMyDeviceBtn = document.getElementById("connectmydevice");
|
|
||||||
|
|
||||||
function getInstalledApps() {
|
function getInstalledApps() {
|
||||||
showLoadingIndicator();
|
showLoadingIndicator();
|
||||||
// Get apps
|
// Get apps
|
||||||
Comms.getInstalledApps().then(appIDs => {
|
return Comms.getInstalledApps().then(appIDs => {
|
||||||
appsInstalled = appIDs;
|
appsInstalled = appIDs;
|
||||||
connectMyDeviceBtn.style.display = 'none';
|
handleConnectionChange(true);
|
||||||
refreshMyApps();
|
refreshMyApps();
|
||||||
refreshLibrary();
|
refreshLibrary();
|
||||||
}).catch(err => {
|
|
||||||
showToast("Getting app list failed, "+err,"error");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("myappsrefresh").addEventListener("click", getInstalledApps);
|
var connectMyDeviceBtn = document.getElementById("connectmydevice");
|
||||||
connectMyDeviceBtn.addEventListener("click", getInstalledApps);
|
|
||||||
|
function handleConnectionChange(connected) {
|
||||||
|
connectMyDeviceBtn.textContent = connected ? 'Disconnect' : 'Connect';
|
||||||
|
connectMyDeviceBtn.classList.toggle('is-connected', connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("myappsrefresh").addEventListener("click", () => {
|
||||||
|
getInstalledApps().catch(err => {
|
||||||
|
showToast("Getting app list failed, "+err,"error");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
connectMyDeviceBtn.addEventListener("click", () => {
|
||||||
|
if (connectMyDeviceBtn.classList.contains('is-connected')) {
|
||||||
|
Comms.disconnectDevice();
|
||||||
|
} else {
|
||||||
|
getInstalledApps().catch(err => {
|
||||||
|
showToast("Device connection failed, "+err,"error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Comms.watchConnectionChange(handleConnectionChange);
|
||||||
|
|
||||||
// =========================================== About
|
// =========================================== About
|
||||||
|
|
||||||
|
|