From 079598bc4884b2b58436ff8288b0cc9baa40b3ae Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 21 Apr 2023 11:38:27 +0100 Subject: [PATCH] Merge in https://github.com/espruino/BangleApps/pull/2702 (PR included a bunch of other stuff not required) --- apps/xxlmessage/ChangeLog | 2 + apps/xxlmessage/README.md | 13 ++ apps/xxlmessage/app-icon.js | 1 + apps/xxlmessage/app.js | 42 +++++++ apps/xxlmessage/app.png | Bin 0 -> 315 bytes apps/xxlmessage/boot.js | 1 + apps/xxlmessage/lib-unbuffered.js | 133 ++++++++++++++++++++ apps/xxlmessage/lib.js | 194 ++++++++++++++++++++++++++++++ apps/xxlmessage/metadata.json | 20 +++ apps/xxlmessage/screenshot.png | Bin 0 -> 2032 bytes 10 files changed, 406 insertions(+) create mode 100644 apps/xxlmessage/ChangeLog create mode 100644 apps/xxlmessage/README.md create mode 100644 apps/xxlmessage/app-icon.js create mode 100644 apps/xxlmessage/app.js create mode 100644 apps/xxlmessage/app.png create mode 100644 apps/xxlmessage/boot.js create mode 100644 apps/xxlmessage/lib-unbuffered.js create mode 100644 apps/xxlmessage/lib.js create mode 100644 apps/xxlmessage/metadata.json create mode 100644 apps/xxlmessage/screenshot.png diff --git a/apps/xxlmessage/ChangeLog b/apps/xxlmessage/ChangeLog new file mode 100644 index 000000000..4c587db52 --- /dev/null +++ b/apps/xxlmessage/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Display icon of the message origin's app \ No newline at end of file diff --git a/apps/xxlmessage/README.md b/apps/xxlmessage/README.md new file mode 100644 index 000000000..40e62fdd2 --- /dev/null +++ b/apps/xxlmessage/README.md @@ -0,0 +1,13 @@ +# XXL Message app +This app displays an incomming message with a very large +font and scrolls the text. For people who can't read the +menu font without glasses, this might be an alternative +to the default messages UI app. + +When arrived, new messages are displayed instantly on the screen. +When the message fully scrolled two times or +if you touch the screen or press the button, +the default clock is loaded. + +Nothing more, nothing less. + diff --git a/apps/xxlmessage/app-icon.js b/apps/xxlmessage/app-icon.js new file mode 100644 index 000000000..ee6642f11 --- /dev/null +++ b/apps/xxlmessage/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwcA/4A/AH4A/AH2SpMkAQ1/CI3+CI+fB4v5AQQRFk4JB84REBAXkCIgLFEAYsCIgo+BCIwLEC4oRHF4w7CCJAIRGQaDECLQIRLKB9QUKDFRdKB3GQYwAFBwpKFAAhEFAQokHAH4A/AH4A/ABA")) \ No newline at end of file diff --git a/apps/xxlmessage/app.js b/apps/xxlmessage/app.js new file mode 100644 index 000000000..207221fc6 --- /dev/null +++ b/apps/xxlmessage/app.js @@ -0,0 +1,42 @@ + + +if (require("Storage").read("messagegui")){ // "messagegui" module is installed + require("messages").openGUI(); + console.log("Opened Messages UI"); + Bangle.load("messagegui"); +} + + +function stop() { + g.setBgColor(0, 1, 1); + g.clear(); + g.reset(); + load(); +} +var txt = 'No Messages'; +try{ + console.log("try delete messages"); + var MESSAGES = require("messages").getMessages(); + MESSAGES = []; + txt = 'Deleted all messages'; + console.log("worked"); +}catch(e){} +g.setBgColor('#ffff00'); +g.setColor('#000000'); +g.clear(); + +g.setFont('6x8:3'); +g.setFontAlign(0, 0); +g.setColor('#000000'); +g.drawString(g.wrapString(txt, g.getWidth()).join("\n"), g.getWidth()/2, g.getHeight()/2); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +//E.showMessage(txt,{ +// title:"XXL Messages", +// img:atob("FBQBAfgAf+Af/4P//D+fx/n+f5/v+f//n//5//+f//n////3//5/n+P//D//wf/4B/4AH4A=") // (i) +//}) + +setTimeout(stop, 4000); + diff --git a/apps/xxlmessage/app.png b/apps/xxlmessage/app.png new file mode 100644 index 0000000000000000000000000000000000000000..88dae4c66789915451183a6f1d860be86908d95c GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@H(7p!ia> zONTwMEm$OyW6_ei6DE~8rHHtIHFqeSGMwv?xhz%Ssl^tp);j&N#?N0*`(22B`J%RZ rSEbdLHKLpU|8Ru32<|l7-~X7dHq;*x?>3YG`i;TU)z4*}Q$iB}(i3^k literal 0 HcmV?d00001 diff --git a/apps/xxlmessage/boot.js b/apps/xxlmessage/boot.js new file mode 100644 index 000000000..62053a0b9 --- /dev/null +++ b/apps/xxlmessage/boot.js @@ -0,0 +1 @@ +Bangle.on("message", (type, msg) => require("xxlmessage.lib.js").listener(type, msg)); \ No newline at end of file diff --git a/apps/xxlmessage/lib-unbuffered.js b/apps/xxlmessage/lib-unbuffered.js new file mode 100644 index 000000000..68fb2a7a2 --- /dev/null +++ b/apps/xxlmessage/lib-unbuffered.js @@ -0,0 +1,133 @@ +// GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"}) +var xxl = { +// private: + msg: [], + drawTimeout: undefined, + xpos : 0, + loopCount : 0, + txt:'', + wtot:0, + img:undefined, + imgcol:'#ffffff', + + setFont: function(){ + g.setFont('6x8:5x9'); // TODO this is a bottleneck. How to prepare the font once? + }, + +//public: + show: function(theMessage){ + console.log("theMessage is:"); + console.log(theMessage); + xxl.msg = theMessage; + // prepare string and metrics + xxl.txt = xxl.msg.src + ": " + xxl.msg.body; + xxl.setFont(); + xxl.wtot = g.stringMetrics(xxl.txt).width; + xxl.xpos = 2 * g.getWidth(); + + // get icon + xxl.img = require("messageicons").getImage(xxl.msg); + xxl.imgcol = require("messageicons").getColor(xxl.msg, '#ffffff'); + + Bangle.loadWidgets(); + + Bangle.on('touch', function (b, xy) { + xxl.stop(); + }); + setWatch(xxl.stop, BTN1); + Bangle.buzz(500,1); + + xxl.draw(); + }, + +//private: + // schedule a draw for 30 FPS + queueDraw: function() { + if (xxl.drawTimeout) { return; } // clearTimeout(xxl.drawTimeout); } + xxl.drawTimeout = setTimeout(function () { + xxl.drawTimeout = undefined; + xxl.draw(); + }, 33 - (Date.now() % 33)); + }, + + + stop:function() { + console.log("stop"); + if (xxl.drawTimeout) { clearTimeout(xxl.drawTimeout); } + xxl.drawTimeout = undefined; + g.reset(); + g.setBgColor('#ffff00'); + g.clear(); + + // Bangle.setLCDPower(0); // light off + // Bangle.setLocked(true); // disable touch + + setTimeout(load, 100); + }, + + draw: function() { + wh = 24; // widgets height + var gw = g.getWidth(); + var h = (g.getHeight() - wh)/2; // height of drawing area per stripe + + Bangle.setLCDPower(1); // light on + Bangle.setLocked(false); // keep the touch input active + g.setBgColor('#000000'); + g.clear(); + + if (xxl.img) { // 24x24 + g.setColor(xxl.imgcol); + g.drawImage(xxl.img + , gw/2, wh+h // center point + ,{rotate:0,scale:2} + ); + } + + xxl.setFont(); + g.setFontAlign(-1, -1); + + // draw both lines + g.setBgColor('#000000'); + g.setColor('#ffffff'); + g.drawString(xxl.txt, xxl.xpos, wh); + g.drawString(xxl.txt, xxl.xpos - gw - 32, h + wh); + + g.reset(); + // widget redraw + Bangle.drawWidgets(); + + // scroll + xxl.xpos -= 25; + if (xxl.xpos < -xxl.wtot - gw * 2) { + ++xxl.loopCount; + if (xxl.loopCount > 2) { + xxl.stop(); + return; + } + xxl.xpos = 3 * gw; + } + // loop drawing + xxl.queueDraw(); + } +}; + + +// for IDE +// var exports={}; + +exports.listener = function (type, msg) { + // msg = {t:"add",id:int, src,title,subject,body,sender,tel, important:bool, new:bool} + if (!msg) return; + if (type === 'text' && msg.t !== 'remove') { + msg.handled = true; // don't do anything else with the message + xxl.show(msg); + } +}; + +// debug +// Bangle.on("message", (type, msg) => exports.listener(type, msg)); + + + + + diff --git a/apps/xxlmessage/lib.js b/apps/xxlmessage/lib.js new file mode 100644 index 000000000..9aa85462d --- /dev/null +++ b/apps/xxlmessage/lib.js @@ -0,0 +1,194 @@ +// GB({t:"notify",id:1680248072,src:"SMS Messenger",title:"Fabia",body:"Nein"}) +// msg = {"t":"add","id":1680248072,"src":"SMS Messenger","title":"Fabia","body":"Nein","new":true,"handled":true} +var xxl = { +// private: + msg: [], + drawTimeout: undefined, + xpos : 0, + loopCount : 0, + txt:'', + wtot:0, + img:undefined, + imgcol:'#ffffff', + + // gfx buffer + bufimg:undefined, + bufpal4color:undefined, + buffnt:'6x15', // font to use. Built-in: 4x6, 6x8,12x20,6x15,Vector + bufw:0, // width of buffer for all lines + bufh:0, // height of buffer + buflin:0, // number of lines to print + bufscale:0, // scale factor for buffer to screen + +// public: + show: function(theMessage){ + // console.log("theMessage is:"); + // console.log(theMessage); + xxl.msg = theMessage; + + // get icon + try{ + xxl.img = require("messageicons").getImage(xxl.msg); + xxl.imgcol = (require("messageicons").getColor(xxl.msg, '#ffffff')||'#00ffff'); + }catch(e){} + + Bangle.loadWidgets(); + + Bangle.on('touch', function (b, xy) { + xxl.stop(); + }); + setWatch(xxl.stop, BTN1); + Bangle.buzz(500,1); + + + // offscreen gfx buffer + // screen is 176x176 + // font should be scaled 5x9=30x72px + // built in fonts are 4x6, 6x8,12x20,6x15,Vector + xxl.bufpal4color = new Uint16Array([0x0000,0xFFFF,0x7BEF,0xAFE5],0,2); // b,w,grey,greenyellow + g.setFont(xxl.buffnt); + var hfont = g.getFontHeight(); + xxl.bufscale=parseInt((g.getHeight() - 24/*widgets*/)/2) / hfont; + xxl.buflin=2; // number of lines + xxl.bufw=(g.getWidth() * xxl.buflin) / xxl.bufscale; // 6x15 font scaled by 5 on 176 screen width + xxl.bufh=hfont; + + xxl.bufimg = Graphics.createArrayBuffer(xxl.bufw,xxl.bufh,2,{msb:true}); + + // prepare string and metrics + xxl.txt = (xxl.msg.title||(xxl.msg.src||"MSG")) + ": " + (xxl.msg.body||"-x-"); + g.setFont(xxl.buffnt); + xxl.wtot = g.stringMetrics(xxl.txt).width; + xxl.xpos = xxl.bufw; // g.getWidth(); + + xxl.draw(); + }, + +//private: + // schedule a draw for 60 FPS + queueDraw: function() { + if (xxl.drawTimeout) { return; } // clearTimeout(xxl.drawTimeout); } + xxl.drawTimeout = setTimeout(function () { + xxl.drawTimeout = undefined; + xxl.draw(); + }, 16 - (Date.now() % 16)); + }, + + + stop:function() { + // console.log("stop"); + if (xxl.drawTimeout) { clearTimeout(xxl.drawTimeout); } + xxl.drawTimeout = undefined; + g.reset(); + g.setBgColor('#ffff00'); + g.clear(); + + // Bangle.setLCDPower(0); // light off + // Bangle.setLocked(true); // disable touch + + setTimeout(function(){Bangle.showClock();}, 100); + }, + + // this is even slower than the scaled printing :( + // megaPrintBufferd: function(txt, x, y){ + // xxl.bufimg.setFont(xxl.buffnt); + // xxl.bufimg.setFontAlign(-1, -1); + // xxl.bufimg.setColor(1); // index in palette + // xxl.bufimg.clear(); + // xxl.bufimg.drawString(txt, x, 0); + // for(var i = 0; i 2) { + xxl.stop(); + return; + } + xxl.xpos = (3*xxl.bufw)/2; + } + // loop drawing + xxl.queueDraw(); + } +}; + + +// for IDE +// var exports={}; + +exports.listener = function (type, msg) { + // msg = {t:"add",id:int, src,title,subject,body,sender,tel, important:bool, new:bool} + if (!msg) return; + if (type === 'text' && msg.t !== 'remove') { + msg.handled = true; // don't do anything else with the message + xxl.show(msg); + } +}; + +// debug +// var msg = {t:"add",id:12341, src:"SMS",title:undefined,subject:undefined,body:"yes",sender:"phoo",tel:undefined, important:false, new:true}; +// exports.listener('text', msg); + + + + + + + diff --git a/apps/xxlmessage/metadata.json b/apps/xxlmessage/metadata.json new file mode 100644 index 000000000..f8150f0e7 --- /dev/null +++ b/apps/xxlmessage/metadata.json @@ -0,0 +1,20 @@ +{ + "id": "xxlmessage", + "name": "XXL Message", + "version": "0.02", + "shortName": "XXL Msg", + "description": "App to display large notifications from iOS and Gadgetbridge/Android", + "icon": "app.png", + "type": "app", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "dependencies" : {"messages":"module", "messageicons":"module" }, + "readme": "README.md", + "screenshots": [{"url":"screenshot.png"}], + "storage": [ + {"name":"xxlmessage.app.js","url":"app.js"}, + {"name":"xxlmessage.lib.js","url":"lib.js"}, + {"name":"xxlmessage.boot.js","url":"boot.js"}, + {"name":"xxlmessage.img","url":"app-icon.js","evaluate":true} + ] +} \ No newline at end of file diff --git a/apps/xxlmessage/screenshot.png b/apps/xxlmessage/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5d9fbcf55317dae1572772bd31abbf209720acdc GIT binary patch literal 2032 zcmd^=i8~tx1ID9TN0GIqTgA0%&1aNsG~y_8WRW`Bs-ud84~b}rtHSDN=Tl#crf92* zm^kYQ77`T|v|>`Et&xxer7R_jI|wrSFZMipp5Obv&+jjI?_c(UYa9g~1pojV2sc;n zgKhacDoO|4Oq)XbXa^R}5ZUG4Z0PxMf^o8RilT$A z<*0yECh1@mLvrzS;IXgrt8zA-P8$`DU%h-V7 z*XFK?U>0vn?^ZH~aJ6NJ@>FKm?~Ye~K4GYCrEjuAnn=BfJ#IYQT~V))eU%~KEHGCD zJ^8ZLvD^wZ-mVF6i}Xocb&oR9Z*}y1VC^${qA$n7_?q*y*&7Or)mWnqH3|9%v#YzI zs?g?~8j;`f;Xh|W+MaAZ=akpLJbEHc7`qIklNw9|M zew}(zM!0M9$8yA#!-DPt{pK~FOQ!GX#3ag)k!#Ry{SZ^!ta)gp6EUWJDiWise9!98 zKbYY=codiB2w!ral+Ha)D?znnZd|};YURgue`*M_j(uDn&j@1ylLT2X9jb)+0^%2u zOVO?cqh9V6ZRdT+IuC^)^=NjuG8;u)G;fAgpH}|LH#Jt;kj1YP1j{}_T(X;|c=%VFga#E zIt2ZDa2W5X({JrVEuNGOX1ab!K$$@5$BpN;L&u=AN!a&tac}PK9E?@?3kmFqIYJZA zlABi#AA5J#a{18)kPs+eHI;=W^zQJhvk5U{P@VJtos74f!7f*&;8#_zCR4++d$ChP zZFE$xDa`v9jfbOlQmzt{U)*FQ%iq8&zpcwWNxMJ|DO$M4*VZU|rD>hYA$OG~VWLX% zKu_qwJ88zKee1@{>JgJW5`vb+;0G?$Wn2zk#k0*HW4KUxxXLGeVLOu6M4~7HJ^2l3 z5Zfj}S^Qzh$|aEzbbpnxk1`<@PcOWFJt$uu1{qtmhG+H%*tbO~Bi!pYj_{-uiHA_h zm`{B)@&)u+p1JTvqiRN)?P7ZiDl>*B#iZlX*+62WQf(z9mNBkZ#T*zE5X>ux1L#mk zzdE994B7ehbcp8`=REDC{UZZ*I)*Hr4>u`2X&tyzMs7vWp}NS+`5XU>N-hmiz4fxo zg%%}y|2k}uEvEC1F9oLF+-qI&Nrd%4?7fNimtMz=a(dzA4o@M>A1~hcZARy*sd=DZ z(=oGvhr(AT;zYsA{Fls|&_JNY0sQOK;+~-_wh&L-uZ|#bjy~mI)mIHZ%=Q z_{(ehxjzS=;K$_{PJaX4dA3gGcGx`)ETHQN5TIWj418QEOdHWwXnR4(fcS+ll+y91 z3iPMs&pWYi^{q0@Xj@EIMa$r;Oq--@=N^4u*dTgvM-8_JbWc^X3v;rnrqOhQFc54h zOS7V14#d={9om!xWr0dmO)XY9OU@~qlN6Kze;$jLu3pJU=Zyy2I!ssYj&xnc4!mQW5AldtEpSL{AkOXyz_`?VD1v&8;x*WveIFkEkW%*$>B2 z-2FMXv%(Oeuw8^~J8#x94vY+SSapqLRn(rQ#|olj#8%56rW)fC2bFcx zJ$~JFRPB>6a1)$~>eYn^8T!km&kO#d+x!{hah3s{PwlI;k%4q@8P!_2xJK)h2|ODp zkVJV&%U|z0d=a8TO0ugJCt^fc4 literal 0 HcmV?d00001