From 136c73a85fde5504d5e660649fd9a8ebd73c822e Mon Sep 17 00:00:00 2001 From: Bryan Date: Sat, 10 Aug 2024 22:34:23 -0600 Subject: [PATCH] tweak swipe animations, use UI swipe mode for left right swipes to try to make it feel snappier, fix scrolling issues --- messagebox.lib.js | 68 +++------- messagecenter.app.js | 283 ++++++++++++++++++++++++++---------------- messagecenter_call.js | 74 ++++++++--- messagegui.lib.js | 2 +- 4 files changed, 246 insertions(+), 181 deletions(-) diff --git a/messagebox.lib.js b/messagebox.lib.js index a71529e..dfd0fb3 100644 --- a/messagebox.lib.js +++ b/messagebox.lib.js @@ -1,5 +1,3 @@ - - let options = { srcFont: "6x8", titleFont: "12x20", @@ -32,8 +30,8 @@ const centerString = (str, x, y, w) => { HeaderBox = function(msg, messageRect) { this.icon = require("messageicons").getImage(msg); this.color = require("messageicons").getColor(msg, {default:g.theme.fg2}); - this.iconW = 48; - this.titleW = messageRect.w - this.iconW; + this.iconSize = 48; + this.titleW = messageRect.w - this.iconSize; if (!msg.body) this.titleLines = ""; else { this.titleLines = (() => { @@ -50,14 +48,14 @@ HeaderBox = function(msg, messageRect) { this.titleX = 0; this.titleY = 0; this.srcLineH = g.setFont(options.srcFont).getFontHeight(); - this.srcLines = g.wrapString(msg.src, this.iconW); + this.srcLines = g.wrapString(msg.src, this.iconSize); this.srcH = this.srcLineH * this.srcLines.length; - this.srcX = this.x2 - this.iconW; + this.srcX = this.x2 - this.iconSize; this.srcY = 0; this.im = g.imageMetrics(this.icon); - this.imgX = this.titleW + ((this.iconW - this.im.width) / 2); + this.imgX = this.titleW + ((this.iconSize - this.im.width) / 2); this.minH = Math.max(this.titleLineH, this.srcH + this.im.height) + options.padding; - this.maxH = Math.max(this.titleLineH * this.titleLines.length, this.iconW) + options.padding; + this.maxH = Math.max(this.titleLineH * this.titleLines.length, this.iconSize) + options.padding; this.h = this.maxH; this.new = msg.new ?? false; }; // HeaderBox @@ -77,7 +75,7 @@ HeaderBox.prototype.draw = function(messageRect) { g.setColor(options.headerFgColor); g.setFont(options.titleFont); if (this.h > this.minH) { // multi-line title - let titleY = y + 3; + let titleY = Math.floor(((this.h - options.padding - (this.titleLineH * this.titleLines.length)) / 2) + y); if (this.titleLines) { for (let line of this.titleLines) { centerString(line, x, titleY, this.titleW); @@ -92,7 +90,7 @@ HeaderBox.prototype.draw = function(messageRect) { if (this.h == this.maxH) { let srcY = y+4; for (let line of this.srcLines) { - centerString(line, x2 - this.iconW, srcY, this.iconW); + centerString(line, x2 - this.iconSize, srcY, this.iconSize); srcY += this.srcLineH; } } @@ -107,8 +105,7 @@ const TextBox = function(msg, messageRect) { if (msg.subject) { // If there's a subject, add it to the top lines.splice(0, 0, msg.subject); } - this.initScrollY = 0; - this.scrollY = this.initScrollY; + this.scrollY = 0; this.minY = messageRect.y2 - (this.lineH * (this.lines.length + 3)); if (this.minY > 0) this.minY = 0; }; // TextBox @@ -144,7 +141,7 @@ MessageBox = function(msg, yOffset) { this.headerBox = new HeaderBox(msg, this.rect); this.textBox = new TextBox(msg, this.rect); let messageH = this.textBox.lines.length * this.textBox.lineH; - let boxH = this.rect.h - this.headerBox.maxH; + let boxH = this.rect.h - this.headerBox.maxH - options.fh; if ( messageH <= boxH) this.oneScreen = true; else this.oneScreen = false; this.top = true; @@ -155,6 +152,7 @@ MessageBox = function(msg, yOffset) { this.bottom = false; this.textBox.initScrollY = 0; } + this.textBox.scrollY = this.textBox.initScrollY; this.sbH = this.rect.h / messageH * this.rect.h; // scrollbar height this.sbRatio = (this.rect.h - this.sbH) / Math.abs(this.textBox.minY); // scrollbar ratio }; // MessageBox @@ -201,9 +199,10 @@ MessageBox.prototype.drawScrollbar = function() { }; MessageBox.prototype.scroll = function(dy) { - if ((dy > 0 && this.top) || (dy < 0 && this.bottom)) { - return; - } + if (this.oneScreen) return; + // if ((dy > 0 && this.top) || (dy < 0 && this.bottom)) { + // return; + // } if (this.headerBox.h > this.headerBox.minH && dy < 0) { this.headerBox.h += dy; if (this.headerBox.h < this.headerBox.minH) this.headerBox.h = this.headerBox.minH; @@ -228,44 +227,7 @@ MessageBox.prototype.scroll = function(dy) { this.draw(); }; - -// 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.setOptions = setOptions; module.exports.setClipRect = setClipRect; diff --git a/messagecenter.app.js b/messagecenter.app.js index 76039c3..51e1fe8 100644 --- a/messagecenter.app.js +++ b/messagecenter.app.js @@ -1,9 +1,9 @@ //{ - //let settings = require('Storage').readJSON("messages.settings.json", true) || {}; - //const settings = () => require("messagegui").settings(); - const fontTiny = "6x8"; // fixed size, don't use this for important things - let fontNormal; + // let settings = require('Storage').readJSON("messages.settings.json", true) || {}; + // const settings = () => require("messagegui").settings(); + // let fontTiny = "6x8"; // fixed size, don't use this for important things + // let fontNormal; // setFont() is also called after we close the settings screen // const setFont = function() { // const fontSize = settings().fontSize; @@ -45,13 +45,15 @@ const setListener = function(event, callback) { 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]); + console.log(timeouts); + for (let t in timeouts) clearTimeout(timeouts[t]); require("messages").stopBuzz(); require("widget_utils").show(); + Bangle.drawWidgets(); }; const clearTimeouts = function() { - for (let t in timeouts) if (timeouts[t]) clearTimeout(timeouts[t]); + for (let t in timeouts) clearTimeout(timeouts[t]); }; const showNoMessages = function() { @@ -120,31 +122,44 @@ const showCall = function(call) { 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; + const drawAcceptArrow = function(xOffset) { + xOffset = xOffset??0; + imgX = x + 2 + xOffset; g.setColor(0, 1, 0); g.drawImage(rightImg, imgX, y2-50); + //if (xOffset > 0) g.fillRect(imgX+3, y2-43, x, y2-9); }; + const drawRejectArrow = function(xOffset) { + xOffset = xOffset??0; + let imgX = x2 - 50 - xOffset; + g.setColor(1, 0.25, 0.25); + g.drawImage(leftImg, imgX, y2-50); + //if (xOffset > 0) g.fillRect(imgX+45, y2-43, x2, y2-9); + }; + if (cmd === "end") { + console.log("end"); if (timeouts.timer) clearTimeout(timeouts.timer); + let elapsedString = Bangle.elapsedString; + delete Bangle.elapsedString; g.setColor(g.theme.fg).setFont("6x15:2").setFontAlign(0, -1); - g.drawString("Call Ended", mx, y+25); - endTimeout = setTimeout(() => g.clear(), 3000); + g.setFont("Vector:25").setFontAlign(0, -1).drawString(elapsedString, mx, y+25); + g.drawString("Call Ended", mx, y); + + const done = new Promise((resolve, _reject) => { + setTimeout(() => {resolve();}, 5000); + }); + done.then(goBack); } if (cmd === "incoming") { - drawLeftArrow(); - drawRightArrow(); + drawRejectArrow(); + drawAcceptArrow(); g.setColor(0,1,0); g.drawImage(ringingImg, mx-25, y+15); } if (cmd === "start" || cmd === "outgoing") { - drawLeftArrow(x2 - 52); + drawRejectArrow(); startTime = parseInt(Date.now()/1000); g.setColor(g.theme.fg); g.drawImage(cmd === "start" ? incomingImg : outgoingImg, x+10, y+20); @@ -154,23 +169,62 @@ const showCall = function(call) { 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); + Bangle.elapsedString = `${h}:${m}:${s}`; + g.setFont("Vector:25").setFontAlign(0, -1).drawString(Bangle.elapsedString, 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); + if (dir < 0) leftHandler(dir); + else if (dir > 0 && cmd === "incoming") rightHandler(); + }; + + const leftHandler = function(dir) { + let xOff = 0; + const animate = new Promise((resolve, _reject) => { + const swipeAnimation = () => { + xOff += 30; + g.clearRect(x, y2-50, x2, y2); + drawRejectArrow(xOff); + if (xOff > 160) return resolve(); + else setTimeout(swipeAnimation, 30); + } + swipeAnimation(); + }); + animate.then(() => { + if (timeouts.timer) clearTimeout(timeouts["timer"]); + Bangle.messageResponse(msg, false); + goBack(); + }); + }; + + const rightHandler = function(dir) { + let xOff = 0; + const animate = new Promise((resolve, _reject) => { + const swipeAnimation = () => { + xOff += 30; + g.clearRect(x, y2-50, x2, y2); + drawAcceptArrow(xOff); + if (xOff > 160) return resolve(); + else setTimeout(swipeAnimation, 30); + } + swipeAnimation(); + }); + animate.then(() => { + if (timeouts.timer) clearTimeout(timeouts["timer"]); + Bangle.messageResponse(msg, true); + goBack(); + }); }; Bangle.setUI({ mode: "custom", - touch: () => {if (buzzing) return require("messages".stopBuzz())}, + touch: () => {if (buzzing) return require("messages").stopBuzz()}, swipe: handler, - btn: _e => goBack(), + btn: _e => goBack, remove: cleanup }); }; @@ -179,8 +233,8 @@ const showText = function(messageNum) { g.reset().clear(); if (!Bangle.MESSAGES.length) return goBack(); // no messages setBusy(); // busy until everything is set up - let showAll = false; - if (messageNum === undefined) {messageNum = 0; showAll = true;} + //let showAll = false; + if (messageNum === undefined) {messageNum = 0;} //showAll = true;} else if (messageNum >= Bangle.MESSAGES.length - 1) messageNum = Bangle.MESSAGES.length - 1; Bangle.setUI(); // make sure to clear setUI from anything previous let switching = false; @@ -188,19 +242,19 @@ const showText = function(messageNum) { require("messagebox").setOptions({fh: 20}); const step = 42; const delay = 30; - const swipeThreshold = 20; + //const swipeThreshold = 20; let mode = "scroll"; // one of "scroll", "next", "prev" (switch to next/prev message), "swipe" (swipe to delete or archive) msgIdx = messageNum; // global message index // TODO we might have to append array of (m.show && !m.new) to array of m.new so that all new messages are at the beginning of list - let messageList = showAll ? Bangle.MESSAGES : Bangle.MESSAGES.filter(m => m.new || m.show); - if (!messageList.length) return goBack(); + //let messageList = showAll ? Bangle.MESSAGES : Bangle.MESSAGES.filter(m => m.new || m.show || !m.handled); + //if (!messageList.length) return goBack(); // Bangle.setLocked(false); // TODO make as option // Bangle.setLCDPower(true); // TODO make as option let msgBoxes = []; let i = 0; - for (let msg of messageList) { + for (let msg of Bangle.MESSAGES) { msgBoxes[i] = new MessageBox(msg); if (i === messageNum - 1) msgBoxes[i].yOffset = MessageBox.prototype.prevOffset; else if (i === messageNum) { @@ -214,30 +268,24 @@ const showText = function(messageNum) { const drawFooter = function() { let fh = 20; // footer height // left hint: swipe from left for main menu - g.reset().setBgColor(g.theme.bg2).clearRect(Bangle.appRect.x, Bangle.appRect.y2-fh, Bangle.appRect.x2, Bangle.appRect.y2) + g.reset().setBgColor(g.theme.bg).clearRect(Bangle.appRect.x, Bangle.appRect.y2-fh, Bangle.appRect.x2, Bangle.appRect.y2) + .setColor(g.theme.bgH).drawLine(Bangle.appRect.x, Bangle.appRect.y2-fh, Bangle.appRect.x2, Bangle.appRect.y2-fh) .setFont("6x15") // TODO make as option - .setFontAlign(-1, 1) // bottom left - .drawString( - //"\0"+atob("CAiBAEgkEgkSJEgA"), // >> - ">>", - Bangle.appRect.x + 1, Bangle.appRect.y2 - ); + .setFontAlign(-1, 1).setColor(0, 1, 0) //bottom left + .drawString(">>", Bangle.appRect.x + 1, Bangle.appRect.y2); // center message count+hints: swipe up/down for next/prev message const footer = ` ${messageNum + 1}/${msgBoxes.length} `; const fw = g.stringWidth(footer); - g.setFontAlign(0, 1); // bottom center - g.drawString(footer, Bangle.appRect.x+Bangle.appRect.w/2, Bangle.appRect.y2); + g.setFontAlign(0, 1).setColor(g.theme.fg) // bottom center + .drawString(footer, Bangle.appRect.x+Bangle.appRect.w/2, Bangle.appRect.y2); if (messageNum < Bangle.MESSAGES.length - 1 && msgBoxes[messageNum].bottom) g.drawString("\0"+atob("CAiBAABBIhRJIhQI"), Bangle.appRect.x+Bangle.appRect.w/2-fw/2 - 20, Bangle.appRect.y2); // v swipe to next if (messageNum > 0 && msgBoxes[messageNum].top) g.drawString("\0"+atob("CAiBABAoRJIoRIIA"), Bangle.appRect.x+Bangle.appRect.w/2+fw/2 + 20, Bangle.appRect.y2); // ^ swipe to prev // right hint: swipe from right for message actions - g.setFontAlign(1, 1) // bottom right - .drawString( - //"\0"+atob("CAiBABIkSJBIJBIA"), // << - "<<", - Bangle.appRect.x2 - 1, Bangle.appRect.y2 - ); + g.setFontAlign(1, 1).setColor(1, 0.25, 0.25) // bottom right + .drawString("<<", Bangle.appRect.x2 - 1, Bangle.appRect.y2) + .setColor(g.theme.fg); }; const refresh = function() { @@ -317,8 +365,8 @@ const showText = function(messageNum) { msgBoxes[messageNum].draw(); msgBoxes[messageNum + 1].draw(); drawFooter(); - multiplier *= 2; - timeouts.animID = setTimeout(animate, delay); + multiplier *= 2.5; + timeouts["animID"] = setTimeout(animate, delay); } }; animate(); @@ -352,8 +400,8 @@ const showText = function(messageNum) { msgBoxes[messageNum].draw(); msgBoxes[messageNum - 1].draw(); drawFooter(); - multiplier *= 2; - timeouts.animID = setTimeout(animate, delay); + multiplier *= 2.5; + timeouts["animID"] = setTimeout(animate, delay); } }; animate(); @@ -361,17 +409,19 @@ const showText = function(messageNum) { }; const drawLeftBackground = function() { - g.setBgColor(1, 0.5, 0); // red - g.setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); - g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); - g.setBgColor(g.theme.bg); + //g.setBgColor(1, 0.5, 0); // red + g.setBgColor(g.theme.bg) + .setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2) + .clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2) + .setBgColor(g.theme.bg); }; const drawRightBackground = function() { - g.setBgColor(0, 0.5, 1); // red - g.setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); - g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); - g.setBgColor(g.theme.bg); + //g.setBgColor(0, 0.5, 1); // red + g.setBgColor(g.theme.bg) + .setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2) + .clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2) + .setBgColor(g.theme.bg); }; const animateToLeft = function() { @@ -379,18 +429,20 @@ const showText = function(messageNum) { clearTimeout(timeouts.animID); timeouts.animID = undefined; } - const endX = Bangle.appRect.x + (Bangle.appRect.w / 2); + let multiplier = 1; + const endX = Bangle.appRect.x - Bangle.appRect.w; //+ (Bangle.appRect.w / 2); const msgBox = msgBoxes[messageNum]; return new Promise((resolve, _reject) => { let animate = () => { - msgBox.xOffset -= step; + msgBox.xOffset -= step * multiplier; + multiplier *= 2.5; drawLeftBackground(); if (msgBox.xOffset <= endX) { return resolve(); } else { msgBox.draw(); drawFooter(); - timeouts.animID = setTimeout(animate, delay); + timeouts["animID"] = setTimeout(animate, delay); } }; animate(); @@ -402,18 +454,20 @@ const showText = function(messageNum) { clearTimeout(timeouts.animID); timeouts.animID = undefined; } - const endX = Bangle.appRect.x2 - (Bangle.appRect.w / 2); + let multiplier = 1; + const endX = Bangle.appRect.x2; // - (Bangle.appRect.w / 2); const msgBox = msgBoxes[messageNum]; return new Promise((resolve, _reject) => { let animate = () => { - msgBox.xOffset += step; + msgBox.xOffset += step * multiplier; + multiplier *= 2.5; drawRightBackground(); if (msgBox.xOffset >= endX) { return resolve(); } else { msgBox.draw(); drawFooter(); - timeouts.animID = setTimeout(animate, delay); + timeouts["animID"] = setTimeout(animate, delay); } }; animate(); @@ -421,7 +475,7 @@ const showText = function(messageNum) { }; let firstTouch = true; - const handler = function(e) { + const dragHandler = function(e) { if (e.b === 0) { firstTouch = true; checkForNewMessages(); @@ -438,28 +492,30 @@ const showText = function(messageNum) { msgBoxes[messageNum].clearNew(); if (Math.abs(e.dy) > Math.abs(e.dx)) { firstTouch = false; - if (e.dy > 0 && msgBoxes[messageNum].top) { + if (e.dy > 0 && msgBoxes[messageNum].top && messageNum > 0) { mode = "prev"; - } else if (msgBoxes[messageNum].bottom) { // e.dy will be < 0 here + } else if (e.dy < 0 && msgBoxes[messageNum].bottom && messageNum + 1 < msgBoxes.length) { // e.dy will be < 0 here mode = "next"; } else { mode = "scroll"; } - } else if (Math.abs(e.dx) > Math.abs(e.dy)) { - firstTouch = false; - if (e.dx < 0) { - mode = "left"; - } else { - mode = "right"; - } - } else { + } + // } else if (Math.abs(e.dx) > Math.abs(e.dy)) { + // firstTouch = false; + // if (e.dx < 0) { + // mode = "left"; + // } else { + // mode = "right"; + // } + // } else { + else { mode = undefined; return; } } if (mode == "scroll") scrollHandler(e); - else if (mode == "left") leftHandler(e); // remove from phone and watch - else if (mode == "right") rightHandler(e); // remove from watch only + //else if (mode == "left") leftHandler(e); // remove from phone and watch + //else if (mode == "right") rightHandler(e); // remove from watch only else if (mode == "next") nextHandler(e); else if (mode == "prev") prevHandler(e); }; @@ -484,14 +540,20 @@ const showText = function(messageNum) { }); }; + const swipeHandler = function(dir) { + if (dir > 0) return rightHandler(); + else if (dir < 0) return leftHandler(); + else return; + }; + const leftHandler = function(e) { const msgBox = msgBoxes[messageNum]; - if (e.b == 0) { - if (msgBox.xOffset > -swipeThreshold) { - msgBox.xOffset = 0; - msgBox.draw(); - drawFooter(); - } else { + // if (e.b == 0) { + // if (msgBox.xOffset > -swipeThreshold) { + // msgBox.xOffset = 0; + // msgBox.draw(); + // drawFooter(); + // } else { switching = true; animateToLeft().then(() => { g.setBgColor(g.theme.bg); @@ -499,38 +561,38 @@ const showText = function(messageNum) { removeMessage(); switching = false; }); - } - return; - } - msgBox.xOffset += e.dx; - if (msgBox.xOffset > 0) msgBox.xOffset = 0; - drawLeftBackground(); - msgBox.draw(); - drawFooter(); + // } + // return; + // } + // msgBox.xOffset += e.dx; + // if (msgBox.xOffset > 0) msgBox.xOffset = 0; + // drawLeftBackground(); + // msgBox.draw(); + // drawFooter(); }; const rightHandler = function(e) { const msgBox = msgBoxes[messageNum]; - if (e.b == 0) { - if (msgBox.xOffset < swipeThreshold) { - msgBox.xOffset = 0; - msgBox.draw(); - drawFooter(); - } else { + // if (e.b == 0) { + // if (msgBox.xOffset < swipeThreshold) { + // msgBox.xOffset = 0; + // msgBox.draw(); + // drawFooter(); + // } else { switching = true; animateToRight().then(() => { g.setBgColor(g.theme.bg); removeMessage(); switching = false; }); - } - return; - } - msgBox.xOffset += e.dx; - if (msgBox.xOffset < 0) msgBox.xOffset = 0; - drawRightBackground(); - msgBox.draw(); - drawFooter(); + // } + // return; + // } + // msgBox.xOffset += e.dx; + // if (msgBox.xOffset < 0) msgBox.xOffset = 0; + // drawRightBackground(); + // msgBox.draw(); + // drawFooter(); }; const scrollHandler = function(e) { @@ -541,7 +603,8 @@ const showText = function(messageNum) { Bangle.setUI({ mode: "custom", - drag: e => handler(e), + drag: e => dragHandler(e), + swipe: dir => swipeHandler(dir), btn: _e => goBack(), remove: cleanup }); @@ -557,7 +620,7 @@ const checkForNewMessages = function(idleTime) { idleTime = idleTime ?? 3000; // how much time without interaction before we are considered idle idle = false; if (timeouts.idleTimer) clearTimeout(timeouts.idleTimer); - timeouts.idleTimer = setTimeout(() => { + timeouts["idleTimer"] = setTimeout(() => { if (haveNewMessage) { haveNewMessage = false; let idx = Bangle.MESSAGES.findIndex(m => !m.handled); @@ -580,17 +643,19 @@ const setBusy = function() { timeouts.idleTimer = undefined; }; -const goBack = function(timedOut) { // TODO do we want this as a stack or by priority? +const goBack = function(timedOut) { + console.log("goBack()"); idle = true; if (buzzing) require("messages").stopBuzz(); let backTo; if (previous && previous.length) { backTo = previous.pop(); + clearTimeouts(); } else { if (!timedOut) Bangle.MESSAGES.forEach((m) => {if (!m.new) m.show = false;}); require("messages").write(Bangle.MESSAGES); cleanup = _cleanup; - Bangle.showClock(); + Bangle.load(); } //console.log("backTo = ", backTo); switch (backTo) { @@ -676,7 +741,6 @@ const showMessage = function() { idx = Bangle.MESSAGES.findIndex(m => !m.handled); if (idx >= 0) { 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); } @@ -688,7 +752,6 @@ const showMessage = function() { saveMessages = function() { require("messages").write(Bangle.MESSAGES); }; -//E.on("kill", events.saveMessages); setListener("kill", saveMessages); Bangle.loadWidgets(); diff --git a/messagecenter_call.js b/messagecenter_call.js index 4621ab6..67aae97 100644 --- a/messagecenter_call.js +++ b/messagecenter_call.js @@ -1,3 +1,8 @@ +let timeouts = {}; +const goBack = function() {}; +const cleanup = function() {}; + + 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==")); @@ -18,35 +23,38 @@ const showCall = function(call) { 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; + const drawAcceptArrow = function(xOffset) { + xOffset = xOffset??0; + imgX = x + 2 + xOffset; g.setColor(0, 1, 0); g.drawImage(rightImg, imgX, y2-50); + if (xOffset > 0) g.fillRect(imgX+3, y2-43, x, y2-9); + }; + const drawRejectArrow = function(xOffset) { + xOffset = xOffset??0; + let imgX = x2 - 50 - xOffset; + g.setColor(1, 0.25, 0.25); + g.drawImage(leftImg, imgX, y2-50); + if (xOffset > 0) g.fillRect(imgX+45, y2-43, x2, y2-9); }; if (cmd === "end") { - if (timerInt) clearTimeout(timerInt); //TODO change timerInt variable + 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); + timeouts["endTimeout"] = setTimeout(() => g.clear(), 3000); } if (cmd === "incoming") { - drawLeftArrow(); - drawRightArrow(); + drawRejectArrow(); + drawAcceptArrow(); g.setColor(0,1,0); g.drawImage(ringingImg, mx-25, y+15); } if (cmd === "start" || cmd === "outgoing") { - drawLeftArrow(x2 - 52); + drawRejectArrow(); startTime = parseInt(Date.now()/1000); g.setColor(g.theme.fg); g.drawImage(cmd === "start" ? incomingImg : outgoingImg, x+10, y+20); @@ -57,25 +65,57 @@ const showCall = function(call) { 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 + timeouts["timer"] = setTimeout(timer, 1000); }; timer(); } const handler = function(dir) { + if (cmd === "end") return; + if (dir < 0) leftHandler(dir); + else if (dir > 0 && cmd === "incoming") rightHandler(); + }; - } + const leftHandler = function(dir) { + let xOff = 0; + const swipeAnimation = () => { + xOff += 30; + g.clearRect(x, y2-50, x2, y2); + drawRejectArrow(xOff); + if (xOff > 160) return; + else setTimeout(swipeAnimation, 30); + } + swipeAnimation(); + if (timeouts.timer) clearTimeout(timeouts.timer); + return Bangle.messageResponse(msg, false); + }; + + const rightHandler = function(dir) { + let xOff = 0; + const swipeAnimation = () => { + xOff += 30; + g.clearRect(x, y2-50, x2, y2); + drawAcceptArrow(xOff); + if (xOff > 160) return; + else setTimeout(swipeAnimation, 30); + } + swipeAnimation(); + if (timeouts.timer) clearTimeout(timeouts.timer); + return Bangle.messageResponse(msg, true); + }; Bangle.setUI({ mode: "custom", + touch: () => {if (buzzing) return require("messages".stopBuzz())}, swipe: handler, - btn: () => {clearInterval(timerInt)} + btn: _e => goBack(), + remove: cleanup }); }; -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"} +let msg = {"t":"call","cmd":"incoming","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 0f15b39..a85ef52 100644 --- a/messagegui.lib.js +++ b/messagegui.lib.js @@ -7,7 +7,7 @@ exports.messageListener = function(type, msg) { if (!Bangle.MESSAGES || !Bangle.MESSAGES.length) Bangle.MESSAGES = require("messages").getMessages(msg); msg.show = true; msg.type = type; - if (msg.id === "call" && msg.t === "remove" && msg.cmd != "end") { + if (msg.id === "call" && msg.t === "remove") { msg.t = "modify"; // not sure why messages module puts everything as remove except for "incoming" msg.new = true; }