Merge pull request #2171 from halemmerich/iconlaunch

iconlaunch - Directly eval apps instead of loading them
master
Gordon Williams 2022-10-14 08:25:21 +01:00 committed by GitHub
commit dbbedd6d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 61 deletions

View File

@ -2,3 +2,4 @@
0.02: implemented "direct launch" and "one click exit" settings
0.03: Use default Bangle formatter for booleans
0.04: Support new fast app switching
0.05: Allow to directly eval apps instead of loading

View File

@ -10,3 +10,7 @@ This launcher shows 9 apps per screen, making it much faster to navigate versus
## Technical note
The app uses `E.showScroller`'s code in the app but not the function itself because `E.showScroller` doesn't report the position of a press to the select function.
### Fastload option
Fastload clears up the memory used by the launcher and directly evals the code of the app to load. This means if widgets are loaded (fullscreen option) it is possible that widgets stay loaded in apps not expecting that and the widgets may draw over the app.

View File

@ -1,31 +1,21 @@
{
const s = require("Storage");
const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,oneClickExit:false };
function returnToClock() {
Bangle.setUI();
setTimeout(eval,0,s.read(".bootcde"));
}
if( settings.oneClickExit)
setWatch(returnToClock, BTN1);
if (!settings.fullscreen) {
if (!global.WIDGETS) Bangle.loadWidgets();
Bangle.loadWidgets();
Bangle.drawWidgets();
}
var apps = s
.list(/\.info$/)
.map((app) => {
var a = s.readJSON(app, 1);
var a = s.readJSON(app, 1);
return (
a && {
name: a.name,
type: a.type,
icon: a.icon,
sortorder: a.sortorder,
src: a.src,
name: a.name,
type: a.type,
icon: a.icon,
sortorder: a.sortorder,
src: a.src,
}
);
})
@ -38,34 +28,29 @@
);
apps.sort((a, b) => {
var n = (0 | a.sortorder) - (0 | b.sortorder);
if (n) return n; // do sortorder first
if (n) return n;
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
});
apps.forEach((app) => {
if (app.icon) app.icon = s.read(app.icon); // should just be a link to a memory area
if (app.icon) app.icon = s.read(app.icon);
});
let scroll = 0;
let selectedItem = -1;
const R = Bangle.appRect;
const iconSize = 48;
const appsN = Math.floor(R.w / iconSize);
const whitespace = (R.w - appsN * iconSize) / (appsN + 1);
const itemSize = iconSize + whitespace;
function drawItem(itemI, r) {
let drawItem = function(itemI, r) {
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
let x = 0;
for (let i = itemI * appsN; i < appsN * (itemI + 1); i++) {
if (!apps[i]) break;
x += whitespace;
if (!apps[i].icon) {
g.setFontAlign(0,0,0).setFont("12x20:2").drawString("?", x + r.x+iconSize/2, r.y + iconSize/2);
g.setFontAlign(0, 0, 0).setFont("12x20:2").drawString("?", x + r.x + iconSize / 2, r.y + iconSize / 2);
} else {
g.drawImage(apps[i].icon, x + r.x, r.y);
}
@ -80,9 +65,8 @@
x += iconSize;
}
drawText(itemI);
}
function drawItemAuto(i) {
};
let drawItemAuto = function(i) {
var y = idxToY(i);
g.reset().setClipRect(R.x, y, R.x2, y + itemSize);
drawItem(i, {
@ -92,11 +76,9 @@
h: itemSize
});
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}
};
let lastIsDown = false;
function drawText(i) {
let drawText = function(i) {
const selectedApp = apps[selectedItem];
const idy = (selectedItem - (selectedItem % 3)) / 3;
if (!selectedApp || i != idy) return;
@ -111,14 +93,13 @@
appY + rect.height / 2
);
g.drawString(selectedApp.name, R.w / 2, appY);
}
function selectItem(id, e) {
};
let selectItem = function(id, e) {
const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1);
const appId = id * appsN + iconN;
if( settings.direct && apps[appId])
{
load(apps[appId].src);
loadApp(apps[appId].src);
return;
}
if (appId == selectedItem && apps[appId]) {
@ -126,42 +107,36 @@
if (!app.src || s.read(app.src) === undefined) {
E.showMessage( /*LANG*/ "App Source\nNot found");
} else {
load(app.src);
loadApp(app.src);
}
}
selectedItem = appId;
drawItems();
}
function idxToY(i) {
};
let idxToY = function(i) {
return i * itemSize + R.y - (scroll & ~1);
}
function YtoIdx(y) {
};
let YtoIdx = function(y) {
return Math.floor((y + (scroll & ~1) - R.y) / itemSize);
}
function drawItems() {
};
let drawItems = function() {
g.reset().clearRect(R.x, R.y, R.x2, R.y2);
g.setClipRect(R.x, R.y, R.x2, R.y2);
var a = YtoIdx(R.y);
var b = Math.min(YtoIdx(R.y2), 99);
for (var i = a; i <= b; i++)
drawItem(i, {
x: R.x,
y: idxToY(i),
w: R.w,
h: itemSize,
});
x: R.x,
y: idxToY(i),
w: R.w,
h: itemSize,
});
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}
};
drawItems();
g.flip();
const itemsN = Math.ceil(apps.length / appsN);
function onDrag(e){
let onDrag = function(e) {
g.setColor(g.theme.fg);
g.setBgColor(g.theme.bg);
let dy = e.dy;
@ -190,7 +165,6 @@
y += itemSize;
}
} else {
// d>0
g.setClipRect(R.x, R.y, R.x2, R.y + dy);
let i = YtoIdx(R.y + dy);
let y = idxToY(i);
@ -206,8 +180,7 @@
}
}
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}
};
Bangle.setUI({
mode: "custom",
drag: onDrag,
@ -217,4 +190,36 @@
selectItem(i, e);
},
});
const returnToClock = function() {
loadApp(".bootcde");
};
let watch;
let loadApp;
if (settings.fastload){
loadApp = function(name) {
Bangle.setUI();
if (watch) clearWatch(watch);
apps = [];
delete drawItemAuto;
delete drawText;
delete selectItem;
delete onDrag;
delete drawItems;
delete drawItem;
delete returnToClock;
delete idxToY;
delete YtoIdx;
delete settings;
setTimeout(eval, 0, s.read(name));
return;
};
} else {
loadApp = function(name) {
load(name);
}
}
if (settings.oneClickExit) {
watch = setWatch(returnToClock, BTN1);
}
}

View File

@ -2,7 +2,7 @@
"id": "iconlaunch",
"name": "Icon Launcher",
"shortName" : "Icon launcher",
"version": "0.04",
"version": "0.05",
"icon": "app.png",
"description": "A launcher inspired by smartphones, with an icon-only scrollable menu.",
"tags": "tool,system,launcher",

View File

@ -28,6 +28,10 @@
/*LANG*/"One click exit": {
value: settings.oneClickExit == true,
onchange: (m) => { save("oneClickExit", m) }
},
/*LANG*/"Fastload": {
value: settings.fastload == true,
onchange: (m) => { save("fastload", m) }
}
};
E.showMenu(appMenu);