mirror of https://github.com/espruino/BangleApps
Ratchet Launcher: Initial version
parent
9dc1678e2a
commit
8dc3e8f8fc
|
@ -0,0 +1 @@
|
|||
0.01: Initial release
|
|
@ -0,0 +1,15 @@
|
|||
# Rachet Launcher
|
||||
|
||||
Ratchet Launcher is a fork of the default Launcher with modified user interaction. Instead of free scrolling, apps are selected by swiping up and down, but in discrete "ticks", just like in the settings menus.
|
||||
|
||||
**WARNING: Untested on Bangle.js v1! Please test and give feedback.**
|
||||
|
||||
## Usage
|
||||
- Choose app: Swipe up/down (top/bottom button on Bangle.js v1)
|
||||
- Launch app: Tap screen (center button on Bangle.js v1)
|
||||
- Return to clock: Swipe three ticks beyond first/last app in list
|
||||
|
||||
## Installation
|
||||
1. Install Ratchet Launcher using App Loader
|
||||
2. Uninstall default Launcher
|
||||
3. Reload
|
|
@ -0,0 +1,123 @@
|
|||
var Storage = require("Storage");
|
||||
var Layout = require("Layout");
|
||||
|
||||
var font = "6x15";
|
||||
var largeFont = "12x20";
|
||||
var currentApp = 0;
|
||||
var overscroll = 0;
|
||||
var blankImage = Graphics.createImage(` `);
|
||||
var rowHeight = g.getHeight()/3;
|
||||
|
||||
// Load apps list
|
||||
var apps = Storage.list(/\.info$/).map(app=>{
|
||||
var a=Storage.readJSON(app,1);
|
||||
return a&&{
|
||||
name:a.name,
|
||||
type:a.type,
|
||||
icon:a.icon ? Storage.read(a.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;
|
||||
});
|
||||
|
||||
// Initialize layout
|
||||
var layout = new Layout({
|
||||
type:"v", c:[
|
||||
// A row for the previous app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"prev_icon", src:blankImage, width:48, height:48, scale:0.8, pad:8},
|
||||
{type: "txt", id:"prev_name", label:"", font:font, fillx:1, wrap:1},
|
||||
]},
|
||||
// A row for the current app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"cur_icon", src:apps[currentApp].icon, width:48, height:48},
|
||||
{type: "txt", id:"cur_name", label:apps[currentApp].name, font:largeFont, fillx:1, wrap:1},
|
||||
]},
|
||||
// A row for the next app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"next_icon", src:blankImage, width:48, height:48, scale:0.8, pad:8},
|
||||
{type: "txt", id:"next_name", label:"", font:font, fillx:1, wrap:1},
|
||||
]},
|
||||
]
|
||||
});
|
||||
|
||||
// Drawing logic
|
||||
function render() {
|
||||
// Previous app
|
||||
if (currentApp > 0) {
|
||||
layout.prev_icon.src = apps[currentApp-1].icon;
|
||||
layout.prev_name.label = apps[currentApp-1].name;
|
||||
} else {
|
||||
layout.prev_icon.src = blankImage;
|
||||
layout.prev_name.label = "";
|
||||
}
|
||||
|
||||
// Current app
|
||||
layout.cur_icon.src = apps[currentApp].icon;
|
||||
layout.cur_name.label = apps[currentApp].name;
|
||||
|
||||
// Next app
|
||||
if (currentApp < apps.length-1) {
|
||||
layout.next_icon.src = apps[currentApp+1].icon;
|
||||
layout.next_name.label = apps[currentApp+1].name;
|
||||
} else {
|
||||
layout.next_icon.src = blankImage;
|
||||
layout.next_name.label = "";
|
||||
}
|
||||
|
||||
g.clear();
|
||||
layout.render();
|
||||
}
|
||||
|
||||
// Launch the currently selected app
|
||||
function launch() {
|
||||
var app = apps[currentApp];
|
||||
if (!app) return;
|
||||
if (!app.src || Storage.read(app.src)===undefined) {
|
||||
E.showMessage(/*LANG*/"App Source\nNot found");
|
||||
setTimeout(drawMenu, 2000);
|
||||
} else {
|
||||
E.showMessage(/*LANG*/"Loading...");
|
||||
load(app.src);
|
||||
}
|
||||
}
|
||||
|
||||
// Select previous/next app
|
||||
function move(step) {
|
||||
if ((currentApp == 0 && step < 0) || (currentApp >= apps.length-1 && step > 0)) {
|
||||
// When we hit the end of the list (top or bottom), the step is
|
||||
// counted towards the overscroll value. When the overscroll
|
||||
// threshold is exceeded, we return to the clock face.
|
||||
overscroll += step;
|
||||
} else {
|
||||
// This is the default case: the step is countedf towards the currentApp index
|
||||
currentApp += step;
|
||||
overscroll = 0;
|
||||
return render();
|
||||
}
|
||||
|
||||
// Overscroll threshold reached, return to clock
|
||||
if (Math.abs(overscroll) > 3) {
|
||||
Bangle.buzz(500, 1);
|
||||
return load();
|
||||
}
|
||||
}
|
||||
|
||||
// Wire up user input
|
||||
Bangle.setUI('updown', dir => {
|
||||
if (dir) move(-1*dir);
|
||||
else launch();
|
||||
});
|
||||
|
||||
render();
|
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"id": "ratchet_launch",
|
||||
"name": "Ratchet Launcher",
|
||||
"shortName": "Ratchet",
|
||||
"version": "0.01",
|
||||
"description": "Launcher with discrete scrolling for quicker app selection",
|
||||
"icon": "app.png",
|
||||
"type": "launch",
|
||||
"tags": "tool,system,launcher",
|
||||
"supports": ["BANGLEJS2","BANGLEJS"],
|
||||
"storage": [
|
||||
{"name":"ratchet_launch.app.js","url":"app.js"}
|
||||
],
|
||||
"sortorder": -10,
|
||||
"readme":"README.md"
|
||||
}
|
Loading…
Reference in New Issue