Merge pull request #155 from detached/call-notifications

Adds gbridge call notification and refactor widget
master
Gordon Williams 2020-04-03 13:25:47 +01:00 committed by GitHub
commit 9f3ecbc973
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 174 additions and 103 deletions

View File

@ -2,4 +2,5 @@
0.02: Increase contrast (darker notification background, white text) 0.02: Increase contrast (darker notification background, white text)
0.03: Gadgetbridge widget now shows connection state 0.03: Gadgetbridge widget now shows connection state
0.04: Tweaks for variable size widget system 0.04: Tweaks for variable size widget system
0.05: Optimize animation, limit title length 0.05: Show incoming call notification
Optimize animation, limit title length

View File

@ -1,69 +1,64 @@
(function() { (() => {
var musicState = "stop";
var musicInfo = {"artist":"","album":"","track":""}; const state = {
var scrollPos = 0; music: "stop",
function gb(j) {
Bluetooth.println(JSON.stringify(j)); musicInfo: {
artist: "",
album: "",
track: ""
},
scrollPos: 0
};
function gbSend(message) {
Bluetooth.println(JSON.stringify(message));
} }
function show(size,render) {
function showNotification(size, render) {
var oldMode = Bangle.getLCDMode(); var oldMode = Bangle.getLCDMode();
Bangle.setLCDMode("direct"); Bangle.setLCDMode("direct");
g.setClipRect(0, 240, 239, 319); g.setClipRect(0, 240, 239, 319);
g.setColor("#222222"); g.setColor("#222222");
g.fillRect(1, 241, 238, 318); g.fillRect(1, 241, 238, 318);
render(320 - size); render(320 - size);
g.setColor("#ffffff"); g.setColor("#ffffff");
g.fillRect(0, 240, 1, 319); g.fillRect(0, 240, 1, 319);
g.fillRect(238, 240, 239, 319); g.fillRect(238, 240, 239, 319);
g.fillRect(2, 318, 238, 319); g.fillRect(2, 318, 238, 319);
Bangle.setLCDPower(1); // light up Bangle.setLCDPower(1); // light up
Bangle.setLCDMode(oldMode); // clears cliprect Bangle.setLCDMode(oldMode); // clears cliprect
function anim() { function anim() {
scrollPos-=2; state.scrollPos -= 2;
if (scrollPos<-size) scrollPos=-size; if (state.scrollPos < -size) {
Bangle.setLCDOffset(scrollPos); state.scrollPos = -size;
if (scrollPos>-size) setTimeout(anim,15);
} }
anim(); Bangle.setLCDOffset(state.scrollPos);
} if (state.scrollPos > -size) setTimeout(anim, 15);
function hide() {
function anim() {
scrollPos+=4;
if (scrollPos>0) scrollPos=0;
Bangle.setLCDOffset(scrollPos);
if (scrollPos<0) setTimeout(anim,10);
} }
anim(); anim();
} }
Bangle.on('touch',function() { function hideNotification() {
if (scrollPos) hide(); function anim() {
}); state.scrollPos += 4;
Bangle.on('swipe',function(dir) { if (state.scrollPos > 0) state.scrollPos = 0;
if (musicState=="play") { Bangle.setLCDOffset(state.scrollPos);
gb({t:"music",n:dir>0?"next":"previous"}); if (state.scrollPos < 0) setTimeout(anim, 10);
}
anim();
} }
});
gb({t:"status",bat:E.getBattery()});
global.GB = function(j) { function handleNotificationEvent(event) {
switch (j.t) {
case "notify": // split text up at word boundaries
show(80,function(y) { var txt = event.body.split("\n");
// TODO: icon based on src?
var x = 120;
g.setFontAlign(0,0);
g.setFont("6x8",1);
g.setColor("#40d040");
g.drawString(j.src,x,y+7);
g.setColor("#ffffff");
g.setFont("6x8",2);
if (j.title === undefined) g.drawString(j.title,x,y+25);
else g.drawString(j.title.slice(0,17),x,y+25);
g.setFont("6x8",1);
g.setColor("#ffffff");
// split text up a word boundaries
var txt = j.body.split("\n");
var MAXCHARS = 38; var MAXCHARS = 38;
for (var i = 0; i < txt.length; i++) { for (var i = 0; i < txt.length; i++) {
txt[i] = txt[i].trim(); txt[i] = txt[i].trim();
@ -77,36 +72,108 @@
txt.splice(i + 1, 0, l.substr(p)); txt.splice(i + 1, 0, l.substr(p));
} }
} }
showNotification(80, (y) => {
// TODO: icon based on src?
var x = 120;
g.setFontAlign(0, 0);
g.setFont("6x8", 1);
g.setColor("#40d040");
g.drawString(event.src, x, y + 7);
g.setColor("#ffffff");
g.setFont("6x8", 2);
if (event.title)
g.drawString(event.title.slice(0,17), x, y + 25);
g.setFont("6x8", 1);
g.setColor("#ffffff");
g.setFontAlign(-1, -1); g.setFontAlign(-1, -1);
g.drawString(txt.join("\n"), 10, y + 40); g.drawString(txt.join("\n"), 10, y + 40);
Bangle.buzz();
}); });
break;
case "musicinfo": Bangle.buzz();
musicInfo = j; }
break;
case "musicstate": function handleMusicStateUpdate(event) {
musicState = j.state; state.music = event.state
if (musicState=="play")
show(40,function(y) { if (state.music == "play") {
showNotification(40, (y) => {
g.setColor("#ffffff"); g.setColor("#ffffff");
g.drawImage(require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")), 8, y + 8); g.drawImage(require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")), 8, y + 8);
g.setFontAlign(-1, -1); g.setFontAlign(-1, -1);
g.setFont("6x8",1);
var x = 40; var x = 40;
g.setFont("4x6", 2); g.setFont("4x6", 2);
g.setColor("#ffffff"); g.setColor("#ffffff");
g.drawString(musicInfo.artist,x,y+8); g.drawString(state.musicInfo.artist, x, y + 8);
g.setFont("6x8", 1); g.setFont("6x8", 1);
g.setColor("#ffffff"); g.setColor("#ffffff");
g.drawString(musicInfo.track,x,y+22); g.drawString(state.musicInfo.track, x, y + 22);
}); });
if (musicState=="pause") }
hide();
if (state.music == "pause") {
hideNotification();
}
}
function handleCallEvent(event) {
if (event.cmd == "accept") {
showNotification(40, (y) => {
g.setColor("#ffffff");
g.drawImage(require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw=")), 8, y + 8);
g.setFontAlign(-1, -1);
var x = 40;
g.setFont("4x6", 2);
g.setColor("#ffffff");
g.drawString(event.name, x, y + 8);
g.setFont("6x8", 1);
g.setColor("#ffffff");
g.drawString(event.number, x, y + 22);
});
Bangle.buzz();
}
}
global.GB = (event) => {
switch (event.t) {
case "notify":
handleNotificationEvent(event);
break;
case "musicinfo":
state.musicInfo = event;
break;
case "musicstate":
handleMusicStateUpdate(event);
break;
case "call":
handleCallEvent(event);
break; break;
} }
}; };
// Touch control
Bangle.on("touch", () => {
if (state.scrollPos) {
hideNotification();
}
});
Bangle.on("swipe", (dir) => {
if (state.music == "play") {
const command = dir > 0 ? "next" : "previous"
gbSend({ t: "music", n: command });
}
});
function draw() { function draw() {
g.setColor(-1); g.setColor(-1);
if (NRF.getSecurityStatus().connected) if (NRF.getSecurityStatus().connected)
@ -114,13 +181,16 @@ function draw() {
else else
g.drawImage(require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")), this.x + 1, this.y + 1); g.drawImage(require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")), this.x + 1, this.y + 1);
} }
function changed() {
function changedConnectionState() {
WIDGETS["gbridgew"].draw(); WIDGETS["gbridgew"].draw();
g.flip(); // turns screen on g.flip(); // turns screen on
} }
NRF.on('connected',changed);
NRF.on('disconnected',changed); NRF.on("connected", changedConnectionState);
NRF.on("disconnected", changedConnectionState);
WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw }; WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw };
gbSend({ t: "status", bat: E.getBattery() });
})(); })();