diff --git a/apps/iconlaunch/ChangeLog b/apps/iconlaunch/ChangeLog index fcd7c9194..858d13b80 100644 --- a/apps/iconlaunch/ChangeLog +++ b/apps/iconlaunch/ChangeLog @@ -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 diff --git a/apps/iconlaunch/README.md b/apps/iconlaunch/README.md index 0d36fdeb4..0b67494ce 100644 --- a/apps/iconlaunch/README.md +++ b/apps/iconlaunch/README.md @@ -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. diff --git a/apps/iconlaunch/app.js b/apps/iconlaunch/app.js index 97f7f0ac1..fd58176db 100644 --- a/apps/iconlaunch/app.js +++ b/apps/iconlaunch/app.js @@ -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); + } } diff --git a/apps/iconlaunch/metadata.json b/apps/iconlaunch/metadata.json index f1c34cf3d..82d2e7578 100644 --- a/apps/iconlaunch/metadata.json +++ b/apps/iconlaunch/metadata.json @@ -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", diff --git a/apps/iconlaunch/settings.js b/apps/iconlaunch/settings.js index bd1a4a597..449a1c096 100644 --- a/apps/iconlaunch/settings.js +++ b/apps/iconlaunch/settings.js @@ -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);