add call functionality

master
Bryan 2024-08-09 23:23:14 -06:00
parent 110d93f9da
commit df67d082fa
10 changed files with 218 additions and 63 deletions

BIN
icons8-double-left-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

BIN
icons8-double-right-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

BIN
icons8-incoming-call-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

BIN
icons8-outgoing-call-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

BIN
icons8-phone-ringing-50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

View File

@ -1,3 +1,5 @@
let options = { let options = {
srcFont: "6x8", srcFont: "6x8",
titleFont: "12x20", titleFont: "12x20",
@ -70,11 +72,12 @@ HeaderBox.prototype.draw = function(messageRect) {
let y2 = messageRect.y + this.h - 1; let y2 = messageRect.y + this.h - 1;
exports.setClipRect(x, y, x2, y2); exports.setClipRect(x, y, x2, y2);
g.setBgColor(options.headerBgColor).clearRect(x, y, x2, y2); g.setBgColor(options.headerBgColor).clearRect(x, y, x2, y2);
g.setBgColor(g.theme.bg2).clearRect(x+3, y+3, x2-3, y2-3);
if (this.new) g.setColor(options.headerHlColor).fillPoly([x, y, x + 20, y, x, y + 20]); if (this.new) g.setColor(options.headerHlColor).fillPoly([x, y, x + 20, y, x, y + 20]);
g.setColor(options.headerFgColor); g.setColor(options.headerFgColor);
g.setFont(options.titleFont); g.setFont(options.titleFont);
if (this.h > this.minH) { // multi-line title if (this.h > this.minH) { // multi-line title
let titleY = y; let titleY = y + 3;
if (this.titleLines) { if (this.titleLines) {
for (let line of this.titleLines) { for (let line of this.titleLines) {
centerString(line, x, titleY, this.titleW); centerString(line, x, titleY, this.titleW);
@ -87,14 +90,13 @@ HeaderBox.prototype.draw = function(messageRect) {
} }
g.setFont(options.srcFont); g.setFont(options.srcFont);
if (this.h == this.maxH) { if (this.h == this.maxH) {
let srcY = y; let srcY = y+4;
for (let line of this.srcLines) { for (let line of this.srcLines) {
centerString(line, x2 - this.iconW, srcY, this.iconW); centerString(line, x2 - this.iconW, srcY, this.iconW);
srcY += this.srcLineH; srcY += this.srcLineH;
} }
} }
g.setColor(this.color).drawImage(this.icon, x + this.imgX, y + getImgY()); g.setColor(this.color).drawImage(this.icon, x + this.imgX, y + getImgY());
g.setColor(g.theme.bg).fillRect(x, y2 - 6, x2, y2); // bar at bottom of header
}; };
const TextBox = function(msg, messageRect) { const TextBox = function(msg, messageRect) {
@ -227,33 +229,43 @@ MessageBox.prototype.scroll = function(dy) {
}; };
SwipeBox = function(msg, screenRect) { // SwipeBox = function(msg, screenRect) {
this.screenRect = screenRect; // this.msg = msg;
console.log("screenRect = ", screenRect); // this.screenRect = screenRect;
console.log("this.screenRect = ", this.screenRect); //
this.headerBox = new HeaderBox(msg, screenRect); // console.log("screenRect = ", screenRect);
//this.bodyRect = {x: screenRect.x, y: screenRect.y + headerBox.h, x2: screenRect.x2, y2: screenRect.y2}; // console.log("this.screenRect = ", this.screenRect);
// this.headerBox = new HeaderBox(msg, screenRect);
}; // //this.bodyRect = {x: screenRect.x, y: screenRect.y + headerBox.h, x2: screenRect.x2, y2: screenRect.y2};
//
SwipeBox.prototype.draw = function(xOffset) { // };
const x = this.screenRect.x, y = this.screenRect.y + this.headerBox.h, x2 = this.screenRect.x2, y2 = this.screenRect.y2; //
const w = x2 - x + 1; // SwipeBox.prototype.draw = function(xOffset) {
const yOff = 120 - this.headerBox.h; // const x = this.screenRect.x, y = this.screenRect.y + this.headerBox.h, x2 = this.screenRect.x2, y2 = this.screenRect.y2;
this.headerBox.draw(this.screenRect); // //const w = x2 - x + 1;
g.reset(); // const mx = (x + x2) / 2;
const drawArrows = function (xOffset) { // //const yOff = 127 - this.headerBox.h;
g.setColor(1, 0, 0); // this.headerBox.draw(this.screenRect);
g.fillPoly([x-w+xOffset, y+yOff, x+50+xOffset, y+yOff, x+60+xOffset, y+yOff+25, x+50+xOffset, y+yOff+50, x-w+xOffset, y+yOff+50]); // g.reset();
g.setColor(0, 1, 0); //
g.fillPoly([x2+w+xOffset, y+yOff, x2-50+xOffset, y+yOff, x2-60+xOffset, y+yOff+25, x2-50+xOffset, y+yOff+50, x2+w+xOffset, y+yOff+50]); // // g.setFont("6x15:2").setFontAlign(0,-1);
// // g.drawString(this.msg.body, mx, y);
}; // g.setColor(0,1,0);
drawArrows(xOffset); // g.drawImage(incomingImg, mx-25, y+20);
}; //
// const drawArrows = function(xOffset) {
// g.setColor(1 ,0.25, 0.25);
// g.drawImage(leftImg, x+2, y2-50);
// g.setColor(0, 1, 0);
// g.drawImage(rightImg, x2-50, y2-50);
//
// }
//
// drawArrows(xOffset);
// };
module.exports.HeaderBox = HeaderBox; module.exports.HeaderBox = HeaderBox;
module.exports.MessageBox = MessageBox; module.exports.MessageBox = MessageBox;
module.exports.SwipeBox = SwipeBox; //module.exports.SwipeBox = SwipeBox;
module.exports.setOptions = setOptions; module.exports.setOptions = setOptions;
module.exports.setClipRect = setClipRect; module.exports.setClipRect = setClipRect;

View File

@ -47,6 +47,7 @@ const _cleanup = function() {
for (let e in events) if (e) Bangle.removeListener(e, events[e]); for (let e in events) if (e) Bangle.removeListener(e, events[e]);
for (let t in timeouts) if (timeouts[t]) clearTimeout(timeouts[t]); for (let t in timeouts) if (timeouts[t]) clearTimeout(timeouts[t]);
require("messages").stopBuzz(); require("messages").stopBuzz();
require("widget_utils").show();
}; };
const clearTimeouts = function() { const clearTimeouts = function() {
@ -61,7 +62,7 @@ const showNoMessages = function() {
Bangle.setUI({ Bangle.setUI({
mode: "custom", mode: "custom",
btn: goBack(), btn: _e => goBack(),
remove: cleanup remove: cleanup
}); });
}; };
@ -71,7 +72,7 @@ const showMusic = function(music) {
Bangle.setUI({ Bangle.setUI({
mode: "custom", mode: "custom",
btn: goBack(), btn: _e => goBack()
remove: cleanup remove: cleanup
}); });
}; };
@ -81,7 +82,7 @@ const showMap = function(map) {
Bangle.setUI({ Bangle.setUI({
mode: "custom", mode: "custom",
btn: goBack(), btn: _e => goBack()
remove: cleanup remove: cleanup
}); });
}; };
@ -91,34 +92,85 @@ const showAlarm = function(alarm) {
Bangle.setUI({ Bangle.setUI({
mode: "custom", mode: "custom",
btn: goBack(), btn: _e => goBack()
remove: cleanup remove: cleanup
}); });
}; };
const showCall = function(call) { const showCall = function(call) {
const incomingImg = require("heatshrink").decompress(atob("j0ewIQNgwDCnEAh0B4EAvEOgEB+F//kP4P/+E/weAgH+g8Agf4CQMH8EYgEfEYU8AYV4AQIhBAYMD8ADBg4vBgEPzwDBj/+AYM/AYV//ADCC4X/EwQiCABo="));
const outgoingImg = require("heatshrink").decompress(atob("j0ewIRO4ACBgeAh0Ag8AvEAh0B+F//kP4P/+E/wASB/0AjkD/EA8EH8EDgEfEwU8AYQhBgAhBFwXgAYMHGwUPzwDBj4mBgE/AYV/FQIDBC4X/EwQiCABoA=="));
const ringingImg = require("heatshrink").decompress(atob("mUywIlimAFEhgFEgYSF4AWEAIYWBAIYWBAIcAsAYBgOAgEYCwQJBBwIWBHIXAA4YSC4EGAoICCDwQ8DAQUgAQMQVtsD///AoU/AoIGCv5BBh/4gF+B4UfwF4Dgd4nAFDg8cB4P/8EA9gFC/wgBBwIzBwEDSQaOB+BzCRAM8SQSQBDAKSCTAPADwMAGoPwh4eBg+An0/SQX/jv/TwUH/wlBAAQkBADwA="));
const leftImg = require("heatshrink").decompress(atob("mEwwJC/AAkBgEQAoUDwE4AoUHwF4AoUPgHwAoUegPgAoU8gfAAoV4DAIFC+AYBFwXgjwuD4E8FygFFCIodFFIo1FIIpNGLIowSRIiVFAH4A="));
const rightImg = require("heatshrink").decompress(atob("mEwwJC/AAcIgGAAoUcgPAAoUegPgAoUPgHwAoUHwF4AoUD4E8AoQWBjwqD+AZBAAV4DIIFCngZBGCgFFCIodFFIo1FIIhNFLIouRRIqVFAH8AA=="));
Bangle.setUI(); // clear from previous Bangle.setUI(); // clear from previous
// const HeaderBox = new require("messagebox").HeaderBox; g.reset().clear();
// let header = new HeaderBox(call, Bangle.appRect); msg = call;
g.reset().clear().setFont("12x20") delete msg.new;
// header.draw(Bangle.appRect); if (!msg.name) {
//let str = g.wrapString(JSON.stringify(call),g.getWidth()).join("\n"); let pn = msg.number.replaceAll(/\D/, ""); // remove any non digit characters
//g.drawString(str, 0, 60); msg.title = `${pn.slice(-10, -7)}-${pn.slice(-7,-4)}-${pn.slice(-4)}`;
const SwipeBox = require("messagebox").SwipeBox; }
const swipeBox = new SwipeBox(call, Bangle.appRect); const cmd = msg.cmd;
let xOff = 0;
swipeBox.draw(xOff); const HeaderBox = require("messagebox").HeaderBox;
const handler = function(e) { const headerBox = new HeaderBox(msg, Bangle.appRect);
xOff += e.dx; const x = Bangle.appRect.x, y = Bangle.appRect.y + headerBox.h, x2 = Bangle.appRect.x2, y2 = Bangle.appRect.y2;
console.log(e, xOff); const mx = (x + x2) / 2;
g.clear(); headerBox.draw(Bangle.appRect);
swipeBox.draw(xOff); g.reset();
const drawLeftArrow = function(imgX) {
imgX = imgX ?? x+2;
g.setColor(1 ,0.25, 0.25);
g.drawImage(leftImg, imgX, y2-50);
};
const drawRightArrow = function(imgX) {
imgX = imgX ?? x2-50;
g.setColor(0, 1, 0);
g.drawImage(rightImg, imgX, y2-50);
};
if (cmd === "end") {
if (timeouts.timer) clearTimeout(timeouts.timer);
g.setColor(g.theme.fg).setFont("6x15:2").setFontAlign(0, -1);
g.drawString("Call Ended", mx, y+25);
endTimeout = setTimeout(() => g.clear(), 3000);
}
if (cmd === "incoming") {
drawLeftArrow();
drawRightArrow();
g.setColor(0,1,0);
g.drawImage(ringingImg, mx-25, y+15);
}
if (cmd === "start" || cmd === "outgoing") {
drawLeftArrow(x2 - 52);
startTime = parseInt(Date.now()/1000);
g.setColor(g.theme.fg);
g.drawImage(cmd === "start" ? incomingImg : outgoingImg, x+10, y+20);
const timer = () => {
g.clearRect(mx-45, y+20, mx+70, y+50);
elapsed = parseInt(Date.now()/1000) - startTime;
const h = ("0" + Math.floor((elapsed/3600)%60)).slice(-2);
const m = ("0" + Math.floor((elapsed/60)%60)).slice(-2);
const s = ("0" + Math.floor(elapsed%60)).slice(-2);
g.setFont("Vector:25").setFontAlign(0, -1).drawString(`${h}:${m}:${s}`, mx + 15, y+25);
timeouts.timer = setTimeout(timer, 1000);
};
timer();
}
const handler = function(dir) {
if (cmd === "end") return;
if (dir < 0) return Bangle.messageResponse(msg, false);
else if (dir > 0 && cmd === "incoming") return Bangle.messageResponse(msg, true);
}; };
Bangle.setUI({ Bangle.setUI({
mode: "custom", mode: "custom",
drag: handler, touch: () => {if (buzzing) return require("messages".stopBuzz())},
btn: goBack, swipe: handler,
btn: _e => goBack(),
remove: cleanup remove: cleanup
}); });
}; };
@ -496,6 +548,7 @@ const showText = function(messageNum) {
msgBoxes[messageNum].draw(); msgBoxes[messageNum].draw();
drawFooter(); drawFooter();
idle = true;
checkForNewMessages(); checkForNewMessages();
}; // function showText }; // function showText
@ -608,17 +661,22 @@ const filterMessages = function() {
map = Bangle.MESSAGES.find(m => m.type === "map"); map = Bangle.MESSAGES.find(m => m.type === "map");
music = Bangle.MESSAGES.find(m => m.type === "music"); music = Bangle.MESSAGES.find(m => m.type === "music");
Bangle.MESSAGES = Bangle.MESSAGES.filter(m => m.type === "text"); Bangle.MESSAGES = Bangle.MESSAGES.filter(m => m.type === "text");
let newUnhandledTexts = Bangle.MESSAGES.filter(m => m.new && !m.handled);
let newHandledTexts = Bangle.MESSAGES.filter(m => m.new && m.handled);
let otherTexts = Bangle.MESSAGES.filter(m => !m.new && !m.handled);
Bangle.MESSAGES = [].concat(newUnhandledTexts, newHandledTexts, otherTexts);
}; };
const showMessage = function() { const showMessage = function() {
if (call) {setActive("call"); return showCall(call);} if (call) {setActive("call"); return showCall(call);}
else if (alarm && !alarm.handled) {setActive("alarm"); return showAlarm(alarm);} else if (alarm) {setActive("alarm"); return showAlarm(alarm);}
else if (map && !map.handled) {setActive("map"); return showMap(map);} else if (map) {setActive("map"); return showMap(map);}
else if (music && !music.handled) {setActive("music"); return showMusic(music);} else if (music) {setActive("music"); return showMusic(music);}
else { else {
idx = Bangle.MESSAGES.findIndex(m => !m.handled); idx = Bangle.MESSAGES.findIndex(m => !m.handled);
if (idx >= 0) { if (idx >= 0) {
for (let m of Bangle.MESSAGES) m.handled = true; // set all text messages as handled Bangle.MESSAGES.every(m => m.handled = true); // set all text messages as handled
//for (let m of Bangle.MESSAGES) m.handled = true; // set all text messages as handled
setActive("text"); setActive("text");
return showText(idx); return showText(idx);
} }
@ -627,10 +685,11 @@ const showMessage = function() {
}; };
// entry point // entry point
events.saveMessages = function() { saveMessages = function() {
require("messages").write(Bangle.MESSAGES); require("messages").write(Bangle.MESSAGES);
}; };
E.on("kill", events.saveMessages); //E.on("kill", events.saveMessages);
setListener("kill", saveMessages);
Bangle.loadWidgets(); Bangle.loadWidgets();
require("widget_utils").hide(); require("widget_utils").hide();
@ -639,16 +698,13 @@ if (!Bangle.MESSAGES || !Bangle.MESSAGES.length) {
Bangle.MESSAGES = require("messages").getMessages(); Bangle.MESSAGES = require("messages").getMessages();
} }
if (!Bangle.MESSAGES.length) showNoMessages();
if (Bangle.notify) { // notification arrived that opened the app. This is set in messagecenter.notify.js if (Bangle.notify) { // notification arrived that opened the app. This is set in messagecenter.notify.js
buzzing = true; buzzing = true;
require("messages").buzz(Bangle.MESSAGES[0].src); require("messages").buzz(Bangle.MESSAGES[0].src);
delete Bangle.notify; delete Bangle.notify;
filterMessages();
showMessage();
} else { // user opened the app
if (!Bangle.MESSAGES.length) showNoMessages();
else {
showText(); // show all messages
}
} }
filterMessages();
showMessage();
//} //}

82
messagecenter_call.js Normal file
View File

@ -0,0 +1,82 @@
const showCall = function(call) {
const incomingImg = require("heatshrink").decompress(atob("j0ewIQNgwDCnEAh0B4EAvEOgEB+F//kP4P/+E/weAgH+g8Agf4CQMH8EYgEfEYU8AYV4AQIhBAYMD8ADBg4vBgEPzwDBj/+AYM/AYV//ADCC4X/EwQiCABo="));
const outgoingImg = require("heatshrink").decompress(atob("j0ewIRO4ACBgeAh0Ag8AvEAh0B+F//kP4P/+E/wASB/0AjkD/EA8EH8EDgEfEwU8AYQhBgAhBFwXgAYMHGwUPzwDBj4mBgE/AYV/FQIDBC4X/EwQiCABoA=="));
const ringingImg = require("heatshrink").decompress(atob("mUywIlimAFEhgFEgYSF4AWEAIYWBAIYWBAIcAsAYBgOAgEYCwQJBBwIWBHIXAA4YSC4EGAoICCDwQ8DAQUgAQMQVtsD///AoU/AoIGCv5BBh/4gF+B4UfwF4Dgd4nAFDg8cB4P/8EA9gFC/wgBBwIzBwEDSQaOB+BzCRAM8SQSQBDAKSCTAPADwMAGoPwh4eBg+An0/SQX/jv/TwUH/wlBAAQkBADwA="));
const leftImg = require("heatshrink").decompress(atob("mEwwJC/AAkBgEQAoUDwE4AoUHwF4AoUPgHwAoUegPgAoU8gfAAoV4DAIFC+AYBFwXgjwuD4E8FygFFCIodFFIo1FIIpNGLIowSRIiVFAH4A="));
const rightImg = require("heatshrink").decompress(atob("mEwwJC/AAcIgGAAoUcgPAAoUegPgAoUPgHwAoUHwF4AoUD4E8AoQWBjwqD+AZBAAV4DIIFCngZBGCgFFCIodFFIo1FIIhNFLIouRRIqVFAH8AA=="));
Bangle.setUI(); // clear from previous
g.reset().clear();
msg = call;
delete msg.new;
if (!msg.name) {
let pn = msg.number.replaceAll(/\D/, ""); // remove any non digit characters
msg.title = `${pn.slice(-10, -7)}-${pn.slice(-7,-4)}-${pn.slice(-4)}`;
}
const cmd = msg.cmd;
const HeaderBox = require("messagebox").HeaderBox;
const headerBox = new HeaderBox(msg, Bangle.appRect);
const x = Bangle.appRect.x, y = Bangle.appRect.y + headerBox.h, x2 = Bangle.appRect.x2, y2 = Bangle.appRect.y2;
const mx = (x + x2) / 2;
let timerInt; //TODO deal with this
headerBox.draw(Bangle.appRect);
g.reset();
const drawLeftArrow = function(imgX) {
imgX = imgX ?? x+2;
g.setColor(1 ,0.25, 0.25);
g.drawImage(leftImg, imgX, y2-50);
};
const drawRightArrow = function(imgX) {
imgX = imgX ?? x2-50;
g.setColor(0, 1, 0);
g.drawImage(rightImg, imgX, y2-50);
};
if (cmd === "end") {
if (timerInt) clearTimeout(timerInt); //TODO change timerInt variable
g.setColor(g.theme.fg).setFont("6x15:2").setFontAlign(0, -1);
g.drawString("Call Ended", mx, y+25);
endTimeout = setTimeout(() => g.clear(), 3000);
}
if (cmd === "incoming") {
drawLeftArrow();
drawRightArrow();
g.setColor(0,1,0);
g.drawImage(ringingImg, mx-25, y+15);
}
if (cmd === "start" || cmd === "outgoing") {
drawLeftArrow(x2 - 52);
startTime = parseInt(Date.now()/1000);
g.setColor(g.theme.fg);
g.drawImage(cmd === "start" ? incomingImg : outgoingImg, x+10, y+20);
const timer = () => {
g.clearRect(mx-45, y+20, mx+70, y+50);
elapsed = parseInt(Date.now()/1000) - startTime;
const h = ("0" + Math.floor((elapsed/3600)%60)).slice(-2);
const m = ("0" + Math.floor((elapsed/60)%60)).slice(-2);
const s = ("0" + Math.floor(elapsed%60)).slice(-2);
g.setFont("Vector:25").setFontAlign(0, -1).drawString(`${h}:${m}:${s}`, mx + 15, y+25);
timerInt = setTimeout(timer, 1000); //TODO put into intervals object
};
timer();
}
const handler = function(dir) {
}
Bangle.setUI({
mode: "custom",
swipe: handler,
btn: () => {clearInterval(timerInt)}
});
};
let msg = {"t":"call","cmd":"start","name":"","number":"1306-7740297","id":"call","src":"Phone","positive":true,"negative":true,"title":"Hayley Thiessen, Wifey","body":"Incoming call\n13067740297","new":true,"show":true,"type":"call"}
g.reset();
showCall(msg);

View File

@ -32,4 +32,9 @@ exports.messageListener = function(type, msg) {
} else { } else {
Bangle.emit("breakingnews", type, msg); Bangle.emit("breakingnews", type, msg);
} }
} }; // messageListener
exports.open = function(msg) {
Bangle.load("messagecenter.app.js");
};