2020-04-05 00:12:04 +00:00
|
|
|
Bangle.setLCDMode("120x120");
|
2020-04-02 18:36:19 +00:00
|
|
|
g.clear();
|
2020-04-05 00:12:04 +00:00
|
|
|
g.flip();
|
2020-04-02 18:36:19 +00:00
|
|
|
|
2020-04-02 18:38:12 +00:00
|
|
|
const Storage = require("Storage");
|
2020-04-02 18:36:19 +00:00
|
|
|
|
|
|
|
function getApps(){
|
|
|
|
return Storage.list(/\.info$/).filter(app => app.endsWith('.info')).map(app => Storage.readJSON(app,1) || { name: "DEAD: "+app.substr(1) })
|
|
|
|
.filter(app=>app.type=="app" || app.type=="clock" || !app.type)
|
|
|
|
.sort((a,b)=>{
|
|
|
|
var n=(0|a.sortorder)-(0|b.sortorder);
|
|
|
|
if (n) return n; // do sortorder first
|
|
|
|
if (a.name<b.name) return -1;
|
|
|
|
if (a.name>b.name) return 1;
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
const HEIGHT = g.getHeight();
|
|
|
|
const WIDTH = g.getWidth();
|
|
|
|
const HALF = WIDTH/2;
|
2020-04-08 16:42:47 +00:00
|
|
|
const ANIMATION_FRAME = 4;
|
2020-04-05 00:18:51 +00:00
|
|
|
const ANIMATION_STEP = HALF / ANIMATION_FRAME;
|
2020-04-02 18:36:19 +00:00
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function getPosition(index){
|
|
|
|
return (index*HALF);
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
let current_app = 0;
|
|
|
|
let target = 0;
|
|
|
|
let slideOffset = 0;
|
2020-04-02 18:36:19 +00:00
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
const back = {
|
|
|
|
name: 'BACK',
|
|
|
|
back: true
|
|
|
|
};
|
|
|
|
|
2020-04-08 16:42:47 +00:00
|
|
|
let icons = {};
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
const apps = [back].concat(getApps());
|
|
|
|
apps.push(back);
|
|
|
|
|
|
|
|
function noIcon(x, y, size){
|
|
|
|
const half = size/2;
|
|
|
|
g.setColor(1,1,1);
|
|
|
|
g.setFontAlign(-0,0);
|
|
|
|
const fontSize = Math.floor(size / 30 * 2);
|
|
|
|
g.setFont('6x8', fontSize);
|
|
|
|
if(fontSize) g.drawString('-?-', x+1.5, y);
|
|
|
|
g.drawRect(x-half, y-half, x+half, y+half);
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function drawIcons(offset){
|
|
|
|
apps.forEach((app, i) => {
|
|
|
|
const x = getPosition(i) + HALF - offset;
|
|
|
|
const y = HALF - (HALF*0.3);//-(HALF*0.7);
|
|
|
|
let diff = (x - HALF);
|
|
|
|
if(diff < 0) diff *=-1;
|
2020-04-08 16:42:47 +00:00
|
|
|
|
|
|
|
const dontRender = x+(HALF/2)<0 || x-(HALF/2)>120;
|
|
|
|
if(dontRender) {
|
|
|
|
delete icons[app.name];
|
|
|
|
return;
|
|
|
|
}
|
2020-04-05 00:12:04 +00:00
|
|
|
let size = 30;
|
|
|
|
if((diff*0.5) < size) size -= (diff*0.5);
|
|
|
|
else size = 0;
|
|
|
|
|
|
|
|
const scale = size / 30;
|
|
|
|
if(size){
|
|
|
|
let c = size / 30 * 2;
|
|
|
|
c = c -1;
|
|
|
|
if(c < 0) c = 0;
|
|
|
|
|
|
|
|
if(app.back){
|
|
|
|
g.setFont('6x8', 1);
|
|
|
|
g.setFontAlign(0, -1);
|
|
|
|
g.setColor(c,c,c);
|
|
|
|
g.drawString('Back', HALF, HALF);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// icon
|
2020-04-08 16:42:47 +00:00
|
|
|
|
|
|
|
const icon = app.icon ?
|
|
|
|
icons[app.name] ? icons[app.name] : Storage.read(app.icon)
|
|
|
|
: null;
|
2020-04-05 00:12:04 +00:00
|
|
|
if(icon){
|
2020-04-08 16:42:47 +00:00
|
|
|
icons[app.name] = icon;
|
2020-04-05 00:12:04 +00:00
|
|
|
try {
|
|
|
|
g.drawImage(icon, x-(scale*24), y-(scale*24), { scale: scale });
|
|
|
|
} catch(e){
|
|
|
|
noIcon(x, y, size);
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
noIcon(x, y, size);
|
|
|
|
}
|
|
|
|
//text
|
|
|
|
g.setFont('6x8', 1);
|
|
|
|
g.setFontAlign(0, -1);
|
|
|
|
g.setColor(c,c,c);
|
|
|
|
g.drawString(app.name, HALF, HEIGHT - (HALF*0.7));
|
|
|
|
|
|
|
|
const type = app.type ? app.type : 'App';
|
|
|
|
const version = app.version ? app.version : '0.00';
|
|
|
|
const info = type+' v'+version;
|
|
|
|
g.setFontAlign(0,1);
|
|
|
|
g.setFont('4x6', 0.25);
|
|
|
|
g.setColor(c,c,c);
|
|
|
|
g.drawString(info, HALF, 110, { scale: scale });
|
|
|
|
}
|
|
|
|
});
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function draw(ignoreLoop){
|
2020-04-08 16:42:47 +00:00
|
|
|
g.setColor(0,0,0);
|
|
|
|
g.fillRect(0,0,WIDTH,HEIGHT);
|
2020-04-05 00:12:04 +00:00
|
|
|
drawIcons(slideOffset);
|
|
|
|
g.flip();
|
|
|
|
if(slideOffset == target) return;
|
|
|
|
if(slideOffset < target) slideOffset+= ANIMATION_STEP;
|
|
|
|
else if(slideOffset > target) slideOffset -= ANIMATION_STEP;
|
2020-04-05 00:18:51 +00:00
|
|
|
if(!ignoreLoop) draw();
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function animateTo(index){
|
|
|
|
target = getPosition(index);
|
|
|
|
draw();
|
|
|
|
}
|
|
|
|
function goTo(index){
|
|
|
|
current_app = index;
|
|
|
|
target = getPosition(index);
|
|
|
|
slideOffset = target;
|
|
|
|
draw(true);
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
goTo(1);
|
|
|
|
|
|
|
|
function prev(){
|
|
|
|
if(current_app == 0) goTo(apps.length-1);
|
|
|
|
current_app -= 1;
|
|
|
|
if(current_app < 0) current_app = 0;
|
|
|
|
animateTo(current_app);
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function next(){
|
|
|
|
if(current_app == apps.length-1) goTo(0);
|
|
|
|
current_app += 1;
|
|
|
|
if(current_app > apps.length-1) current_app = apps.length-1;
|
|
|
|
animateTo(current_app);
|
|
|
|
}
|
2020-04-02 18:36:19 +00:00
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
function run() {
|
|
|
|
const app = apps[current_app];
|
|
|
|
if(app.back) return load();
|
|
|
|
if (Storage.read(app.src)===undefined) {
|
|
|
|
E.showMessage("App Source\nNot found");
|
|
|
|
setTimeout(draw, 2000);
|
|
|
|
} else {
|
|
|
|
Bangle.setLCDMode();
|
2020-04-02 18:36:19 +00:00
|
|
|
g.clear();
|
2020-04-05 00:12:04 +00:00
|
|
|
g.flip();
|
|
|
|
E.showMessage("Loading...");
|
|
|
|
load(app.src);
|
2020-04-02 18:36:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
setWatch(prev, BTN1, { repeat: true });
|
|
|
|
setWatch(next, BTN3, { repeat: true });
|
2020-04-02 18:36:19 +00:00
|
|
|
setWatch(run, BTN2, {repeat:true,edge:"falling"});
|
2020-04-02 20:29:37 +00:00
|
|
|
|
|
|
|
// Screen event
|
|
|
|
Bangle.on('touch', function(button){
|
|
|
|
switch(button){
|
|
|
|
case 1:
|
|
|
|
prev();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
next();
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
run();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Bangle.on('swipe', dir => {
|
|
|
|
if(dir == 1) prev();
|
|
|
|
else next();
|
2020-04-03 21:37:00 +00:00
|
|
|
});
|
|
|
|
|
2020-04-05 00:12:04 +00:00
|
|
|
// close launcher when lcd is off
|
|
|
|
Bangle.on('lcdPower', on => {
|
2020-04-03 21:37:00 +00:00
|
|
|
if(!on) return load();
|
2020-04-02 20:29:37 +00:00
|
|
|
});
|