Merge remote-tracking branch 'upstream/master'
commit
ff5fda9dff
43
apps.json
43
apps.json
|
|
@ -31,6 +31,23 @@
|
||||||
],
|
],
|
||||||
"sortorder": -10
|
"sortorder": -10
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "messages",
|
||||||
|
"name": "Messages",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "App to display notifications from iOS and Gadgetbridge (BETA)",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "tool,system",
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"messages.app.js","url":"app.js"},
|
||||||
|
{"name":"messages.img","url":"app-icon.js","evaluate":true},
|
||||||
|
{"name":"messages.boot.js","url":"boot.js"},
|
||||||
|
{"name":"messages.wid.js","url":"widget.js"}
|
||||||
|
],
|
||||||
|
"sortorder": -9
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
|
|
@ -46,8 +63,9 @@
|
||||||
{"name":"health.boot.js","url":"boot.js"},
|
{"name":"health.boot.js","url":"boot.js"},
|
||||||
{"name":"health","url":"lib.js"}
|
{"name":"health","url":"lib.js"}
|
||||||
],
|
],
|
||||||
"sortorder": -10
|
"sortorder": -8
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"id": "moonphase",
|
"id": "moonphase",
|
||||||
"name": "Moonphase",
|
"name": "Moonphase",
|
||||||
|
|
@ -716,7 +734,7 @@
|
||||||
{
|
{
|
||||||
"id": "widbat",
|
"id": "widbat",
|
||||||
"name": "Battery Level Widget",
|
"name": "Battery Level Widget",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "Show the current battery level and charging status in the top right of the clock",
|
"description": "Show the current battery level and charging status in the top right of the clock",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
@ -726,6 +744,19 @@
|
||||||
{"name":"widbat.wid.js","url":"widget.js"}
|
{"name":"widbat.wid.js","url":"widget.js"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "widbatv",
|
||||||
|
"name": "Battery Level Widget (Vertical)",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Slim, vertical battery widget that only takes up 14px",
|
||||||
|
"icon": "widget.png",
|
||||||
|
"type": "widget",
|
||||||
|
"tags": "widget,battery",
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"widbatv.wid.js","url":"widget.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "widlock",
|
"id": "widlock",
|
||||||
"name": "Lock Widget",
|
"name": "Lock Widget",
|
||||||
|
|
@ -777,7 +808,7 @@
|
||||||
{
|
{
|
||||||
"id": "widbt",
|
"id": "widbt",
|
||||||
"name": "Bluetooth Widget",
|
"name": "Bluetooth Widget",
|
||||||
"version": "0.06",
|
"version": "0.07",
|
||||||
"description": "Show the current Bluetooth connection status in the top right of the clock",
|
"description": "Show the current Bluetooth connection status in the top right of the clock",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
@ -1617,12 +1648,12 @@
|
||||||
{
|
{
|
||||||
"id": "widtbat",
|
"id": "widtbat",
|
||||||
"name": "Tiny Battery Widget",
|
"name": "Tiny Battery Widget",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Tiny blueish battery widget, vibs and changes level color when charging",
|
"description": "Tiny blueish battery widget, vibs and changes level color when charging",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"tags": "widget,tool,system",
|
"tags": "widget,tool,system",
|
||||||
"supports": ["BANGLEJS"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"widtbat.wid.js","url":"widget.js"}
|
{"name":"widtbat.wid.js","url":"widget.js"}
|
||||||
]
|
]
|
||||||
|
|
@ -3734,7 +3765,7 @@
|
||||||
{
|
{
|
||||||
"id": "hcclock",
|
"id": "hcclock",
|
||||||
"name": "Hi-Contrast Clock",
|
"name": "Hi-Contrast Clock",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.",
|
"description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.",
|
||||||
"icon": "hcclock-icon.png",
|
"icon": "hcclock-icon.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("mEwghC/AH8A1QWVhWq0AuVAAIuVAAIwT1WinQwTFwMzmQwTCYMjlUqGCIuBlWi0UzC6JdBIoMjC4UDmAuOkYXBPAWgmczLp2ilUiVAUDC4IwLFwIUBLoJ2BFwQwM1WjCgJ1DFwQwLFwJ1B0SQCkQWDGBQXBCgK9BDgKQBAAgwJOwUzRgIDBC54wCkZdGPBwACRgguDBIIwLFxEJBQIwLFxGaBYQwKFxQwLgAWGmQuBcAQwJC48ifYYwJgUidgsyC4L7DGBIXBdohnBCgL7BcYIXIGAqMCIoL7DL5IwERgIUBLoL7BO5QXBGAK7DkWiOxQXGFwOjFoUyFxZhDgBdCCgJ1CCxYxCgBABkcqOwIuNGAQXC0S9BLpgAFXoIwBmYuPAAYwCLp4wHFyYwDFyYwDFygwCCyoA/AFQA="))
|
require("heatshrink").decompress(atob("mEw4UA////G161hyd8Jf4ALlQLK1WABREC1WgBZEK32oFxPW1QuJ7QwIFwOqvQLHhW31NaBY8qy2rtUFoAuG3W61EVqALF1+qr2gqtUHQu11dawNVqo6F22q9XFBYIwEhWqz2r6oLBGAheBqwuBBYx2CFwQLGlWqgoLCMAsKLoILChR6EgQuDqkqYYsBFweqYYoLDoWnYYoLD/WVYYv8FwXqPoIwEn52BqGrPoILEh/1FwOl9SsBBYcD/pdB2uq/QvEh/8LoOu1xHFh8/gGp9WWL4oMBgWltXeO4owBgWt1ReFYYh2GYYmXEQzDD3wiHegYKIGAJRGAAguJAH4AC"))
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
0.01: base code
|
0.01: base code
|
||||||
|
0.02: saved settings when switching color scheme
|
||||||
|
|
@ -180,13 +180,46 @@ function fmtDate(day,month,year,hour)
|
||||||
return months[month] + ". " + day + " " + year;
|
return months[month] + ". " + day + " " + year;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles Flipping colors, then refreshes the UI
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// HANDLE COLORS + SETTINGS
|
||||||
|
//
|
||||||
|
|
||||||
|
function getColorScheme()
|
||||||
|
{
|
||||||
|
let settings = require('Storage').readJSON("hcclock.json", true) || {};
|
||||||
|
if (!("scheme" in settings)) {
|
||||||
|
settings.scheme = 0;
|
||||||
|
}
|
||||||
|
return settings.scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setColorScheme(value)
|
||||||
|
{
|
||||||
|
let settings = require('Storage').readJSON("hcclock.json", true) || {};
|
||||||
|
settings.scheme = value;
|
||||||
|
require('Storage').writeJSON('hcclock.json', settings);
|
||||||
|
|
||||||
|
if(value == 0) // White
|
||||||
|
{
|
||||||
|
bg = 255;
|
||||||
|
fg = 0;
|
||||||
|
}
|
||||||
|
else // Black
|
||||||
|
{
|
||||||
|
bg = 0;
|
||||||
|
fg = 255;
|
||||||
|
}
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
function flipColors()
|
function flipColors()
|
||||||
{
|
{
|
||||||
let t = bg;
|
if(getColorScheme() == 0)
|
||||||
bg = fg;
|
setColorScheme(1);
|
||||||
fg = t;
|
else
|
||||||
redraw();
|
setColorScheme(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
@ -197,7 +230,7 @@ function flipColors()
|
||||||
// Initialize
|
// Initialize
|
||||||
g.clear();
|
g.clear();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
redraw();
|
setColorScheme(getColorScheme());
|
||||||
|
|
||||||
// Define Refresh Interval
|
// Define Refresh Interval
|
||||||
setInterval(updateTime, interval);
|
setInterval(updateTime, interval);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ function drawMenu() {
|
||||||
var w = g.getWidth();
|
var w = g.getWidth();
|
||||||
var h = g.getHeight();
|
var h = g.getHeight();
|
||||||
var m = w/2;
|
var m = w/2;
|
||||||
var n = (h-48)/64;
|
var n = Math.floor((h-48)/64);
|
||||||
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
|
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
|
||||||
if (selected<menuScroll) menuScroll = selected;
|
if (selected<menuScroll) menuScroll = selected;
|
||||||
// arrows
|
// arrows
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Messages app
|
||||||
|
|
||||||
|
**THIS APP IS CURRENTLY BETA**
|
||||||
|
|
||||||
|
This app handles the display of messages and message notifications. It stores
|
||||||
|
a list of currently received messages and allows them to be listed, viewed,
|
||||||
|
and responded to.
|
||||||
|
|
||||||
|
It is a replacement for the old `notify`/`gadgetbridge` apps.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
## Requests
|
||||||
|
|
||||||
|
Please file any issues on https://github.com/espruino/BangleApps/issues/new?title=messages%20app
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
|
||||||
|
Gordon Williams
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEw4UA///rkcAYP9ohL/ABMBqoAEoALDioLFqgLDBQoABERIkEBZcFBY9QBed61QAC1oLF7wLD24LF24LD7wLF1vqBQOrvQLFA4IuC9QLFD4IuC1QLGGAQOBBYwgBEwQLHvQBBEZHVq4jI7wWBHY5TLNZaDLTZazLffMBBY9ABZsABY4KCgEVBQtUBYYkGEQYA/AAwA="))
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
/* MESSAGES is a list of:
|
||||||
|
{id:int,
|
||||||
|
src,
|
||||||
|
title,
|
||||||
|
subject,
|
||||||
|
body,
|
||||||
|
sender,
|
||||||
|
tel:string,
|
||||||
|
new:true // not read yet
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* For example for maps:
|
||||||
|
|
||||||
|
GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"})
|
||||||
|
GB({"t":"notify","id":2,"src":"Hangouts","title":"Gordon","body":"Hello world quite a lot of text here..."})
|
||||||
|
GB({"t":"notify","id":3,"src":"Messages","title":"Ted","body":"Bed time."})
|
||||||
|
GB({"t":"notify","id":4,"src":"Messages","title":"Kailo","body":"Mmm... food"})
|
||||||
|
GB({"t":"notify-","id":1})
|
||||||
|
|
||||||
|
GB({"t":"notify","id":1,"src":"Maps","title":"0 yd - High St","body":"Campton - 11:48 ETA","img":"Y2MBAA....AAAAAAAAAAAAAA="})
|
||||||
|
GB({"t":"notify~","id":1,"body":"Campton - 11:54 ETA"})
|
||||||
|
GB({"t":"notify~","id":1,"title":"High St"})
|
||||||
|
GB({"t":"notify~","id":1,"body":"Campton - 11:55 ETA"})
|
||||||
|
GB({"t":"notify~","id":1,"title":"0 yd - High St"})
|
||||||
|
GB({"t":"notify~","id":1,"body":"Campton - 11:56 ETA"})
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Layout = require("Layout");
|
||||||
|
|
||||||
|
var MESSAGES = require("Storage").readJSON("messages.json",1)||[];
|
||||||
|
if (!Array.isArray(MESSAGES)) MESSAGES=[];
|
||||||
|
var onMessagesModified = function(msg) {
|
||||||
|
// TODO: if new, show this new one
|
||||||
|
if (msg.new) Bangle.buzz();
|
||||||
|
showMessage(msg.id);
|
||||||
|
};
|
||||||
|
function saveMessages() {
|
||||||
|
require("Storage").writeJSON("messages.json",MESSAGES)
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMapMessage(msg) {
|
||||||
|
var m;
|
||||||
|
var distance, street, target, eta;
|
||||||
|
m=msg.title.match(/(.*) - (.*)/);
|
||||||
|
if (m) {
|
||||||
|
distance = m[1];
|
||||||
|
street = m[2];
|
||||||
|
} else street=msg.title;
|
||||||
|
m=msg.body.match(/(.*) - (.*)/);
|
||||||
|
if (m) {
|
||||||
|
target = m[1];
|
||||||
|
eta = m[2];
|
||||||
|
} else target=msg.body;
|
||||||
|
layout = new Layout({
|
||||||
|
type:"v", c: [
|
||||||
|
{type:"txt", font:"6x15", label:target, bgCol:"#0f0", fillx:1, pad:2 },
|
||||||
|
{type:"h", bgCol:"#0f0", fillx:1, c: [
|
||||||
|
{type:"txt", font:"6x8", label:"Towards" },
|
||||||
|
{type:"txt", font:"6x15:2", label:street }
|
||||||
|
]},
|
||||||
|
{type:"h",fillx:1, filly:1, c: [
|
||||||
|
{type:"img",src:atob(msg.img)},
|
||||||
|
{type:"v", fillx:1, c: [
|
||||||
|
{type:"txt", font:"6x15:2", label:distance||"" }
|
||||||
|
]},
|
||||||
|
]},
|
||||||
|
|
||||||
|
{type:"txt", font:"6x8:2", label:eta }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
g.clearRect(0,24,g.getWidth()-1,g.getHeight()-1);
|
||||||
|
layout.render();
|
||||||
|
Bangle.setUI("updown",function() {
|
||||||
|
// any input to mark as not new and return to menu
|
||||||
|
msg.new = false;
|
||||||
|
saveMessages();
|
||||||
|
checkMessages();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(msgid) {
|
||||||
|
var msg = MESSAGES.find(m=>m.id==msgid);
|
||||||
|
if (!msg) return checkMessages(); // go home if no message found
|
||||||
|
if (msg.src=="Maps") return showMapMessage(msg);
|
||||||
|
var m = msg.title+"\n"+msg.body;
|
||||||
|
E.showPrompt(m,{title:"Message", buttons : {"Read":"read", "Back":"back"}}).then(chosen => {
|
||||||
|
if (chosen=="read") {
|
||||||
|
// any input to mark as not new and return to menu
|
||||||
|
msg.new = false;
|
||||||
|
saveMessages();
|
||||||
|
checkMessages();
|
||||||
|
} else {
|
||||||
|
checkMessages(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a single menu item for the message
|
||||||
|
function showMessageMenuItem(y, idx) {
|
||||||
|
var msg = MESSAGES[idx];
|
||||||
|
var W = g.getWidth(), H=48;
|
||||||
|
if (msg.new) g.setBgColor("#4F4");
|
||||||
|
else g.setBgColor("#CFC");
|
||||||
|
g.clearRect(0,y,W-1,y+H-1).setColor(g.theme.fg);
|
||||||
|
var m = msg.title+"\n"+msg.body;
|
||||||
|
if (msg.src) g.setFontAlign(1,-1).drawString(msg.src, W-2, y+2);
|
||||||
|
if (msg.title) g.setFontAlign(-1,-1).setFont("12x20").drawString(msg.title, 2,y+2);
|
||||||
|
if (msg.body) {
|
||||||
|
g.setFontAlign(-1,-1).setFont("6x8");
|
||||||
|
var l = g.wrapString(msg.body, W-14);
|
||||||
|
if (l.length>3) {
|
||||||
|
l = l.slice(0,3);
|
||||||
|
l[l.length-1]+="...";
|
||||||
|
}
|
||||||
|
g.drawString(l.join("\n"), 12,y+20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//test
|
||||||
|
//g.clear(1); showMessageMenuItem(MESSAGES[0],24)
|
||||||
|
|
||||||
|
if (process.env.HWVERSION==1) { // Bangle.js 1
|
||||||
|
showBigMenu = function(options) {
|
||||||
|
/* options = {
|
||||||
|
h = height
|
||||||
|
items = # of items
|
||||||
|
draw = function(y, idx)
|
||||||
|
onSelect = function(idx)
|
||||||
|
}*/
|
||||||
|
var selected = 0;
|
||||||
|
var menuScroll = 0;
|
||||||
|
var menuShowing = false;
|
||||||
|
var w = g.getWidth();
|
||||||
|
var h = g.getHeight();
|
||||||
|
var m = w/2;
|
||||||
|
var n = Math.floor((h-48)/options.h);
|
||||||
|
|
||||||
|
function drawMenu() {
|
||||||
|
g.reset();
|
||||||
|
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
|
||||||
|
if (selected<menuScroll) menuScroll = selected;
|
||||||
|
// draw
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
for (var i=0;i<n;i++) {
|
||||||
|
var idx = i+menuScroll;
|
||||||
|
if (idx<0 || idx>=options.items) break;
|
||||||
|
var y = 24+i*options.h;
|
||||||
|
options.draw(y, idx);
|
||||||
|
// border for selected
|
||||||
|
if (i+menuScroll==selected) {
|
||||||
|
g.setColor(g.theme.fgG).drawRect(0,y,w-1,y+options.h-1).drawRect(1,y+1,w-2,y+options.h-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// arrows
|
||||||
|
g.setColor(menuScroll ? g.theme.fg : g.theme.bg);
|
||||||
|
g.fillPoly([m,6,m-14,20,m+14,20]);
|
||||||
|
g.setColor((options.items>n+menuScroll) ? g.theme.fg : g.theme.bg);
|
||||||
|
g.fillPoly([m,h-7,m-14,h-21,m+14,h-21]);
|
||||||
|
}
|
||||||
|
g.clearRect(0,24,w-1,h-1);
|
||||||
|
drawMenu();
|
||||||
|
Bangle.setUI("updown",dir=>{
|
||||||
|
if (dir) {
|
||||||
|
selected += dir;
|
||||||
|
if (selected<0) selected = options.items-1;
|
||||||
|
if (selected>=options.items) selected = 0;
|
||||||
|
drawMenu();
|
||||||
|
} else {
|
||||||
|
options.onSelect(selected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else { // Bangle.js 2
|
||||||
|
showBigMenu = function(options) {
|
||||||
|
/* options = {
|
||||||
|
h = height
|
||||||
|
items = # of items
|
||||||
|
draw = function(y, idx)
|
||||||
|
onSelect = function(idx)
|
||||||
|
}*/
|
||||||
|
var menuScroll = 0;
|
||||||
|
var menuShowing = false;
|
||||||
|
var w = g.getWidth();
|
||||||
|
var h = g.getHeight();
|
||||||
|
var n = Math.ceil((h-24)/options.h);
|
||||||
|
var menuScrollMax = options.h*options.items - (h-24);
|
||||||
|
|
||||||
|
function drawItem(i) {
|
||||||
|
var y = 24+i*options.h-menuScroll;
|
||||||
|
if (i<0 || i>=options.items || y<-options.h || y>=h) return;
|
||||||
|
options.draw(y, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawMenu() {
|
||||||
|
g.reset().clearRect(0,24,w-1,h-1);
|
||||||
|
g.setClipRect(0,24,w-1,h-1);
|
||||||
|
for (var i=0;i<n;i++) drawItem(i);
|
||||||
|
g.setClipRect(0,0,w-1,h-1);
|
||||||
|
}
|
||||||
|
drawMenu();
|
||||||
|
g.flip(); // force an update now to make this snappier
|
||||||
|
|
||||||
|
Bangle.dragHandler = e=>{
|
||||||
|
var dy = e.dy;
|
||||||
|
if (menuScroll - dy < 0)
|
||||||
|
dy = menuScroll;
|
||||||
|
if (menuScroll - dy > menuScrollMax)
|
||||||
|
dy = menuScroll - menuScrollMax;
|
||||||
|
if (!dy) return;
|
||||||
|
g.reset().setClipRect(0,24,g.getWidth()-1,g.getHeight()-1);
|
||||||
|
g.scroll(0,dy);
|
||||||
|
menuScroll -= dy;
|
||||||
|
if (e.dy < 0) {
|
||||||
|
drawItem(Math.floor((menuScroll+24+g.getHeight())/options.h)-1);
|
||||||
|
if (e.dy <= -options.h) drawItem(Math.floor((menuScroll+24+h)/options.h)-2);
|
||||||
|
} else {
|
||||||
|
drawItem(Math.floor((menuScroll+24)/options.h));
|
||||||
|
if (e.dy >= options.h) drawItem(Math.floor((menuScroll+24)/options.h)+1);
|
||||||
|
}
|
||||||
|
g.setClipRect(0,0,w-1,h-1);
|
||||||
|
};
|
||||||
|
Bangle.on('drag',Bangle.dragHandler);
|
||||||
|
Bangle.touchHandler = (_,e)=>{
|
||||||
|
if (e.y<20) return;
|
||||||
|
var i = Math.floor((e.y+menuScroll-24) / options.h);
|
||||||
|
if (i>=0 && i<options.items)
|
||||||
|
options.onSelect(i);
|
||||||
|
};
|
||||||
|
Bangle.on("touch", Bangle.touchHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMessages(forceShowMenu) {
|
||||||
|
// If no messages, just show 'no messages' and return
|
||||||
|
if (!MESSAGES.length)
|
||||||
|
return E.showPrompt("No Messages",{
|
||||||
|
title:"Messages",
|
||||||
|
img:require("heatshrink").decompress(atob("kkk4UBrkc/4AC/tEqtACQkBqtUDg0VqAIGgoZFDYQIIM1sD1QAD4AIBhnqA4WrmAIBhc6BAWs8AIBhXOBAWz0AIC2YIC5wID1gkB1c6BAYFBEQPqBAYXBEQOqBAnDAIQaEnkAngaEEAPDFgo+IKA5iIOhCGIAFb7RqAIGgtUBA0VqobFgNVA")),
|
||||||
|
buttons : {"Ok":1}
|
||||||
|
}).then(() => { load() });
|
||||||
|
// we have >0 messages
|
||||||
|
// TODO: IF A NEW MESSAGE, SHOW IT
|
||||||
|
if (!forceShowMenu) {
|
||||||
|
var newMessages = MESSAGES.filter(m=>m.new);
|
||||||
|
if (newMessages.length)
|
||||||
|
return showMessage(newMessages[0].id);
|
||||||
|
}
|
||||||
|
// Otherwise show a menu
|
||||||
|
var m = {
|
||||||
|
"":{title:"Messages"},
|
||||||
|
"< Back": ()=>load()
|
||||||
|
};
|
||||||
|
/*g.setFont("6x8");
|
||||||
|
MESSAGES.forEach(msg=>{
|
||||||
|
// "id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"
|
||||||
|
var title = g.wrapString(msg.title, g.getWidth())[0];
|
||||||
|
m[title] = function() {
|
||||||
|
showMessage(msg.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
E.showMenu(m);*/
|
||||||
|
showBigMenu({
|
||||||
|
h : 48,
|
||||||
|
items : MESSAGES.length,
|
||||||
|
draw : showMessageMenuItem,
|
||||||
|
onSelect : idx => showMessage(MESSAGES[idx].id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
checkMessages();
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 917 B |
|
|
@ -0,0 +1,36 @@
|
||||||
|
(function() {
|
||||||
|
var _GB = global.GB;
|
||||||
|
global.GB = (event) => {
|
||||||
|
if (_GB) setTimeout(_GB,0,event);
|
||||||
|
// call handling?
|
||||||
|
if (!event.t.startsWith("notify")) return;
|
||||||
|
/* event is:
|
||||||
|
{t:"notify",id:int, src,title,subject,body,sender,tel:string}
|
||||||
|
{t:"notify~",id:int, title:string} // modified
|
||||||
|
{t:"notify-",id:int} // remove
|
||||||
|
*/
|
||||||
|
var messages, inApp = "undefined"!=typeof MESSAGES;
|
||||||
|
if (inApp)
|
||||||
|
messages = MESSAGES; // we're in an app that has already loaded messages
|
||||||
|
else // no app - load messages
|
||||||
|
messages = require("Storage").readJSON("messages.json",1)||[];
|
||||||
|
// now modify/delete as appropriate
|
||||||
|
var mIdx = messages.findIndex(m=>m.id==event.id);
|
||||||
|
if (event.t=="notify-") {
|
||||||
|
if (mIdx>=0) messages.splice(mIdx, 1); // remove item
|
||||||
|
mIdx=-1;
|
||||||
|
} else { // add/modify
|
||||||
|
if (event.t=="notify") event.new=true; // new message
|
||||||
|
if (mIdx<0) mIdx=messages.push(event)-1;
|
||||||
|
else Object.assign(messages[mIdx], event);
|
||||||
|
}
|
||||||
|
require("Storage").writeJSON("messages.json",messages);
|
||||||
|
if (inApp) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]);
|
||||||
|
// ok, saved now - we only care if it's new
|
||||||
|
if (event.t!="notify") return;
|
||||||
|
// if we're in a clock, go straight to messages app
|
||||||
|
if (Bangle.CLOCK) return load("messages.app.js");
|
||||||
|
if (!global.WIDGETS || !WIDGETS.messages) return Bangle.buzz(); // no widgets - just buzz to let someone know
|
||||||
|
WIDGETS.messages.newMessage();
|
||||||
|
};
|
||||||
|
})()
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
WIDGETS["messages"]={area:"tl",width:0,draw:function() {
|
||||||
|
if (!this.width) return;
|
||||||
|
var c = (Date.now()-this.t)/1000;
|
||||||
|
g.reset().setBgColor((c&1) ? "#0f0" : "#030").setColor((c&1) ? "#000" : "#fff");
|
||||||
|
g.clearRect(this.x,this.y,this.x+this.width,this.y+23);
|
||||||
|
g.setFont("6x8:1x2").setFontAlign(0,0).drawString("MESSAGES", this.x+this.width/2, this.y+12);
|
||||||
|
//if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute
|
||||||
|
if (c<120 && (Date.now()-this.l)>4000) {
|
||||||
|
this.l = Date.now();
|
||||||
|
Bangle.buzz(); // buzz every 4 seconds
|
||||||
|
}
|
||||||
|
setTimeout(()=>WIDGETS["messages"].draw(), 1000);
|
||||||
|
},newMessage:function() {
|
||||||
|
WIDGETS["messages"].t=Date.now(); // first time
|
||||||
|
WIDGETS["messages"].l=Date.now()-10000; // last buzz
|
||||||
|
if (WIDGETS["messages"].c!==undefined) return; // already called
|
||||||
|
WIDGETS["messages"].width=64;
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
Bangle.setLCDPower(1);// turns screen on
|
||||||
|
}};
|
||||||
|
|
@ -5,3 +5,4 @@
|
||||||
0.06: Use 'g.theme' (requires bootloader 0.23)
|
0.06: Use 'g.theme' (requires bootloader 0.23)
|
||||||
0.07: Move CHARGING variable to more readable string
|
0.07: Move CHARGING variable to more readable string
|
||||||
0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on
|
0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on
|
||||||
|
0.09: Misc speed/memory tweaks
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,11 @@
|
||||||
(function(){
|
(function(){
|
||||||
|
|
||||||
function setWidth() {
|
function setWidth() {
|
||||||
WIDGETS["bat"].width = 40 + (Bangle.isCharging()?16:0);
|
WIDGETS["bat"].width = 40 + (Bangle.isCharging()?16:0);
|
||||||
}
|
}
|
||||||
function draw() {
|
|
||||||
var s = 39;
|
|
||||||
var x = this.x, y = this.y;
|
|
||||||
g.reset();
|
|
||||||
if (Bangle.isCharging()) {
|
|
||||||
g.setColor("#0f0").drawImage(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
|
|
||||||
x+=16;
|
|
||||||
}
|
|
||||||
g.setColor(g.theme.fg);
|
|
||||||
g.fillRect(x,y+2,x+s-4,y+21);
|
|
||||||
g.clearRect(x+2,y+4,x+s-6,y+19);
|
|
||||||
g.fillRect(x+s-3,y+10,x+s,y+14);
|
|
||||||
g.setColor("#0f0").fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);
|
|
||||||
}
|
|
||||||
Bangle.on('charging',function(charging) {
|
Bangle.on('charging',function(charging) {
|
||||||
if(charging) Bangle.buzz();
|
if(charging) Bangle.buzz();
|
||||||
setWidth();
|
setWidth();
|
||||||
Bangle.drawWidgets(); // relayout widgets
|
Bangle.drawWidgets(); // re-layout widgets
|
||||||
g.flip();
|
g.flip();
|
||||||
});
|
});
|
||||||
var batteryInterval = Bangle.isLCDOn() ? setInterval(()=>WIDGETS["bat"].draw(), 60000) : undefined;
|
var batteryInterval = Bangle.isLCDOn() ? setInterval(()=>WIDGETS["bat"].draw(), 60000) : undefined;
|
||||||
|
|
@ -37,6 +22,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
WIDGETS["bat"]={area:"tr",width:40,draw:draw};
|
WIDGETS["bat"]={area:"tr",width:40,draw:function() {
|
||||||
|
var s = 39;
|
||||||
|
var x = this.x, y = this.y;
|
||||||
|
g.reset();
|
||||||
|
if (Bangle.isCharging()) {
|
||||||
|
g.setColor("#0f0").drawImage(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
|
||||||
|
x+=16;
|
||||||
|
}
|
||||||
|
g.setColor(g.theme.fg).fillRect(x,y+2,x+s-4,y+21).clearRect(x+2,y+4,x+s-6,y+19).fillRect(x+s-3,y+10,x+s,y+14);
|
||||||
|
g.setColor("#0f0").fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);
|
||||||
|
}};
|
||||||
setWidth();
|
setWidth();
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 280 B |
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New widget
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
Bangle.on('charging',function(charging) {
|
||||||
|
if(charging) Bangle.buzz();
|
||||||
|
WIDGETS["batv"].draw();
|
||||||
|
});
|
||||||
|
setInterval(()=>WIDGETS["batv"].draw(), 60000);
|
||||||
|
Bangle.on('lcdPower', function(on) {
|
||||||
|
if (on) WIDGETS["batv"].draw(); // refresh at power on
|
||||||
|
});
|
||||||
|
WIDGETS["batv"]={area:"tr",width:14,draw:function() {
|
||||||
|
var x = this.x, y = this.y;
|
||||||
|
g.reset();
|
||||||
|
if (Bangle.isCharging()) {
|
||||||
|
g.setColor("#0f0").drawImage(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
|
||||||
|
} else {
|
||||||
|
g.clearRect(x,y,x+14,y+24);
|
||||||
|
g.setColor(g.theme.fg).fillRect(x+2,y+2,x+12,y+22).clearRect(x+4,y+4,x+10,y+20).fillRect(x+5,y+1,x+9,y+2);
|
||||||
|
g.setColor("#0f0").fillRect(x+4,y+20-(E.getBattery()*16/100),x+10,y+20);
|
||||||
|
}
|
||||||
|
}};
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 221 B |
|
|
@ -3,3 +3,4 @@
|
||||||
0.04: Fix automatic update of Bluetooth connection status
|
0.04: Fix automatic update of Bluetooth connection status
|
||||||
0.05: Make Bluetooth widget thinner, and when on a bright theme use light grey for disabled color
|
0.05: Make Bluetooth widget thinner, and when on a bright theme use light grey for disabled color
|
||||||
0.06: Tweaking colors for dark/light themes and low bpp screens
|
0.06: Tweaking colors for dark/light themes and low bpp screens
|
||||||
|
0.07: Memory usage improvements
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
(function(){
|
WIDGETS["bluetooth"]={area:"tr",width:15,draw:function() {
|
||||||
function draw() {
|
|
||||||
g.reset();
|
g.reset();
|
||||||
if (NRF.getSecurityStatus().connected)
|
if (NRF.getSecurityStatus().connected)
|
||||||
g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f"));
|
g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f"));
|
||||||
else
|
else
|
||||||
g.setColor(g.theme.dark ? "#666" : "#999");
|
g.setColor(g.theme.dark ? "#666" : "#999");
|
||||||
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),2+this.x,2+this.y);
|
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),2+this.x,2+this.y);
|
||||||
}
|
},changed:function() {
|
||||||
function changed() {
|
|
||||||
WIDGETS["bluetooth"].draw();
|
WIDGETS["bluetooth"].draw();
|
||||||
g.flip();// turns screen on
|
Bangle.setLCDPower(1); // turn screen on
|
||||||
}
|
}};
|
||||||
NRF.on('connect',changed);
|
NRF.on('connect',WIDGETS["bluetooth"].changed);
|
||||||
NRF.on('disconnect',changed);
|
NRF.on('disconnect',WIDGETS["bluetooth"].changed);
|
||||||
WIDGETS["bluetooth"]={area:"tr",width:15,draw:draw};
|
|
||||||
})()
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.01: New Widget!
|
0.01: New Widget!
|
||||||
|
0.02: Theme support, memory savings
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
/* jshint esversion: 6 */
|
|
||||||
(() => {
|
|
||||||
const CBS = 0x41f, CBC = 0x07E0;
|
|
||||||
var xo = 6, xl = 22, yo = 9, h = 17;
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
g.reset().setColor(CBS).drawImage(require("heatshrink").decompress(atob("j0TwIHEv///kD////EfAYPwuEAgPB4EAg/HCgMfzgDBvwOC/IOC84ONDoUcFgc/AYOAHYRDE")), this.x + 1, this.y + 4);
|
|
||||||
g.setColor(0).fillRect(this.x + xo, this.y + yo, this.x + xl, this.y + h);
|
|
||||||
var cbc = (Bangle.isCharging()) ? CBC : CBS;
|
|
||||||
g.setColor(cbc).fillRect(this.x + xo, this.y + yo, this.x + (xl - xo) / 100 * E.getBattery() + xo, this.y + h);
|
|
||||||
}
|
|
||||||
Bangle.on('charging', function(charging) {
|
Bangle.on('charging', function(charging) {
|
||||||
if (charging) Bangle.buzz();
|
if (charging) Bangle.buzz();
|
||||||
Bangle.drawWidgets();
|
WIDGETS["widtbat"].draw();
|
||||||
});
|
});
|
||||||
WIDGETS["widtbat"] = { area:"tr", width:32, draw: draw };
|
WIDGETS["widtbat"] = { area:"tr", width:32, draw: function() {
|
||||||
})();
|
const xo = 6, xl = 22, yo = 9, h = 17;
|
||||||
|
g.reset().setColor("#08f").drawImage(require("heatshrink").decompress(atob("j0TwIHEv///kD////EfAYPwuEAgPB4EAg/HCgMfzgDBvwOC/IOC84ONDoUcFgc/AYOAHYRDE")), this.x + 1, this.y + 4);
|
||||||
|
g.clearRect(this.x + xo, this.y + yo, this.x + xl, this.y + h);
|
||||||
|
var cbc = (Bangle.isCharging()) ? "#0f0" : "#08f";
|
||||||
|
g.setColor(cbc).fillRect(this.x + xo, this.y + yo, this.x + (xl - xo) / 100 * E.getBattery() + xo, this.y + h);
|
||||||
|
} };
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 238 B |
Loading…
Reference in New Issue