From 8dc3e8f8fcad22e379c7d8b59959c0c55d3fc6ed Mon Sep 17 00:00:00 2001 From: Joseph Paul Date: Fri, 4 Mar 2022 10:16:32 +0100 Subject: [PATCH] Ratchet Launcher: Initial version --- apps/ratchet_launch/ChangeLog | 1 + apps/ratchet_launch/README.md | 15 ++++ apps/ratchet_launch/app.js | 123 ++++++++++++++++++++++++++++++ apps/ratchet_launch/app.png | Bin 0 -> 9788 bytes apps/ratchet_launch/metadata.json | 16 ++++ 5 files changed, 155 insertions(+) create mode 100644 apps/ratchet_launch/ChangeLog create mode 100644 apps/ratchet_launch/README.md create mode 100644 apps/ratchet_launch/app.js create mode 100644 apps/ratchet_launch/app.png create mode 100644 apps/ratchet_launch/metadata.json diff --git a/apps/ratchet_launch/ChangeLog b/apps/ratchet_launch/ChangeLog new file mode 100644 index 000000000..af7f83942 --- /dev/null +++ b/apps/ratchet_launch/ChangeLog @@ -0,0 +1 @@ +0.01: Initial release diff --git a/apps/ratchet_launch/README.md b/apps/ratchet_launch/README.md new file mode 100644 index 000000000..15df463d0 --- /dev/null +++ b/apps/ratchet_launch/README.md @@ -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 diff --git a/apps/ratchet_launch/app.js b/apps/ratchet_launch/app.js new file mode 100644 index 000000000..626b8e4f8 --- /dev/null +++ b/apps/ratchet_launch/app.js @@ -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.nameb.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(); diff --git a/apps/ratchet_launch/app.png b/apps/ratchet_launch/app.png new file mode 100644 index 0000000000000000000000000000000000000000..a27ab48eda4d78d88a5d958e540b9bc822e2131c GIT binary patch literal 9788 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 cggb