diff --git a/apps/distortclk/app-icon.js b/apps/distortclk/app-icon.js
index c375de96e..56a3c6b6f 100644
--- a/apps/distortclk/app-icon.js
+++ b/apps/distortclk/app-icon.js
@@ -1 +1 @@
-require("heatshrink").decompress(atob("j0ewkBiIAxHIQMJiBJEIxAaCAIQfHDgIUFDwwNCHYgVFiAVBHYgIDEghKCCIQGCFYoaDAYgORGIJ2DBwYIBHgQOPgAOIPIYOGAgQOFFgh7DHZQeDBwhoFQgh3JEAgOFFoqkHYRzgOfx4bCJ4gNGSIaJEABA7EAGA"))
+require("heatshrink").decompress(atob("mEwwMB/4AFgYCB4H//kAAoMAn/w+IFBx8P8fjAoPH4/n4/gg/j8/Px4rB+Pz58ch/wnHzz0wv/+hl5zlhDoOGnOY44FB8cZyOP/1/+OJwcfAoP44OGn4FB/lh5giBAIMz7n/AoP/nf4Aocf/IFDz5YBAoWP+YFD54FFMgIFD84FD84FM/0AApKfDApiaCAAJBCApKyCWgRlBAAWfOIIACj/8Aoc//g/BJ4KTBn4FBBIUfAoIbCx4CBFoUHAQPgDIMhAoOEV4NwVgMOn/4/jdBn8fDILpBUIfwh5TBIAYABA="))
diff --git a/apps/encourageclk/ChangeLog b/apps/encourageclk/ChangeLog
new file mode 100644
index 000000000..83c07f784
--- /dev/null
+++ b/apps/encourageclk/ChangeLog
@@ -0,0 +1,3 @@
+0.01: New face :)
+0.02: code improvements
+0.03: code improvments to queuedraw and draw
diff --git a/apps/encourageclk/README.md b/apps/encourageclk/README.md
new file mode 100644
index 000000000..420eddbcc
--- /dev/null
+++ b/apps/encourageclk/README.md
@@ -0,0 +1,18 @@
+# Encouragement & Positivity Clock
+
+Tap on the watch for a note of encouragement
+
+## Features
+
+Pretty backgrounds
+
+
+
+
+## Requests
+
+If you have any issues or would like to suggest an encouraging note, please tweet me!
+
+## Creator
+
+[Eleanor Tayam](http://twitter.com/elykittytee)
diff --git a/apps/encourageclk/app-icon.js b/apps/encourageclk/app-icon.js
new file mode 100644
index 000000000..56a3c6b6f
--- /dev/null
+++ b/apps/encourageclk/app-icon.js
@@ -0,0 +1 @@
+require("heatshrink").decompress(atob("mEwwMB/4AFgYCB4H//kAAoMAn/w+IFBx8P8fjAoPH4/n4/gg/j8/Px4rB+Pz58ch/wnHzz0wv/+hl5zlhDoOGnOY44FB8cZyOP/1/+OJwcfAoP44OGn4FB/lh5giBAIMz7n/AoP/nf4Aocf/IFDz5YBAoWP+YFD54FFMgIFD84FD84FM/0AApKfDApiaCAAJBCApKyCWgRlBAAWfOIIACj/8Aoc//g/BJ4KTBn4FBBIUfAoIbCx4CBFoUHAQPgDIMhAoOEV4NwVgMOn/4/jdBn8fDILpBUIfwh5TBIAYABA="))
diff --git a/apps/encourageclk/app.js b/apps/encourageclk/app.js
new file mode 100644
index 000000000..a78a788ba
--- /dev/null
+++ b/apps/encourageclk/app.js
@@ -0,0 +1,73 @@
+//230404
+
+require("FontHaxorNarrow7x17").add(Graphics);
+require("FontDylex7x13").add(Graphics);
+
+const storage = require('Storage');
+const locale = require("locale");
+const dateutil = require("date_utils");
+const currentFont=g.getFont();
+
+const width = 175;
+const height = 175;
+const offset = 25;
+
+var d = new Date();
+var nowDate = d.getDate(); //today's date
+var drawTimeout;
+var encourage = ["you\'re doing\ngreat!","pas de deux it!","you\'re amazing~","you got dis","keep going","you\'re one\nin a melon!","we\'re rooting\nfor you!","believe in\nyourself","dance like\nno one\'s\nwatching"];
+
+var bgimg = {
+ width : 175, height : 175, bpp : 4,
+ transparent : -1,
+ palette : new Uint16Array([46452,38393,32024,42585,52984,46739,59130,21489,46543,21493,25358,52696,48564,61210,29944,46322]),
+ buffer : require("heatshrink").decompress(atob("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"))
+};
+//TAP ALL THE THINGS
+Bangle.on('touch', (n, e) => {
+ // <88, top
+ if (e.x < width && e.y > offset) {
+ g.setColor(0,0,0);
+ g.setFont("Dylex7x13",2).setFontAlign(0,0).drawString(getEncour(), width/2, height/2);
+ setInterval(draw,3000);
+ }
+});
+
+//getters
+function getRandomInt(max) {
+ return Math.floor(Math.random() * max);
+}
+function getEncour(){ //return string
+ let rando = getRandomInt(encourage.length);
+ return encourage[rando];
+}
+//everymine
+function queueDraw() {
+ if (drawTimeout) clearTimeout(drawTimeout);
+ drawTimeout = setTimeout(function() {
+ drawTimeout = undefined;
+ draw();
+ }, 60000 - (Date.now() % 60000));
+}
+
+function draw() {
+ var time = locale.time(d, 1);
+ var date = locale.date(d);
+ var mo = dateutil.month(d.getMonth() + 1, 1);
+
+ g.drawImage(bgimg,0,offset); //bg
+ g.setFont("HaxorNarrow7x17").setColor(0,0,0);
+ g.setFontAlign(0, 0).setFont(currentFont, 7).drawString(time, width/2, 100);
+ g.setFontAlign(0,0).setFont(currentFont, 3).drawString(mo + " " + nowDate, width/2, 130);
+
+ queueDraw();
+}
+
+//ready set go!
+g.clear();
+
+Bangle.setUI("clock"); //button
+Bangle.drawWidgets(); //widgets
+Bangle.loadWidgets();
+
+draw(); //draw all the things
diff --git a/apps/encourageclk/app.png b/apps/encourageclk/app.png
new file mode 100644
index 000000000..6dc6b9270
Binary files /dev/null and b/apps/encourageclk/app.png differ
diff --git a/apps/encourageclk/metadata.json b/apps/encourageclk/metadata.json
new file mode 100644
index 000000000..4e5d630cf
--- /dev/null
+++ b/apps/encourageclk/metadata.json
@@ -0,0 +1,17 @@
+{
+ "id": "encourageclk",
+ "name": "Encouragement & Positivity Clock",
+ "shortName":"Encouragement Clock",
+ "version": "0.03",
+ "description": "Tap on the watch for a note of encouragement",
+ "icon": "app.png",
+ "type": "clock",
+ "tags": "clock",
+ "supports": ["BANGLEJS2"],
+ "allow_emulator": true,
+ "readme":"README.md",
+ "storage": [
+ {"name":"encourageclk.app.js","url":"app.js"},
+ {"name":"encourageclk.img","url":"app-icon.js","evaluate":true}
+ ]
+}
diff --git a/apps/encourageclk/screenshot.png b/apps/encourageclk/screenshot.png
new file mode 100644
index 000000000..2569b6291
Binary files /dev/null and b/apps/encourageclk/screenshot.png differ
diff --git a/apps/grocery/interface.html b/apps/grocery/interface.html
index 65528c8e6..58ab2a484 100644
--- a/apps/grocery/interface.html
+++ b/apps/grocery/interface.html
@@ -46,7 +46,6 @@
var $name = document.getElementById('add_product_name')
var $form = document.getElementById('add_product_form')
- var $button = document.getElementById('add_product_button')
var $quantity = document.getElementById('add_product_quantity')
var $list = document.getElementById('products')
var $reset = document.getElementById('reset')
@@ -68,7 +67,8 @@
ok: false
})
- renderProducts()
+ renderProducts();
+ window.scrollTo(0, document.body.scrollHeight);
$name.value = ''
$quantity.value = 1
})
diff --git a/apps/longpressbuzz/ChangeLog b/apps/longpressbuzz/ChangeLog
new file mode 100644
index 000000000..5560f00bc
--- /dev/null
+++ b/apps/longpressbuzz/ChangeLog
@@ -0,0 +1 @@
+0.01: New App!
diff --git a/apps/longpressbuzz/README.md b/apps/longpressbuzz/README.md
new file mode 100644
index 000000000..6394faa75
--- /dev/null
+++ b/apps/longpressbuzz/README.md
@@ -0,0 +1,17 @@
+# Long Press, Buzz!
+
+Buzz at boot after a long press to indicate the watch was reinitiated at your command.
+
+To infinity and beyond, space ranger!
+
+## Usage
+
+Just install and it will run as boot code.
+
+## Requests
+
+Mention @[thyttan](https://github.com/thyttan) in an issue to the official [BangleApps repository](https://github.com/espruino/BangleApps/issues) for feature requests and bug reports.
+
+## Creators
+
+[thyttan](https://github.com/thyttan) and [Gordon Williams](https://github.com/gfwilliams).
diff --git a/apps/longpressbuzz/app.png b/apps/longpressbuzz/app.png
new file mode 100644
index 000000000..e3951d784
Binary files /dev/null and b/apps/longpressbuzz/app.png differ
diff --git a/apps/longpressbuzz/boot.js b/apps/longpressbuzz/boot.js
new file mode 100644
index 000000000..05bc4a9b3
--- /dev/null
+++ b/apps/longpressbuzz/boot.js
@@ -0,0 +1 @@
+if (BTN.read()) Bangle.buzz(80,0.40);
diff --git a/apps/longpressbuzz/metadata.json b/apps/longpressbuzz/metadata.json
new file mode 100644
index 000000000..56e06f0bd
--- /dev/null
+++ b/apps/longpressbuzz/metadata.json
@@ -0,0 +1,14 @@
+{ "id": "longpressbuzz",
+ "name": "Long Press, Buzz!",
+ "shortName":"LPB",
+ "version":"0.01",
+ "description": "Buzz at boot after a long press to indicate the watch was reinitiated at your command.",
+ "icon": "app.png",
+ "type": "bootloader",
+ "tags": "system",
+ "supports" : ["BANGLEJS2"],
+ "readme": "README.md",
+ "storage": [
+ {"name":"longpressbuzz.0.boot.js","url":"boot.js"}
+ ]
+}
diff --git a/apps/swscroll/ChangeLog b/apps/swscroll/ChangeLog
index c5fc9dcb4..b35c27001 100644
--- a/apps/swscroll/ChangeLog
+++ b/apps/swscroll/ChangeLog
@@ -1,2 +1,4 @@
0.01: Inital release.
0.02: Rebasing on latest changes to showScroller_Q3 (https://github.com/espruino/Espruino/commit/2d3c34ef7c2b9fe2118e816aacd2e096adb99596).
+0.03: Rebasing on latest changes to showScroller_Q3 (https://github.com/espruino/Espruino/commit/b6f8105b6348bb6f7cd03ac11efc1f3585c6ad79). Ensure that changing a menu item when half-scrolled off screen doesn't overwrite widgets.
+
diff --git a/apps/swscroll/boot.js b/apps/swscroll/boot.js
index 2b1b00de3..57a5d8fb3 100644
--- a/apps/swscroll/boot.js
+++ b/apps/swscroll/boot.js
@@ -95,7 +95,7 @@ var s = {
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
}, drawItem : i => {
var y = idxToY(i);
- g.reset().setClipRect(R.x,y,R.x2,y+options.h);
+ g.reset().setClipRect(R.x,Math.max(y,R.y),R.x2,Math.min(y+options.h,R.y2));
options.draw(i, {x:R.x,y:y,w:R.w,h:options.h});
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
}};
diff --git a/apps/swscroll/metadata.json b/apps/swscroll/metadata.json
index 4edbfa2ba..eff55e4bd 100644
--- a/apps/swscroll/metadata.json
+++ b/apps/swscroll/metadata.json
@@ -1,7 +1,7 @@
{
"id": "swscroll",
"name": "Swipe menus",
- "version": "0.02",
+ "version": "0.03",
"description": "Replace built in E.showScroller to act on swipe instead of drag. Navigate menus in discrete steps instead of a continuous motion.",
"readme": "README.md",
"icon": "app.png",
diff --git a/apps/tinycmc/ChangeLog b/apps/tinycmc/ChangeLog
new file mode 100644
index 000000000..46fdd1b1e
--- /dev/null
+++ b/apps/tinycmc/ChangeLog
@@ -0,0 +1,2 @@
+0.01: New App
+0.02: Set API Key through Apploader
\ No newline at end of file
diff --git a/apps/tinycmc/README.md b/apps/tinycmc/README.md
new file mode 100644
index 000000000..42cbdf203
--- /dev/null
+++ b/apps/tinycmc/README.md
@@ -0,0 +1,7 @@
+# Tiny Coinmarketcap
+A simple app using Gadgedtbridge internet access to fetch current crypto prices from Coinmarketcap.
+I'm providing a "free-tier" API Key.
+
+TO-DOs:
+- [X] Add own API Key option
+- [ ] Add settings for Currency conversion
\ No newline at end of file
diff --git a/apps/tinycmc/app-icon.js b/apps/tinycmc/app-icon.js
new file mode 100644
index 000000000..0c8a0226b
--- /dev/null
+++ b/apps/tinycmc/app-icon.js
@@ -0,0 +1 @@
+require("heatshrink").decompress(atob("mEw4kA/4ACBIP/o8242462/k8/gtytlz1s+r2/gv/q9Zpv/m+02pj/AH4AqgMRBhURAAQWGqPxqPwA4UoloABkoLCAIQhIiMQgUo29mtfr6WIBogxDFwNBAIeKwd8x2Mud8lUhBolQLoYABrERjurs/S7F329rs+i+I+EC4JRFxl+lUmvmGAIWKkJhGJ4lI01y2+3s4BB1s7s+o+MVMAhPEll7kd+uYBCvgBB7khyIRCL4cZiMS7YuCAAxnBSAsBJoWKl0sLYYBFluBL4iPCiuNsRdEAIlr3GBR4iQBJoMs7pdEAIjDBkK/ESAUY665BABNn7AvFkWBlEsXYoBFMAMlkPwC4UYRwOru5ZDMY+iitBF4MoPAOBxsjXoktAYMoYYcowOBwEokAXBiq+BL4eywWH2WHA4VrYAMViECgEgYAOIxhXDlF8k0oM4eDxrABkReBkEIj/y1ZVCsRjB2UnL4tYimCO4UBoOdlhdCveDAYMuYId8kq/DGIOI/Hyw6MDAA9t7FI/HwJAUBqOBll7X5WK+PxqK/DgMRimNsS7HAINm3DuBd4hfB+ONxhZEAIl8lVBL4YXCjLwB7eyLxFn7AvHJ4PxlS7BLo2OvmBqJfHAANC02yLotrs+iiMYB4IWCL4QgByMsvlzXYlz7UhLoIBBC4cADwMViNS7drFQNnAYXSFwZeDAAJPCyPxlEsFgIuClouBBoPxRwZgEGAMYwWI81n9sikA9CFwwwCKIWRyOFlEtlANEoAWGMIYyDisVCBAAHKYRjBqOAC6AyECqQA/AH4AJA=="))
\ No newline at end of file
diff --git a/apps/tinycmc/app.js b/apps/tinycmc/app.js
new file mode 100644
index 000000000..07a56e494
--- /dev/null
+++ b/apps/tinycmc/app.js
@@ -0,0 +1,118 @@
+let settings = require("Storage").readJSON("tinycmc.json", 1);
+const apiKey = settings.apikey || null;
+const cmcBase = 'https://pro-api.coinmarketcap.com/';
+const version = ['v1', 'v2'];
+const path = {
+ latest: '/cryptocurrency/listings/latest',
+ quote: '/cryptocurrency/quotes/latest'
+};
+let page = 0;
+function displayLatest(offset) {
+ g.clear();
+ if (page === 0) {
+ E.showMessage('Getting Top 10');
+ } else {
+ E.showMessage(`Getting Top ${offset} to ${offset + 9}`);
+ }
+
+ const uri = offset ? `${cmcBase}${version[0]}${path.latest}?convert=EUR&limit=10&start=${offset}` : `${cmcBase}${version[0]}${path.latest}?convert=EUR&limit=10`;
+ Bangle.http(uri,
+ {
+ method: 'GET',
+ headers: {
+ "X-CMC_PRO_API_KEY": apiKey,
+ }
+ }).then(data=>{
+ const result = JSON.parse(data.resp).data;
+ let menu = {
+ "" : { title : "-- Select --" },
+ };
+ //FIXME: Menu can also take an array of items, this would be easier to compose using map
+ result.forEach(listing => {
+ menu[listing.name] = {
+ title: `${listing.cmc_rank}: ${listing.symbol} ${Number(listing.quote.EUR.percent_change_24h).toFixed(3)}`,
+ onchange: function() { E.showMenu(); displayQuote(listing.symbol);} };
+ });
+ menu.Next = function() {
+ E.showMenu();
+ g.clear();
+ page = page + 1;
+ displayLatest((page * 10) + 1);
+ }; // remove the menu
+ menu.Exit = function() {
+ E.showMenu();
+ g.clear();
+ Bangle.showClock();
+ }; // remove the menu
+ g.clear();
+ E.showMenu(menu);
+ setWatch(() => {
+ g.clear();
+ displayMenu();
+ }, BTN, {edge:"rising", debounce:50, repeat:true});
+}).catch(error=>{
+ console.log('Error');
+ console.log(error);
+ E.showMessage(`${error}\nTo go back press BTN`);
+ setWatch(() => {
+ g.clear();
+ displayMenu();
+ }, BTN, {edge:"rising", debounce:50, repeat:true});
+ });
+}
+
+function displayQuote(symb) {
+ g.clear();
+ E.showMessage(`Getting latest for ${symb}`);
+ Bangle.http(`${cmcBase}${version[1]}${path.quote}?symbol=${symb}&convert=EUR`,
+ {
+ method: 'GET',
+ headers: {
+ "X-CMC_PRO_API_KEY": apiKey,
+ }
+ }).then(data=>{
+ g.clear();
+ const result = JSON.parse(data.resp).data[symb][0];
+ E.showMessage(`#${result.cmc_rank}: ${result.symbol}\n${Number(result.quote.EUR.price).toFixed(2)}\n%24h:
+${result.quote.EUR.percent_change_24h}`);
+ setWatch(() => {
+ g.clear();
+ displayMenu();
+ }, BTN, {edge:"rising", debounce:50, repeat:true});
+}).catch(error=>{
+ E.showMessage(`${error}\nTo go back press BTN`);
+ setWatch(() => {
+ g.clear();
+ displayMenu();
+ }, BTN, {edge:"rising", debounce:50, repeat:true});
+ });
+}
+
+function displayMenu() {
+ if (!apiKey) {
+ E.showMessage("Please provide a Coinmarketcap API Key");
+ } else {
+ // Actually display the menu
+ E.showMenu({
+ "" : { title : "-- Select --" }, // options
+ "Latest": function() { E.showMenu(); displayLatest(); },
+ "BTC" : function() { E.showMenu(); displayQuote('BTC'); },
+ "ETH" : function() { E.showMenu(); displayQuote('ETH'); },
+ "XMR" : function() { E.showMenu(); displayQuote('XMR'); },
+ "ADA" : function() { E.showMenu(); displayQuote('ADA'); },
+ "DOGE" : function() { E.showMenu(); displayQuote('DOGE'); },
+ "LTC" : function() { E.showMenu(); displayQuote('LTC'); },
+ "Exit" : function() {
+ E.showMenu();
+ g.clear();
+ Bangle.showClock();
+ }, // remove the menu
+ });
+ }
+}
+
+function main () {
+ displayMenu();
+}
+
+main ();
diff --git a/apps/tinycmc/icon.png b/apps/tinycmc/icon.png
new file mode 100644
index 000000000..2038315e0
Binary files /dev/null and b/apps/tinycmc/icon.png differ
diff --git a/apps/tinycmc/interface.html b/apps/tinycmc/interface.html
new file mode 100644
index 000000000..2a9e7824b
--- /dev/null
+++ b/apps/tinycmc/interface.html
@@ -0,0 +1,63 @@
+
+
Go to https://coinmarketcap.com/api/ and sign up for a free account.
+ After registration you can login and obtain your personal API key.