Merge pull request #2645 from thyttan/quicklaunch-infinite

[quicklaunch] Implement stackable extension screens
master
Gordon Williams 2023-03-13 08:49:44 +00:00 committed by GitHub
commit 6a27d7bcb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 219 deletions

View File

@ -10,3 +10,6 @@
0.10: Extend the functionality via a quicklaunch.app.js file that can be launched
with quicklaunch itself.
0.11: Add hints to the extension app. Tweak remove function.
0.12: Stackable extension screens. After updating, please visit the quicklaunch
settings page to prompt an automatic update of the quicklaunch.json settings file with
new key names.

View File

@ -1,3 +1,24 @@
Tap or swipe left/right/up/down on your clock face to launch up to five apps of your choice. The Quick Launch Extension (included) can be chosen as one of the apps, in turn providing fast access to up to five additional apps. Configurations can be accessed through Settings->Apps.
**PLEASE NOTE: With v0.12 of Quick Launch the keys of the settings file have been changed. Please just visit Settings->Apps->Quick Launch to prompt an automatic update. Quick Launch will not be responsive until this has been done. This is a consequence of how the new stackable extension screens are implemented.**
Tap or swipe left/right/up/down on your clock face to launch up to five apps of your choice. The extension (included) can be chosen as one of the apps, in turn providing fast access to up to five additional apps per extension screen - which can be stacked indefinitely. Configurations can be accessed through Settings->Apps.
Below is extension screens where current apps have been set like so:
- left swipe is "PA Remote",
- right swipe is "Remote for Spotify" and
- down swipe is another extension screen where new apps are accessible.
![](screenshot0.png)
*Extension screen.*
![](screenshot1.png)
*Extension screen when Fastload Utils is present.*
## Contributors
frigis1 (Creator),
halemmerich,
thyttan,
glemco.

View File

@ -8,44 +8,58 @@
storage.write("quicklaunch.json", settings);
};
let leaveTrace = function(trace) {
settings.trace = trace;
storage.writeJSON("quicklaunch.json", settings);
return trace;
};
let trace = settings.trace;
let touchHandler = (_,e) => {
let R = Bangle.appRect;
if (e.x < R.x || e.x > R.x2 || e.y < R.y || e.y > R.y2 ) return;
if (settings.exttapapp.src){ if (settings.exttapapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.exttapapp.src)) reset("exttapapp"); else load(settings.exttapapp.src); }
trace = leaveTrace(trace+"t"); // t=tap.
if (settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
};
let swipeHandler = (lr,ud) => {
if (lr == -1 && settings.extleftapp && settings.extleftapp.src){ if (settings.extleftapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.extleftapp.src)) reset("extleftapp"); else load(settings.extleftapp.src); }
if (lr == 1 && settings.extrightapp && settings.extrightapp.src){ if (settings.extrightapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.extrightapp.src)) reset("extrightapp"); else load(settings.extrightapp.src); }
if (ud == -1 && settings.extupapp && settings.extupapp.src){ if (settings.extupapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.extupapp.src)) reset("extupapp"); else load(settings.extupapp.src); }
if (ud == 1 && settings.extdownapp && settings.extdownapp.src){ if (settings.extdownapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.extdownapp.src)) reset("extdownapp"); else load(settings.extdownapp.src); }
if (lr == -1) trace = leaveTrace(trace+"l"); // l=left,
if (lr == 1) trace = leaveTrace(trace+"r"); // r=right,
if (ud == -1) trace = leaveTrace(trace+"u"); // u=up,
if (ud == 1) trace = leaveTrace(trace+"d"); // d=down.
if (lr == -1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (lr == 1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (ud == -1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (ud == 1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
};
let removeUI = ()=>{if (timeoutToClock) clearTimeout(timeoutToClock);}
Bangle.setUI({
mode: "custom",
touch: touchHandler,
swipe : swipeHandler,
remove: removeUI // Compatability with Fastload Utils.
remove: ()=>{if (timeoutToClock) clearTimeout(timeoutToClock);} // Compatibility with Fastload Utils.
});
g.clearRect(Bangle.appRect);
Bangle.loadWidgets(); // Compatability with Fastload Utils.
"Bangle.loadWidgets()"; // Hack: Fool Fastload Utils that we call Bangle.loadWidgets(). This way we get the fastest possibe loading in whichever environment we find ourselves.
// taken from Icon Launcher with some alterations
let timeoutToClock;
const updateTimeoutToClock = function(){
let time = 1000; // milliseconds
let time = 1500; // milliseconds
if (timeoutToClock) clearTimeout(timeoutToClock);
timeoutToClock = setTimeout(load,time);
};
updateTimeoutToClock();
let R = Bangle.appRect;
// Draw app hints
g.setFont("Vector", 11)
.setFontAlign(0,1,0).drawString(settings.extupapp.name, R.x+R.w/2, R.y2)
.setFontAlign(0,1,1).drawString(settings.extrightapp.name, R.x, R.y+R.h/2)
.setFontAlign(0,-1,0).drawString(settings.extdownapp.name, R.x+R.w/2, R.y)
.setFontAlign(0,1,3).drawString(settings.extleftapp.name, R.x2, R.y+R.h/2);
.setFontAlign(0,1,3).drawString(settings[trace+"lapp"].name, R.x2, R.y+R.h/2)
.setFontAlign(0,1,1).drawString(settings[trace+"rapp"].name, R.x, R.y+R.h/2)
.setFontAlign(0,1,0).drawString(settings[trace+"uapp"].name, R.x+R.w/2, R.y2)
.setFontAlign(0,-1,0).drawString(settings[trace+"dapp"].name, R.x+R.w/2, R.y)
.setFontAlign(0,0,0).drawString(settings[trace+"tapp"].name, R.x+R.w/2, R.y+R.h/2);
}

View File

@ -8,21 +8,33 @@
storage.write("quicklaunch.json", settings);
};
let leaveTrace = function(trace) {
settings.trace = trace;
storage.writeJSON("quicklaunch.json", settings);
return trace;
};
let trace;
Bangle.on("touch", (_,e) => {
if (!Bangle.CLOCK) return;
if (Bangle.CLKINFO_FOCUS) return;
let R = Bangle.appRect;
if (e.x < R.x || e.x > R.x2 || e.y < R.y || e.y > R.y2 ) return;
if (settings.tapapp.src){ if (settings.tapapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.tapapp.src)) reset("tapapp"); else load(settings.tapapp.src); }
trace = leaveTrace("t"); // t=tap
if (settings[trace].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
});
Bangle.on("swipe", (lr,ud) => {
if (!Bangle.CLOCK) return;
if (Bangle.CLKINFO_FOCUS) return;
if (lr == -1 && settings.leftapp && settings.leftapp.src){ if (settings.leftapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.leftapp.src)) reset("leftapp"); else load(settings.leftapp.src); }
if (lr == 1 && settings.rightapp && settings.rightapp.src){ if (settings.rightapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.rightapp.src)) reset("rightapp"); else load(settings.rightapp.src); }
if (ud == -1 && settings.upapp && settings.upapp.src){ if (settings.upapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.upapp.src)) reset("upapp"); else load(settings.upapp.src); }
if (ud == 1 && settings.downapp && settings.downapp.src){ if (settings.downapp.name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings.downapp.src)) reset("downapp"); else load(settings.downapp.src); }
if (lr == -1) trace = leaveTrace("l"); // l=left,
if (lr == 1) trace = leaveTrace("r"); // r=right,
if (ud == -1) trace = leaveTrace("u"); // u=up,
if (ud == 1) trace = leaveTrace("d"); // d=down.
if (lr == -1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (lr == 1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (ud == -1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
if (ud == 1 && settings[trace+"app"] && settings[trace+"app"].src){ if (settings[trace+"app"].name == "Show Launcher") Bangle.showLauncher(); else if (!storage.read(settings[trace+"app"].src)) reset(trace+"app"); else load(settings[trace+"app"].src); }
});
}

View File

@ -2,7 +2,7 @@
"id": "quicklaunch",
"name": "Quick Launch",
"icon": "app.png",
"version": "0.11",
"version": "0.12",
"description": "Tap or swipe left/right/up/down on your clock face to launch up to five apps of your choice. Configurations can be accessed through Settings->Apps.",
"type": "bootloader",
"tags": "tools, system",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -2,10 +2,38 @@
var storage = require("Storage");
var settings = Object.assign(storage.readJSON("quicklaunch.json", true) || {});
for (let c of ["leftapp","rightapp","upapp","downapp","tapapp","extleftapp","extrightapp","extupapp","extdownapp","exttapapp"]){
if (!settings[c]) settings[c] = {"name":"(none)"};
// Add default settings if they haven't been configured before.
for (let c of ["lapp","rapp","uapp","dapp","tapp"]){ // l=left, r=right, u=up, d=down, t=tap.
if (!settings[c]) settings[c] = {"name":""};
}
// Convert settings object from before v0.12 to v0.12.
for (let c of ["leftapp","rightapp","upapp","downapp","tapapp"]){
if (settings[c]) {
let cNew = c.substring(0,1)+"app";
settings[cNew] = settings[c];
delete settings[c];
if (settings[cNew].name=="(none)") settings[cNew].name = "";
if (settings[cNew].name=="Quick Launch Extension"){
settings[cNew].name = "Extension";
for (let d of ["extleftapp","extrightapp","extupapp","extdownapp","exttapapp"]){
if (settings[d]) {
let dNew = cNew.substring(0,1)+d.substring(3,4)+"app";
settings[dNew] = settings[d];
delete settings[d];
if (settings[dNew].name=="(none)") settings[dNew].name = "";
}
}
}
storage.writeJSON("quicklaunch.json",settings);
}
}
for (let d of ["extleftapp","extrightapp","extupapp","extdownapp","exttapapp"]){
if (settings[d]) delete settings[d];
}
var apps = storage.list(/\.info$/).map(app=>{var a=storage.readJSON(app,1);return a&&{name:a.name,type:a.type,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="launch" || app.type=="clock" || !app.type));
// Add psuedo app to trigger Bangle.showLauncher later
@ -17,12 +45,13 @@ apps.push({
});
// Add the Quick Launch extension app
apps.push({
"name": "Quick Launch Extension",
let extension = {
"name": "Extension",
"type": "app",
"sortorder": -11,
"src": "quicklaunch.app.js"
});
};
apps.push(extension);
apps.sort((a,b)=>{
var n=(0|a.sortorder)-(0|b.sortorder);
@ -32,9 +61,28 @@ apps.sort((a,b)=>{
return 0;
});
function findPath(key) {return key.substring(0, key.length-3);}
function save(key, value) {
let path = findPath(key);
// If changing from extension app (to something else) remove downstream settings entries.
if (settings[key].name == extension.name && value.name != extension.name) {
for (let c of [path+"lapp", path+"rapp", path+"uapp", path+"dapp", path+"tapp"]) {
delete settings[c];
}
}
// If changing to extension app (from something else) add downstream settings entries.
if (value.name == extension.name && settings[key].name != extension.name) {
for (let c of [path+"lapp", path+"rapp", path+"uapp", path+"dapp", path+"tapp"]) {
settings[c] = {"name":""};
storage.write("quicklaunch.json",settings);
}
}
// Now change the setting on the current level in the path.
settings[key] = value;
storage.write("quicklaunch.json",settings);
storage.writeJSON("quicklaunch.json",settings);
}
function showMainMenu() {
@ -44,203 +92,43 @@ function showMainMenu() {
"< Back" : ()=>{load();}
};
//List all selected apps
mainmenu["Left: "+settings.leftapp.name] = function() { E.showMenu(leftmenu); };
mainmenu["Right: "+settings.rightapp.name] = function() { E.showMenu(rightmenu); };
mainmenu["Up: "+settings.upapp.name] = function() { E.showMenu(upmenu); };
mainmenu["Down: "+settings.downapp.name] = function() { E.showMenu(downmenu); };
mainmenu["Tap: "+settings.tapapp.name] = function() { E.showMenu(tapmenu); };
mainmenu["Extend Quick Launch"] = showExtMenu;
// List all selected apps.
for (let key of Object.keys(settings)) {
if (key == "trace") continue;
let keyCurrent = key;
let entry = findPath(key).toUpperCase();
if (entry=="L") entry = "Left";
if (entry=="R") entry = "Right";
if (entry=="U") entry = "Up";
if (entry=="D") entry = "Down";
if (entry=="T") entry = "Tap";
// If no app is selected the name is an empty string, but we want to display "(none)".
let appName = settings[key].name==""?"(none)":settings[key].name;
mainmenu[entry+ ": "+appName] = function() {showSubMenu(keyCurrent);};
}
return E.showMenu(mainmenu);
}
//Left swipe menu
var leftmenu = {
"" : { "title" : "Left Swipe" },
"< Back" : showMainMenu
};
leftmenu["(none)"] = function() {
save("leftapp", {"name":"(none)"});
showMainMenu();
};
apps.forEach((a)=>{
leftmenu[a.name] = function() {
save("leftapp", a);
showMainMenu();
};
});
//Right swipe menu
var rightmenu = {
"" : { "title" : "Right Swipe" },
"< Back" : showMainMenu
};
rightmenu["(none)"] = function() {
save("rightapp", {"name":"(none)"});
showMainMenu();
};
apps.forEach((a)=>{
rightmenu[a.name] = function() {
save("rightapp", a);
showMainMenu();
};
});
//Up swipe menu
var upmenu = {
"" : { "title" : "Up Swipe" },
"< Back" : showMainMenu
};
upmenu["(none)"] = function() {
save("upapp", {"name":"(none)"});
showMainMenu();
};
apps.forEach((a)=>{
upmenu[a.name] = function() {
save("upapp", a);
showMainMenu();
};
});
//Down swipe menu
var downmenu = {
"" : { "title" : "Down Swipe" },
"< Back" : showMainMenu
};
downmenu["(none)"] = function() {
save("downapp", {"name":"(none)"});
showMainMenu();
};
apps.forEach((a)=>{
downmenu[a.name] = function() {
save("downapp", a);
showMainMenu();
};
});
//Tap menu
var tapmenu = {
"" : { "title" : "Tap" },
"< Back" : showMainMenu
};
tapmenu["(none)"] = function() {
save("tapapp", {"name":"(none)"});
showMainMenu();
};
apps.forEach((a)=>{
tapmenu[a.name] = function() {
save("tapapp", a);
showMainMenu();
};
});
function showExtMenu() {
// Extend Quick Launch menu
var extmenu = {
"" : { "title" : "Extend Quick Launch" },
"< Back" : ()=>{showMainMenu();}
function showSubMenu(key) {
var submenu = {
"" : { "title" : "Path: "+findPath(key).toUpperCase()},
"< Back" : showMainMenu
};
submenu["(none)"] = function() {
save(key, {"name":""});
showMainMenu();
};
apps.forEach((a)=>{
submenu[a.name] = function() {
save(key, a);
showMainMenu();
};
});
//List all selected apps
extmenu["Left: "+settings.extleftapp.name] = function() { E.showMenu(extleftmenu); };
extmenu["Right: "+settings.extrightapp.name] = function() { E.showMenu(extrightmenu); };
extmenu["Up: "+settings.extupapp.name] = function() { E.showMenu(extupmenu); };
extmenu["Down: "+settings.extdownapp.name] = function() { E.showMenu(extdownmenu); };
extmenu["Tap: "+settings.exttapapp.name] = function() { E.showMenu(exttapmenu); };
return E.showMenu(extmenu);
return E.showMenu(submenu);
}
//Extension Left swipe menu
var extleftmenu = {
"" : { "title" : "Extension Left Swipe" },
"< Back" : showExtMenu
};
extleftmenu["(none)"] = function() {
save("extleftapp", {"name":"(none)"});
showExtMenu();
};
apps.forEach((a)=>{
extleftmenu[a.name] = function() {
save("extleftapp", a);
showExtMenu();
};
});
//Extension Right swipe menu
var extrightmenu = {
"" : { "title" : "Extension Right Swipe" },
"< Back" : showExtMenu
};
extrightmenu["(none)"] = function() {
save("extrightapp", {"name":"(none)"});
showExtMenu();
};
apps.forEach((a)=>{
extrightmenu[a.name] = function() {
save("extrightapp", a);
showExtMenu();
};
});
//Extension Up swipe menu
var extupmenu = {
"" : { "title" : "Extension Up Swipe" },
"< Back" : showExtMenu
};
extupmenu["(none)"] = function() {
save("extupapp", {"name":"(none)"});
showExtMenu();
};
apps.forEach((a)=>{
extupmenu[a.name] = function() {
save("extupapp", a);
showExtMenu();
};
});
//Extension Down swipe menu
var extdownmenu = {
"" : { "title" : "Extension Down Swipe" },
"< Back" : showExtMenu
};
downmenu["(none)"] = function() {
save("extdownapp", {"name":"(none)"});
showExtMenu();
};
apps.forEach((a)=>{
extdownmenu[a.name] = function() {
save("extdownapp", a);
showExtMenu();
};
});
//Extension Tap menu
var exttapmenu = {
"" : { "title" : "Extension Tap" },
"< Back" : showExtMenu
};
exttapmenu["(none)"] = function() {
save("exttapapp", {"name":"(none)"});
showExtMenu();
};
apps.forEach((a)=>{
exttapmenu[a.name] = function() {
save("exttapapp", a);
showExtMenu();
};
});
showMainMenu();
})