Merge pull request #2186 from rigrig/widmsggrid

new widget: widmsggrid: Messages Grid Widget
pull/2187/head^2
Gordon Williams 2022-10-26 08:50:09 +01:00 committed by GitHub
commit 5c676c78bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1 @@
0.01: New widget!

23
apps/widmsggrid/README.md Normal file
View File

@ -0,0 +1,23 @@
# Messages Grid Widget
Widget that displays multiple notification icons in a grid.
The widget has a fixed size: if there are multiple notifications it uses smaller
icons.
It shows a single icon per application, so if you have two SMS messages, the
grid only has one SMS icon.
If there are multiple messages waiting, the total number is shown in the
bottom-right corner.
Example: one SMS, one Signal, and two WhatsApp messages:
![screenshot](screenshot.png)
## Installation
This widget needs the [`messages`](/?id=messages) app to handle notifications.
## Settings
This widget uses the `Widget` settings from the `messages` app:
### Widget
* `Flash icon` Toggle flashing of the widget icons.
<!-- * `Show read` - Also show the widget when there are only old messages. -->
* `Widget messages` Not used by this widget, but you should select `Hide` to hide the default widget.

View File

@ -0,0 +1,16 @@
{
"id": "widmsggrid",
"name": "Messages Grid Widget",
"version": "0.01",
"description": "Widget that display notification icons in a grid",
"icon": "widget.png",
"type": "widget",
"dependencies": {"messages":"app"},
"tags": "tool,system",
"supports": ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"widmsggrid.wid.js","url":"widget.js"}
],
"screenshots": [{"url":"screenshot.png"}]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

92
apps/widmsggrid/widget.js Normal file
View File

@ -0,0 +1,92 @@
(function () {
if (global.MESSAGES) return; // don't load widget while in the app
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
const s = {
flash: (settings.flash === undefined) ? true : !!settings.flash,
showRead: !!settings.showRead,
};
delete settings;
WIDGETS["msggrid"] = {
area: "tl", width: 0,
flash: s.flash,
showRead: s.showRead,
init: function() {
// runs on first draw
delete w.init; // don't run again
Bangle.on("touch", w.touch);
Bangle.on("message", w.listener);
w.listener(); // update status now
},
draw: function () {
if (w.init) w.init();
// If we had a setTimeout queued from the last time we were called, remove it
if (w.t) {
clearTimeout(w.t);
delete w.t;
}
if (!w.width) return;
const b = w.flash && w.status === "new" && ((Date.now() / 1000) & 1), // Blink(= inverse colors) on this second?
// show multiple icons in a grid, by scaling them down
cols = Math.ceil(Math.sqrt(w.srcs.length - 0.1)); // cols===rows, -0.1 to work around rounding error
g.reset().clearRect(w.x, w.y, w.x + w.width - 1, w.y + 24)
.setClipRect(w.x, w.y, w.x + w.width - 1, w.y + 24); // guard against oversized icons
let r = 0, c = 0; // row, column
const offset = pos => Math.floor(pos / cols * 24); // pixel offset for position in row/column
w.srcs.forEach(src => {
const appColor = require("messages").getMessageImageCol(src, require("messages").getMessageImageCol("alert"));
let colors = [g.theme.bg, g.setColor(appColor).getColor()];
if (b) {
if (colors[1] == g.theme.fg) colors = colors.reverse();
else colors[1] = g.theme.fg;
}
g.setColor(colors[1]).setBgColor(colors[0]);
g.drawImage(require("messages").getMessageImage(src, "alert"), w.x+offset(c), w.y+offset(r), { scale: 1 / cols });
if (++c >= cols) {
c = 0;
r++;
}
});
if (w.total > 1) {
// show total number of messages in bottom-right corner
g.reset();
if (w.total < 10) g.fillCircle(w.x + w.width - 5, w.y + 20, 4); // single digits get a round background, double digits fill their rectangle
g.setColor(g.theme.bg).setBgColor(g.theme.fg)
.setFont('6x8').setFontAlign(1, 1)
.drawString(w.total, w.x + w.width - 1, w.y + 24, w.total > 9);
}
if (w.flash && w.status === "new") w.t = setTimeout(w.draw, 1000); // schedule redraw while blinking
}, show: function () {
w.width = 24;
w.srcs = require("messages").getMessages()
.filter(m => !['call', 'map', 'music'].includes(m.id))
.filter(m => m.new || w.showRead)
.map(m => m.src);
w.total = w.srcs.length;
w.srcs = w.srcs.filter((src, i, uniq) => uniq.indexOf(src) === i); // keep unique entries only
Bangle.drawWidgets();
Bangle.setLCDPower(1); // turns screen on
}, hide: function () {
w.width = 0;
w.srcs = [];
w.total = 0;
Bangle.drawWidgets();
}, touch: function (b, c) {
if (!w || !w.width) return; // widget not shown
if (process.env.HWVERSION < 2) {
// Bangle.js 1: open app when on clock we touch the side with widget
if (!Bangle.CLOCK) return;
const m = Bangle.appRect / 2;
if ((w.x < m && b !== 1) || (w.x > m && b !== 2)) return;
}
// Bangle.js 2: open app when touching the widget
else if (c.x < w.x || c.x > w.x + w.width || c.y < w.y || c.y > w.y + 24) return;
load("messages.app.js");
}, listener: function () {
w.status = require("messages").status();
if (w.status === "new" || (w.status === "old" && w.showRead)) w.show();
else w.hide();
}
};
delete s;
const w = WIDGETS["msggrid"];
})();

BIN
apps/widmsggrid/widget.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB