diff --git a/icons8-double-left-48.png b/icons8-double-left-48.png new file mode 100644 index 0000000..9bd63af Binary files /dev/null and b/icons8-double-left-48.png differ diff --git a/icons8-double-right-48.png b/icons8-double-right-48.png new file mode 100644 index 0000000..e5aee7b Binary files /dev/null and b/icons8-double-right-48.png differ diff --git a/icons8-incoming-call-30.png b/icons8-incoming-call-30.png new file mode 100644 index 0000000..72065ec Binary files /dev/null and b/icons8-incoming-call-30.png differ diff --git a/icons8-outgoing-call-30.png b/icons8-outgoing-call-30.png new file mode 100644 index 0000000..d05bbca Binary files /dev/null and b/icons8-outgoing-call-30.png differ diff --git a/icons8-phone-ringing-50.png b/icons8-phone-ringing-50.png new file mode 100644 index 0000000..2c7a444 Binary files /dev/null and b/icons8-phone-ringing-50.png differ diff --git a/icons8-phone-ringing-outline-50.png b/icons8-phone-ringing-outline-50.png new file mode 100644 index 0000000..7a7e445 Binary files /dev/null and b/icons8-phone-ringing-outline-50.png differ diff --git a/messagebox.lib.js b/messagebox.lib.js index 75d7c60..a71529e 100644 --- a/messagebox.lib.js +++ b/messagebox.lib.js @@ -1,3 +1,5 @@ + + let options = { srcFont: "6x8", titleFont: "12x20", @@ -70,11 +72,12 @@ HeaderBox.prototype.draw = function(messageRect) { let y2 = messageRect.y + this.h - 1; exports.setClipRect(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]); g.setColor(options.headerFgColor); g.setFont(options.titleFont); if (this.h > this.minH) { // multi-line title - let titleY = y; + let titleY = y + 3; if (this.titleLines) { for (let line of this.titleLines) { centerString(line, x, titleY, this.titleW); @@ -87,14 +90,13 @@ HeaderBox.prototype.draw = function(messageRect) { } g.setFont(options.srcFont); if (this.h == this.maxH) { - let srcY = y; + let srcY = y+4; for (let line of this.srcLines) { centerString(line, x2 - this.iconW, srcY, this.iconW); srcY += this.srcLineH; } } 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) { @@ -227,33 +229,43 @@ MessageBox.prototype.scroll = function(dy) { }; -SwipeBox = function(msg, screenRect) { - this.screenRect = screenRect; - console.log("screenRect = ", screenRect); - 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; - const yOff = 120 - this.headerBox.h; - this.headerBox.draw(this.screenRect); - g.reset(); - const drawArrows = function (xOffset) { - g.setColor(1, 0, 0); - 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.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]); - - }; - drawArrows(xOffset); -}; +// SwipeBox = function(msg, screenRect) { +// this.msg = msg; +// this.screenRect = screenRect; +// +// console.log("screenRect = ", screenRect); +// 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; +// const mx = (x + x2) / 2; +// //const yOff = 127 - this.headerBox.h; +// this.headerBox.draw(this.screenRect); +// g.reset(); +// +// // g.setFont("6x15:2").setFontAlign(0,-1); +// // g.drawString(this.msg.body, mx, y); +// g.setColor(0,1,0); +// 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.MessageBox = MessageBox; -module.exports.SwipeBox = SwipeBox; +//module.exports.SwipeBox = SwipeBox; module.exports.setOptions = setOptions; module.exports.setClipRect = setClipRect; diff --git a/messagecenter.app.js b/messagecenter.app.js index 8cb9edd..76039c3 100644 --- a/messagecenter.app.js +++ b/messagecenter.app.js @@ -47,6 +47,7 @@ const _cleanup = function() { for (let e in events) if (e) Bangle.removeListener(e, events[e]); for (let t in timeouts) if (timeouts[t]) clearTimeout(timeouts[t]); require("messages").stopBuzz(); + require("widget_utils").show(); }; const clearTimeouts = function() { @@ -61,7 +62,7 @@ const showNoMessages = function() { Bangle.setUI({ mode: "custom", - btn: goBack(), + btn: _e => goBack(), remove: cleanup }); }; @@ -71,7 +72,7 @@ const showMusic = function(music) { Bangle.setUI({ mode: "custom", - btn: goBack(), + btn: _e => goBack() remove: cleanup }); }; @@ -81,7 +82,7 @@ const showMap = function(map) { Bangle.setUI({ mode: "custom", - btn: goBack(), + btn: _e => goBack() remove: cleanup }); }; @@ -91,34 +92,85 @@ const showAlarm = function(alarm) { Bangle.setUI({ mode: "custom", - btn: goBack(), + btn: _e => goBack() remove: cleanup }); }; 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 - // const HeaderBox = new require("messagebox").HeaderBox; - // let header = new HeaderBox(call, Bangle.appRect); - g.reset().clear().setFont("12x20") - // header.draw(Bangle.appRect); - //let str = g.wrapString(JSON.stringify(call),g.getWidth()).join("\n"); - //g.drawString(str, 0, 60); - const SwipeBox = require("messagebox").SwipeBox; - const swipeBox = new SwipeBox(call, Bangle.appRect); - let xOff = 0; - swipeBox.draw(xOff); - const handler = function(e) { - xOff += e.dx; - console.log(e, xOff); - g.clear(); - swipeBox.draw(xOff); + 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; + 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 (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({ mode: "custom", - drag: handler, - btn: goBack, + touch: () => {if (buzzing) return require("messages".stopBuzz())}, + swipe: handler, + btn: _e => goBack(), remove: cleanup }); }; @@ -496,6 +548,7 @@ const showText = function(messageNum) { msgBoxes[messageNum].draw(); drawFooter(); + idle = true; checkForNewMessages(); }; // function showText @@ -608,17 +661,22 @@ const filterMessages = function() { map = Bangle.MESSAGES.find(m => m.type === "map"); music = Bangle.MESSAGES.find(m => m.type === "music"); 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() { if (call) {setActive("call"); return showCall(call);} - else if (alarm && !alarm.handled) {setActive("alarm"); return showAlarm(alarm);} - else if (map && !map.handled) {setActive("map"); return showMap(map);} - else if (music && !music.handled) {setActive("music"); return showMusic(music);} + else if (alarm) {setActive("alarm"); return showAlarm(alarm);} + else if (map) {setActive("map"); return showMap(map);} + else if (music) {setActive("music"); return showMusic(music);} else { idx = Bangle.MESSAGES.findIndex(m => !m.handled); 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"); return showText(idx); } @@ -627,10 +685,11 @@ const showMessage = function() { }; // entry point -events.saveMessages = function() { +saveMessages = function() { require("messages").write(Bangle.MESSAGES); }; -E.on("kill", events.saveMessages); +//E.on("kill", events.saveMessages); +setListener("kill", saveMessages); Bangle.loadWidgets(); require("widget_utils").hide(); @@ -639,16 +698,13 @@ if (!Bangle.MESSAGES || !Bangle.MESSAGES.length) { 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 buzzing = true; require("messages").buzz(Bangle.MESSAGES[0].src); delete Bangle.notify; - filterMessages(); - showMessage(); -} else { // user opened the app - if (!Bangle.MESSAGES.length) showNoMessages(); - else { - showText(); // show all messages - } } +filterMessages(); +showMessage(); //} diff --git a/messagecenter_call.js b/messagecenter_call.js new file mode 100644 index 0000000..4621ab6 --- /dev/null +++ b/messagecenter_call.js @@ -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); + diff --git a/messagegui.lib.js b/messagegui.lib.js index d34176a..0f15b39 100644 --- a/messagegui.lib.js +++ b/messagegui.lib.js @@ -32,4 +32,9 @@ exports.messageListener = function(type, msg) { } else { Bangle.emit("breakingnews", type, msg); } -} +}; // messageListener + + +exports.open = function(msg) { + Bangle.load("messagecenter.app.js"); +};