diff --git a/apps.json b/apps.json index 092aa1642..e3cda8672 100644 --- a/apps.json +++ b/apps.json @@ -93,7 +93,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.03", + "version":"0.04", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index 3a1d646bd..bf5c73161 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -1,3 +1,4 @@ 0.01: New Library! 0.02: Add notification ID option -0.03: Fix custom render callback \ No newline at end of file +0.03: Fix custom render callback +0.04: Pass `area{x,y,w,h}` to render callback instead of just `y` \ No newline at end of file diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 2bfc8de2d..7d317fa43 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -1,6 +1,32 @@ -var pos = 0; -var oldg; -var id = null; +let oldg; +let id = null; + +/** + * See notify/notify.js + */ +function fitWords(text,rows,width) { + // We never need more than rows*width characters anyway, split by any whitespace + const words = text.trim().substr(0,rows*width).split(/\s+/); + let row=1,len=0,limit=width; + let result = ""; + for (let word of words) { + // len==0 means first word of row, after that we also add a space + if ((len?len+1:0)+word.length > limit) { + if (row>=rows) { + result += "..."; + break; + } + result += "\n"; + len=0; + row++; + if (row===rows) limit -= 3; // last row needs space for "..." + } + result += (len?" ":"") + word; + len += (len?1:0) + word.length; + } + return result; +} + /** options = { @@ -19,56 +45,49 @@ exports.show = function(options) { options = options||{}; if (options.on===undefined) options.on=true; id = ("id" in options)?options.id:null; - var h = options.size||120; + let size = options.size||120; + if (size>120) {size=120} Bangle.setLCDMode("direct"); - var y = 40; - var x = 4; - // clear area + let x = 0, + y = 0, + w = 240, + h = 240; + // clear screen g.clear(1); // top bar - var top = 0; - if (options.title) { - g.setColor(0x39C7).fillRect(0, y, 239, y+30); + if (options.title||options.src) { + y=40;h=size; + const title = options.title || options.src + g.setColor(0x39C7).fillRect(x, y, x+w-1, y+30); g.setColor(-1).setFontAlign(-1, -1, 0).setFont("6x8", 3); - g.drawString(options.title.trim().substring(0, 13), 5, y+3); - y+=30; - } - if (options.src) { - g.setColor(-1).setFontAlign(1, 1, 0).setFont("6x8", 2); - g.drawString(options.src.substring(0, 10), 235, y-32); + g.drawString(title.trim().substring(0, 13), x+5, y+3); + if (options.title && options.src) { + g.setColor(-1).setFontAlign(1, 1, 0).setFont("6x8", 2); + // above drawing area, but we are fullscreen + g.drawString(options.src.substring(0, 10), x+235, y-32); + } + y += 30;h -= 30; } if (options.icon) { - let i = options.icon; - g.drawImage(i, x,y+4); - if ("string"==typeof i) x += i.charCodeAt(0); - else x += i[0]; + let i = options.icon, iw,ih; + if ("string"==typeof i) {iw=i.charCodeAt(0); ih=i.charCodeAt(1)} + else {iw=i[0]; ih=i[1]} + const iy=y ? (y+4) : (h-ih)/2; // show below title bar if present, otherwise center vertically + g.drawImage(i, x+4,iy); + x += iw+4;w -= iw+4; } // body text if (options.body) { - var body = options.body; - const maxChars = Math.floor((300-x)/16); - var limit = maxChars; - let row = 1; - let words = body.trim().replace("\n", " ").split(" "); - body = ""; - for (var i = 0; i < words.length; i++) { - if (body.length + words[i].length + 1 > limit) { - if (row>=8) { - body += "..."; - break; - } - body += "\n " + words[i]; - row++; - limit += maxChars; - if (row==8) limit -= 4; - } else { - body += " " + words[i]; - } - } - g.setColor(-1).setFont("6x8", 2).setFontAlign(-1, -1, 0).drawString(body, x-4, y+4); + const maxRows = Math.floor((h-4)/16), // font=2*(6x8) + maxChars = Math.floor((w-4)/12), + text=fitWords(options.body, maxRows, maxChars); + g.setColor(-1).setFont("6x8", 2).setFontAlign(-1, -1, 0).drawString(text, x+4, y+4); } - if (options.render) options.render(120-h/2); + if (options.render) { + const area={x:x, y:y, w:w, h:h} + options.render(area); + } if (options.on) Bangle.setLCDPower(1); // light up Bangle.on("touch", exports.hide);