Merge pull request #2156 from halemmerich/unload

Fast switch for imageclock and iconlaunch
pull/2158/head
Gordon Williams 2022-09-30 10:10:04 +01:00 committed by GitHub
commit a456f4ff62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 928 additions and 851 deletions

View File

@ -1,3 +1,4 @@
0.01: Initial release 0.01: Initial release
0.02: implemented "direct launch" and "one click exit" settings 0.02: implemented "direct launch" and "one click exit" settings
0.03: Use default Bangle formatter for booleans 0.03: Use default Bangle formatter for booleans
0.04: Support new fast app switching

View File

@ -1,163 +1,167 @@
const s = require("Storage"); {
const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,oneClickExit:false }; const s = require("Storage");
const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,oneClickExit:false };
if( settings.oneClickExit) function returnToClock() {
setWatch(_=> load(), BTN1); Bangle.setUI();
setTimeout(eval,0,s.read(".bootcde"));
}
if (!settings.fullscreen) { if( settings.oneClickExit)
Bangle.loadWidgets(); setWatch(returnToClock, BTN1);
Bangle.drawWidgets();
}
var apps = s if (!settings.fullscreen) {
.list(/\.info$/) if (!global.WIDGETS) Bangle.loadWidgets();
.map((app) => { Bangle.drawWidgets();
var a = s.readJSON(app, 1); }
return (
a && {
name: a.name,
type: a.type,
icon: a.icon,
sortorder: a.sortorder,
src: a.src,
}
);
})
.filter(
(app) =>
app &&
(app.type == "app" ||
(app.type == "clock" && settings.showClocks) ||
!app.type)
);
apps.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;
});
apps.forEach((app) => {
if (app.icon) app.icon = s.read(app.icon); // should just be a link to a memory area
});
let scroll = 0; var apps = s
let selectedItem = -1; .list(/\.info$/)
const R = Bangle.appRect; .map((app) => {
var a = s.readJSON(app, 1);
const iconSize = 48; return (
a && {
const appsN = Math.floor(R.w / iconSize); name: a.name,
const whitespace = (R.w - appsN * iconSize) / (appsN + 1); type: a.type,
icon: a.icon,
const itemSize = iconSize + whitespace; sortorder: a.sortorder,
src: a.src,
function drawItem(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);
} else {
g.drawImage(apps[i].icon, x + r.x, r.y);
}
if (selectedItem == i) {
g.drawRect(
x + r.x - 1,
r.y - 1,
x + r.x + iconSize + 1,
r.y + iconSize + 1
); );
} })
x += iconSize; .filter(
} (app) =>
drawText(itemI); app &&
} (app.type == "app" ||
(app.type == "clock" && settings.showClocks) ||
function drawItemAuto(i) { !app.type)
var y = idxToY(i); );
g.reset().setClipRect(R.x, y, R.x2, y + itemSize); apps.sort((a, b) => {
drawItem(i, { var n = (0 | a.sortorder) - (0 | b.sortorder);
x: R.x, if (n) return n; // do sortorder first
y: y, if (a.name < b.name) return -1;
w: R.w, if (a.name > b.name) return 1;
h: itemSize return 0;
});
apps.forEach((app) => {
if (app.icon) app.icon = s.read(app.icon); // should just be a link to a memory area
}); });
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}
let lastIsDown = false; let scroll = 0;
let selectedItem = -1;
const R = Bangle.appRect;
function drawText(i) { const iconSize = 48;
const selectedApp = apps[selectedItem];
const idy = (selectedItem - (selectedItem % 3)) / 3;
if (!selectedApp || i != idy) return;
const appY = idxToY(idy) + iconSize / 2;
g.setFontAlign(0, 0, 0);
g.setFont("12x20");
const rect = g.stringMetrics(selectedApp.name);
g.clearRect(
R.w / 2 - rect.width / 2,
appY - rect.height / 2,
R.w / 2 + rect.width / 2,
appY + rect.height / 2
);
g.drawString(selectedApp.name, R.w / 2, appY);
}
function selectItem(id, e) { const appsN = Math.floor(R.w / iconSize);
const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1); const whitespace = (R.w - appsN * iconSize) / (appsN + 1);
const appId = id * appsN + iconN;
if( settings.direct && apps[appId]) const itemSize = iconSize + whitespace;
{
load(apps[appId].src); function drawItem(itemI, r) {
return; g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
} let x = 0;
if (appId == selectedItem && apps[appId]) { for (let i = itemI * appsN; i < appsN * (itemI + 1); i++) {
const app = apps[appId]; if (!apps[i]) break;
if (!app.src || s.read(app.src) === undefined) { x += whitespace;
E.showMessage( /*LANG*/ "App Source\nNot found"); if (!apps[i].icon) {
} else { g.setFontAlign(0,0,0).setFont("12x20:2").drawString("?", x + r.x+iconSize/2, r.y + iconSize/2);
load(app.src); } else {
g.drawImage(apps[i].icon, x + r.x, r.y);
}
if (selectedItem == i) {
g.drawRect(
x + r.x - 1,
r.y - 1,
x + r.x + iconSize + 1,
r.y + iconSize + 1
);
}
x += iconSize;
} }
drawText(itemI);
} }
selectedItem = appId;
drawItems();
}
function idxToY(i) { function drawItemAuto(i) {
return i * itemSize + R.y - (scroll & ~1); var y = idxToY(i);
} g.reset().setClipRect(R.x, y, R.x2, y + itemSize);
function YtoIdx(y) {
return Math.floor((y + (scroll & ~1) - R.y) / itemSize);
}
function drawItems() {
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, { drawItem(i, {
x: R.x, x: R.x,
y: idxToY(i), y: y,
w: R.w, w: R.w,
h: itemSize, h: itemSize
}); });
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1); g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
} }
drawItems(); let lastIsDown = false;
g.flip();
const itemsN = Math.ceil(apps.length / appsN); function drawText(i) {
const selectedApp = apps[selectedItem];
const idy = (selectedItem - (selectedItem % 3)) / 3;
if (!selectedApp || i != idy) return;
const appY = idxToY(idy) + iconSize / 2;
g.setFontAlign(0, 0, 0);
g.setFont("12x20");
const rect = g.stringMetrics(selectedApp.name);
g.clearRect(
R.w / 2 - rect.width / 2,
appY - rect.height / 2,
R.w / 2 + rect.width / 2,
appY + rect.height / 2
);
g.drawString(selectedApp.name, R.w / 2, appY);
}
Bangle.setUI({ function selectItem(id, e) {
mode: "custom", const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1);
drag: (e) => { const appId = id * appsN + iconN;
if( settings.direct && apps[appId])
{
load(apps[appId].src);
return;
}
if (appId == selectedItem && apps[appId]) {
const app = apps[appId];
if (!app.src || s.read(app.src) === undefined) {
E.showMessage( /*LANG*/ "App Source\nNot found");
} else {
load(app.src);
}
}
selectedItem = appId;
drawItems();
}
function idxToY(i) {
return i * itemSize + R.y - (scroll & ~1);
}
function YtoIdx(y) {
return Math.floor((y + (scroll & ~1) - R.y) / itemSize);
}
function drawItems() {
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,
});
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}
drawItems();
g.flip();
const itemsN = Math.ceil(apps.length / appsN);
function onDrag(e){
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.setBgColor(g.theme.bg); g.setBgColor(g.theme.bg);
let dy = e.dy; let dy = e.dy;
@ -202,10 +206,15 @@ Bangle.setUI({
} }
} }
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1); g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
}, }
touch: (_, e) => {
if (e.y < R.y - 4) return; Bangle.setUI({
var i = YtoIdx(e.y); mode: "custom",
selectItem(i, e); drag: onDrag,
}, touch: (_, e) => {
}); if (e.y < R.y - 4) return;
var i = YtoIdx(e.y);
selectItem(i, e);
},
});
}

View File

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

View File

@ -8,3 +8,4 @@
0.07: Allow wrapping drawing in timeouts to get faster reactions 0.07: Allow wrapping drawing in timeouts to get faster reactions
Show/Hide widgets with swipe up or down Show/Hide widgets with swipe up or down
0.08: Use default Bangle formatter for booleans 0.08: Use default Bangle formatter for booleans
0.09: Support new fast app switching

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"id": "imageclock", "id": "imageclock",
"name": "Imageclock", "name": "Imageclock",
"shortName": "Imageclock", "shortName": "Imageclock",
"version": "0.08", "version": "0.09",
"type": "clock", "type": "clock",
"description": "BETA!!! File formats still subject to change --- This app is a highly customizable watchface. To use it, you need to select a watchface. You can build the watchfaces yourself without programming anything. All you need to do is write some json and create image files.", "description": "BETA!!! File formats still subject to change --- This app is a highly customizable watchface. To use it, you need to select a watchface. You can build the watchfaces yourself without programming anything. All you need to do is write some json and create image files.",
"icon": "app.png", "icon": "app.png",