From 2d60ce4a5358cfa2367bc60f44d3a1efbc7740fe Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 24 May 2022 22:08:43 +1000 Subject: [PATCH 1/4] android: Fix SMS bug --- apps/android/ChangeLog | 1 + apps/android/boot.js | 13 ++++++++++++- apps/android/metadata.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 55f456795..f13ccd95c 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -8,3 +8,4 @@ 0.07: Include charging state in battery updates to phone 0.08: Handling of alarms 0.09: Alarm vibration, repeat, and auto-snooze now handled by sched +0.10: Fix SMS bug diff --git a/apps/android/boot.js b/apps/android/boot.js index fb2101aa4..efd7e7e46 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -3,6 +3,7 @@ Bluetooth.println(""); Bluetooth.println(JSON.stringify(message)); } + var lastMsg; var settings = require("Storage").readJSON("android.settings.json",1)||{}; //default alarm settings @@ -18,7 +19,17 @@ /* TODO: Call handling, fitness */ var HANDLERS = { // {t:"notify",id:int, src,title,subject,body,sender,tel:string} add - "notify" : function() { Object.assign(event,{t:"add",positive:true, negative:true});require("messages").pushMessage(event); }, + "notify" : function() { + Object.assign(event,{t:"add",positive:true, negative:true}); + // Detect a weird GadgetBridge bug and fix it + // For some reason SMS messages send two GB notifications, with different sets of info + if (lastMsg && event.body == lastMsg.body && lastMsg.src == undefined && event.src == "Messages") { + // Mutate the other message + event.id = lastMsg.id; + } + lastMsg = event; + require("messages").pushMessage(event); + }, // {t:"notify~",id:int, title:string} // modified "notify~" : function() { event.t="modify";require("messages").pushMessage(event); }, // {t:"notify-",id:int} // remove diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 4051a344b..bf37b8407 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.09", + "version": "0.10", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", From 1fb256b9def3cf47df62d79b1f8f1ae563848e5f Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 24 May 2022 22:24:38 +1000 Subject: [PATCH 2/4] messages: Replace mail icon with color notif icons --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 94 ++----------------------------------- apps/messages/lib.js | 93 +++++++++++++++++++++++++++++++++++- apps/messages/metadata.json | 2 +- apps/messages/widget.js | 53 +++++++++++++++------ 5 files changed, 135 insertions(+), 108 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index d6ad393d6..1a484b3e5 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -50,4 +50,5 @@ 0.35: Reset graphics colors before rendering a message (possibly fix #1752) 0.36: Ensure a new message plus an almost immediate deletion of that message doesn't load the messages app (fix #1362) 0.37: Now use the setUI 'back' icon in the top left rather than specific buttons/menu items +0.38: Add notification icons in the widget diff --git a/apps/messages/app.js b/apps/messages/app.js index aac59e246..4919fcd94 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -67,99 +67,13 @@ function saveMessages() { require("Storage").writeJSON("messages.json",MESSAGES) } -function getNotificationImage() { - return atob("HBKBAD///8H///iP//8cf//j4//8f5//j/x/8//j/H//H4//4PB//EYj/44HH/Hw+P4//8fH//44///xH///g////A=="); -} -function getFBIcon() { - return atob("GBiBAAAAAAAAAAAYAAD/AAP/wAf/4A/48A/g8B/g+B/j+B/n+D/n/D8A/B8A+B+B+B/n+A/n8A/n8Afn4APnwADnAAAAAAAAAAAAAA=="); -} function getPosImage() { return atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA=="); } function getNegImage() { return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="); } -/* -* icons should be 24x24px with 1bpp colors and 'Transparency to Color' -* http://www.espruino.com/Image+Converter -*/ -function getMessageImage(msg) { - if (msg.img) return atob(msg.img); - var s = (msg.src||"").toLowerCase(); - if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA="); - if (s=="bibel") return atob("GBgBAAAAA//wD//4D//4H//4H/f4H/f4H+P4H4D4H4D4H/f4H/f4H/f4H/f4H/f4H//4H//4H//4GAAAEAAAEAAACAAAB//4AAAA"); - if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); - if (s=="corona-warn") return atob("GBgBAAAAABwAAP+AAf/gA//wB/PwD/PgDzvAHzuAP8EAP8AAPAAAPMAAP8AAH8AAHzsADzuAB/PAB/PgA//wAP/gAH+AAAwAAAAA"); - if (s=="discord") return atob("GBgBAAAAAAAAAAAAAIEABwDgDP8wH//4H//4P//8P//8P//8Pjx8fhh+fzz+f//+f//+e//ePH48HwD4AgBAAAAAAAAAAAAAAAAA"); - if (s=="facebook") return getFBIcon(); - if (s=="gmail") return getNotificationImage(); - if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); - if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); - if (s=="home assistant") return atob("FhaBAAAAAADAAAeAAD8AAf4AD/3AfP8D7fwft/D/P8ec572zbzbNsOEhw+AfD8D8P4fw/z/D/P8P8/w/z/AAAAA="); - if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); - if (s=="kalender") return atob("GBgBBgBgBQCgff++RQCiRgBiQAACf//+QAACQAACR//iRJkiRIEiR//iRNsiRIEiRJkiR//iRIEiRIEiR//iQAACQAACf//+AAAA"); - if (s=="lieferando") return atob("GBgBABgAAH5wAP9wAf/4A//4B//4D//4H//4P/88fV8+fV4//V4//Vw/HVw4HVw4HBg4HBg4HBg4HDg4Hjw4Hj84Hj44Hj44Hj44"); - if (s=="mail") return getNotificationImage(); - if (s=="messenger") return getFBIcon(); - if (s=="nina") return atob("GBgBAAAABAAQCAAICAAIEAAEEgAkJAgSJBwSKRxKSj4pUn8lVP+VVP+VUgAlSgApKQBKJAASJAASEgAkEAAECAAICAAIBAAQAAAA"); - if (s=="outlook mail") return atob("HBwBAAAAAAAAAAAIAAAfwAAP/gAB/+AAP/5/A//v/D/+/8P/7/g+Pv8Dye/gPd74w5znHDnOB8Oc4Pw8nv/Dwe/8Pj7/w//v/D/+/8P/7/gf/gAA/+AAAfwAAACAAAAAAAAAAAA="); - if (s=="phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA="); - if (s=="post & dhl") return atob("GBgBAPgAE/5wMwZ8NgN8NgP4NgP4HgP4HgPwDwfgD//AB/+AAf8AAAAABs7AHcdgG4MwAAAAGESAFESAEkSAEnyAEkSAFESAGETw"); - if (s=="signal") return atob("GBgBAAAAAGwAAQGAAhggCP8QE//AB//oJ//kL//wD//0D//wT//wD//wL//0J//kB//oA//ICf8ABfxgBYBAADoABMAABAAAAAAA"); - if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); - if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); - if (s=="sms message") return getNotificationImage(); - if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); - if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); - if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); - if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); - if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); - if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); - if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); - if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); - if (s=="wordfeud") return atob("GBgCWqqqqqqlf//////9v//////+v/////++v/////++v8///Lu+v8///L++v8///P/+v8v//P/+v9v//P/+v+fx/P/+v+Pk+P/+v/PN+f/+v/POuv/+v/Ofdv/+v/NvM//+v/I/Y//+v/k/k//+v/i/w//+v/7/6//+v//////+v//////+f//////9Wqqqqqql"); - if (s=="youtube") return atob("GBgBAAAAAAAAAAAAAAAAAf8AH//4P//4P//8P//8P5/8P4/8f4P8f4P8P4/8P5/8P//8P//8P//4H//4Af8AAAAAAAAAAAAAAAAA"); - if (msg.id=="music") return atob("FhaBAH//+/////////////h/+AH/4Af/gB/+H3/7/f/v9/+/3/7+f/vB/w8H+Dwf4PD/x/////////////3//+A="); - return getNotificationImage(); -} -function getMessageImageCol(msg,def) { - return { - // generic colors, using B2-safe colors - "alarm": "#fff", - "mail": "#ff0", - "music": "#f0f", - "phone": "#0f0", - "sms message": "#0ff", - // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) - // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) - "bibel": "#54342c", - "discord": "#738adb", - "facebook": "#4267b2", - "gmail": "#ea4335", - "google home": "#fbbc05", - "hangouts": "#1ba261", - "home assistant": "#fff", // ha-blue is #41bdf5, but that's the background - "instagram": "#dd2a7b", - "liferando": "#ee5c00", - "messenger": "#0078ff", - "nina": "#e57004", - "outlook mail": "#0072c6", - "post & dhl": "#f2c101", - "signal": "#00f", - "skype": "#00aff0", - "slack": "#e51670", - "snapchat": "#ff0", - "teams": "#464eb8", - "telegram": "#0088cc", - "threema": "#000", - "to do": "#3999e5", - "twitch": "#6441A4", - "twitter": "#1da1f2", - "whatsapp": "#4fce5d", - "wordfeud": "#e7d3c7", - "youtube": "#f00", - }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); -} + function showMapMessage(msg) { active = "map"; @@ -411,7 +325,7 @@ function showMessage(msgid) { {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2, halign:1 }, title?{type:"txt", font:titleFont, label:title, bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2 }:{}, ]}, - { type:"btn", src:getMessageImage(msg), col:getMessageImageCol(msg), pad: 3, cb:()=>{ + { type:"btn", src:require("messages").getMessageImage(msg), col:require("messages").getMessageImageCol(msg), pad: 3, cb:()=>{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, @@ -467,14 +381,14 @@ function checkMessages(options) { g.clearRect(r.x,r.y,r.x+r.w, r.y+r.h); if (!msg) return; var x = r.x+2, title = msg.title, body = msg.body; - var img = getMessageImage(msg); + var img = require("messages").getMessageImage(msg); if (msg.id=="music") { title = msg.artist || /*LANG*/"Music"; body = msg.track; } if (img) { var fg = g.getColor(); - g.setColor(getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering + g.setColor(require("messages").getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering .setColor(fg); // only color the icon x += 50; } diff --git a/apps/messages/lib.js b/apps/messages/lib.js index c39c8886c..f3c461e57 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -85,7 +85,7 @@ exports.pushMessage = function(event) { return load("messages.app.js"); } if (!quiet && (!global.WIDGETS || !WIDGETS.messages)) return Bangle.buzz(); // no widgets - just buzz to let someone know - WIDGETS.messages.show(); + WIDGETS.messages.update(); }, 500); } /// Remove all messages @@ -102,5 +102,94 @@ exports.clearAll = function(event) { if (inApp) return onMessagesModified(); // if we have a widget, update it if (global.WIDGETS && WIDGETS.messages) - WIDGETS.messages.hide(); + WIDGETS.messages.update(); +} + +function getNotificationImage() { + return atob("HBKBAD///8H///iP//8cf//j4//8f5//j/x/8//j/H//H4//4PB//EYj/44HH/Hw+P4//8fH//44///xH///g////A=="); +} +function getFBIcon() { + return atob("GBiBAAAAAAAAAAAYAAD/AAP/wAf/4A/48A/g8B/g+B/j+B/n+D/n/D8A/B8A+B+B+B/n+A/n8A/n8Afn4APnwADnAAAAAAAAAAAAAA=="); +} +/* +* icons should be 24x24px with 1bpp colors and 'Transparency to Color' +* http://www.espruino.com/Image+Converter +*/ +exports.getMessageImage = function (msg) { + if (msg.img) return atob(msg.img); + var s = (msg.src||"").toLowerCase(); + if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA="); + if (s=="bibel") return atob("GBgBAAAAA//wD//4D//4H//4H/f4H/f4H+P4H4D4H4D4H/f4H/f4H/f4H/f4H/f4H//4H//4H//4GAAAEAAAEAAACAAAB//4AAAA"); + if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); + if (s=="corona-warn") return atob("GBgBAAAAABwAAP+AAf/gA//wB/PwD/PgDzvAHzuAP8EAP8AAPAAAPMAAP8AAH8AAHzsADzuAB/PAB/PgA//wAP/gAH+AAAwAAAAA"); + if (s=="discord") return atob("GBgBAAAAAAAAAAAAAIEABwDgDP8wH//4H//4P//8P//8P//8Pjx8fhh+fzz+f//+f//+e//ePH48HwD4AgBAAAAAAAAAAAAAAAAA"); + if (s=="facebook") return getFBIcon(); + if (s=="gmail") return getNotificationImage(); + if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); + if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); + if (s=="home assistant") return atob("FhaBAAAAAADAAAeAAD8AAf4AD/3AfP8D7fwft/D/P8ec572zbzbNsOEhw+AfD8D8P4fw/z/D/P8P8/w/z/AAAAA="); + if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); + if (s=="kalender") return atob("GBgBBgBgBQCgff++RQCiRgBiQAACf//+QAACQAACR//iRJkiRIEiR//iRNsiRIEiRJkiR//iRIEiRIEiR//iQAACQAACf//+AAAA"); + if (s=="lieferando") return atob("GBgBABgAAH5wAP9wAf/4A//4B//4D//4H//4P/88fV8+fV4//V4//Vw/HVw4HVw4HBg4HBg4HBg4HDg4Hjw4Hj84Hj44Hj44Hj44"); + if (s=="mail") return getNotificationImage(); + if (s=="messenger") return getFBIcon(); + if (s=="nina") return atob("GBgBAAAABAAQCAAICAAIEAAEEgAkJAgSJBwSKRxKSj4pUn8lVP+VVP+VUgAlSgApKQBKJAASJAASEgAkEAAECAAICAAIBAAQAAAA"); + if (s=="outlook mail") return atob("HBwBAAAAAAAAAAAIAAAfwAAP/gAB/+AAP/5/A//v/D/+/8P/7/g+Pv8Dye/gPd74w5znHDnOB8Oc4Pw8nv/Dwe/8Pj7/w//v/D/+/8P/7/gf/gAA/+AAAfwAAACAAAAAAAAAAAA="); + if (s=="phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA="); + if (s=="post & dhl") return atob("GBgBAPgAE/5wMwZ8NgN8NgP4NgP4HgP4HgPwDwfgD//AB/+AAf8AAAAABs7AHcdgG4MwAAAAGESAFESAEkSAEnyAEkSAFESAGETw"); + if (s=="signal") return atob("GBgBAAAAAGwAAQGAAhggCP8QE//AB//oJ//kL//wD//0D//wT//wD//wL//0J//kB//oA//ICf8ABfxgBYBAADoABMAABAAAAAAA"); + if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); + if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); + if (s=="sms message") return getNotificationImage(); + if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); + if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); + if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); + if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); + if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); + if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); + if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); + if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); + if (s=="wordfeud") return atob("GBgCWqqqqqqlf//////9v//////+v/////++v/////++v8///Lu+v8///L++v8///P/+v8v//P/+v9v//P/+v+fx/P/+v+Pk+P/+v/PN+f/+v/POuv/+v/Ofdv/+v/NvM//+v/I/Y//+v/k/k//+v/i/w//+v/7/6//+v//////+v//////+f//////9Wqqqqqql"); + if (s=="youtube") return atob("GBgBAAAAAAAAAAAAAAAAAf8AH//4P//4P//8P//8P5/8P4/8f4P8f4P8P4/8P5/8P//8P//8P//4H//4Af8AAAAAAAAAAAAAAAAA"); + if (msg.id=="music") return atob("FhaBAH//+/////////////h/+AH/4Af/gB/+H3/7/f/v9/+/3/7+f/vB/w8H+Dwf4PD/x/////////////3//+A="); + return getNotificationImage(); +} + +exports.getMessageImageCol = function (msg,def) { + return { + // generic colors, using B2-safe colors + "alarm": "#fff", + "mail": "#ff0", + "music": "#f0f", + "phone": "#0f0", + "sms message": "#0ff", + // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) + // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) + "bibel": "#54342c", + "discord": "#738adb", + "facebook": "#4267b2", + "gmail": "#ea4335", + "google home": "#fbbc05", + "hangouts": "#1ba261", + "home assistant": "#fff", // ha-blue is #41bdf5, but that's the background + "instagram": "#dd2a7b", + "liferando": "#ee5c00", + "messenger": "#0078ff", + "nina": "#e57004", + "outlook mail": "#0072c6", + "post & dhl": "#f2c101", + "signal": "#00f", + "skype": "#00aff0", + "slack": "#e51670", + "snapchat": "#ff0", + "teams": "#464eb8", + "telegram": "#0088cc", + "threema": "#000", + "to do": "#3999e5", + "twitch": "#6441A4", + "twitter": "#1da1f2", + "whatsapp": "#4fce5d", + "wordfeud": "#e7d3c7", + "youtube": "#f00", + }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); } diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index ab9b03273..fd09fdfe4 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.37", + "version": "0.38", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", diff --git a/apps/messages/widget.js b/apps/messages/widget.js index 4b368ffd6..bb887b04e 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,3 +1,15 @@ +(() => { + +function getBaseMessages() { + if ("undefined"!=typeof MESSAGES) return MESSAGES; + return require("Storage").readJSON("messages.json",1)||[]; +} + +function getMessages() { + return getBaseMessages().filter(msg => msg.new && msg.id != "music") + .filter((msg, i, arr) => arr.findIndex(nmsg => msg.src == nmsg.src) == i); +} + WIDGETS["messages"]={area:"tl", width:0, iconwidth:24, draw:function(recall) { // If we had a setTimeout queued from the last time we were called, remove it @@ -11,8 +23,18 @@ draw:function(recall) { let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.flash===undefined) settings.flash = true; if (recall !== true || settings.flash) { + var msgs = getMessages(); + var msgsShown = E.clip(msgs.length, 0, 3); g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+23); - g.drawImage(settings.flash && (c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y-1); + for(let i = 0;i < msgsShown;i++) { + const msg = msgs[i]; + const colors = [g.theme.bg, g.setColor(require("messages").getMessageImageCol(msg)).getColor()]; + if (settings.flash && (c&1)) { + colors[1] = g.theme.fg; + } + g.setColor(colors[1]).setBgColor(colors[0]); + g.drawImage(i == 2 ? atob("GBgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4H4H4H4H4H4H4H4H4H4H4H4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") : require("messages").getMessageImage(msg), this.x + i * this.iconwidth, this.y - 1); + } } if (settings.repeat===undefined) settings.repeat = 4; if (c<120 && (Date.now()-this.l)>settings.repeat*1000) { @@ -21,18 +43,19 @@ draw:function(recall) { } WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(true), 1000); if (process.env.HWVERSION>1) Bangle.on('touch', this.touch); -},show:function(quiet) { - WIDGETS["messages"].t=Date.now(); // first time - WIDGETS["messages"].l=Date.now()-10000; // last buzz - if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing - WIDGETS["messages"].width=this.iconwidth; - Bangle.drawWidgets(); - Bangle.setLCDPower(1);// turns screen on -},hide:function() { - delete WIDGETS["messages"].t; - delete WIDGETS["messages"].l; - WIDGETS["messages"].width=0; +},update:function(quiet) { + const msgs = getMessages(); + if (msgs.length === 0) { + delete WIDGETS["messages"].t; + delete WIDGETS["messages"].l; + } else { + WIDGETS["messages"].t=Date.now(); // first time + WIDGETS["messages"].l=Date.now()-10000; // last buzz + if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing + } + WIDGETS["messages"].width=this.iconwidth * E.clip(msgs.length, 0, 3); Bangle.drawWidgets(); + if (msgs.length !== 0) Bangle.setLCDPower(1);// turns screen on },buzz:function() { if ((require('Storage').readJSON('setting.json',1)||{}).quiet) return; // never buzz during Quiet Mode require("buzz").pattern((require('Storage').readJSON("messages.settings.json", true) || {}).vibrate || "."); @@ -41,10 +64,10 @@ draw:function(recall) { if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.iconwidth) return; load("messages.app.js"); }}; + /* We might have returned here if we were in the Messages app for a message but then the watch was never viewed. In that case we don't want to buzz but should still show that there are unread messages. */ -if (global.MESSAGES===undefined) (function() { - var messages = require("Storage").readJSON("messages.json",1)||[]; - if (messages.some(m=>m.new&&m.id!="music")) WIDGETS["messages"].show(true); +WIDGETS["messages"].update(true); + })(); From 9740a36796e617489133e4d42901aca3371012e4 Mon Sep 17 00:00:00 2001 From: "Lubomir (Mac)" Date: Sun, 29 May 2022 14:19:38 +1000 Subject: [PATCH 3/4] messages: Use message array from lib Also, a max widget messages setting --- apps/messages/lib.js | 4 ++-- apps/messages/settings.js | 6 ++++++ apps/messages/widget.js | 24 +++++++++++++----------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/messages/lib.js b/apps/messages/lib.js index dc1da6662..a098f2c81 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -85,7 +85,7 @@ exports.pushMessage = function(event) { return load("messages.app.js"); } if (!quiet && (!global.WIDGETS || !WIDGETS.messages)) return Bangle.buzz(); // no widgets - just buzz to let someone know - WIDGETS.messages.update(); + if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages); }, 500); } /// Remove all messages @@ -102,7 +102,7 @@ exports.clearAll = function(event) { if (inApp) return onMessagesModified(); // if we have a widget, update it if (global.WIDGETS && WIDGETS.messages) - WIDGETS.messages.update(); + WIDGETS.messages.update(messages); } function getNotificationImage() { diff --git a/apps/messages/settings.js b/apps/messages/settings.js index adea36f12..44301fff6 100644 --- a/apps/messages/settings.js +++ b/apps/messages/settings.js @@ -4,6 +4,7 @@ if (settings.vibrate===undefined) settings.vibrate="."; if (settings.repeat===undefined) settings.repeat=4; if (settings.unreadTimeout===undefined) settings.unreadTimeout=60; + if (settings.maxMessages===undefined) settings.maxMessages=3; settings.unlockWatch=!!settings.unlockWatch; settings.openMusic=!!settings.openMusic; settings.maxUnreadTimeout=240; @@ -58,6 +59,11 @@ format: v => v?/*LANG*/'Yes':/*LANG*/'No', onchange: v => updateSetting("quietNoAutOpn", v) }, + /*LANG*/'Widget messages': { + value:0|settings().maxMessages, + min: 1, max: 5, + onchange: v => updateSetting("maxMessages", v) + } }; E.showMenu(mainmenu); }) diff --git a/apps/messages/widget.js b/apps/messages/widget.js index bb887b04e..a8ba33ae5 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,12 +1,12 @@ (() => { -function getBaseMessages() { +function getMessages() { if ("undefined"!=typeof MESSAGES) return MESSAGES; return require("Storage").readJSON("messages.json",1)||[]; } -function getMessages() { - return getBaseMessages().filter(msg => msg.new && msg.id != "music") +function filterMessages(msgs) { + return msgs.filter(msg => msg.new && msg.id != "music") .filter((msg, i, arr) => arr.findIndex(nmsg => msg.src == nmsg.src) == i); } @@ -23,17 +23,16 @@ draw:function(recall) { let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.flash===undefined) settings.flash = true; if (recall !== true || settings.flash) { - var msgs = getMessages(); - var msgsShown = E.clip(msgs.length, 0, 3); + var msgsShown = E.clip(this.msgs.length, 0, settings.maxMessages); g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+23); for(let i = 0;i < msgsShown;i++) { - const msg = msgs[i]; + const msg = this.msgs[i]; const colors = [g.theme.bg, g.setColor(require("messages").getMessageImageCol(msg)).getColor()]; if (settings.flash && (c&1)) { colors[1] = g.theme.fg; } g.setColor(colors[1]).setBgColor(colors[0]); - g.drawImage(i == 2 ? atob("GBgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4H4H4H4H4H4H4H4H4H4H4H4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") : require("messages").getMessageImage(msg), this.x + i * this.iconwidth, this.y - 1); + g.drawImage(i == (settings.maxMessages - 1) && msgs.length > settings.maxMessages ? atob("GBgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4H4H4H4H4H4H4H4H4H4H4H4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") : require("messages").getMessageImage(msg), this.x + i * this.iconwidth, this.y - 1); } } if (settings.repeat===undefined) settings.repeat = 4; @@ -43,8 +42,9 @@ draw:function(recall) { } WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(true), 1000); if (process.env.HWVERSION>1) Bangle.on('touch', this.touch); -},update:function(quiet) { - const msgs = getMessages(); +},update:function(rawMsgs, quiet) { + const settings = require('Storage').readJSON("messages.settings.json", true) || {}; + msgs = filterMessages(rawMsgs); if (msgs.length === 0) { delete WIDGETS["messages"].t; delete WIDGETS["messages"].l; @@ -53,7 +53,8 @@ draw:function(recall) { WIDGETS["messages"].l=Date.now()-10000; // last buzz if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing } - WIDGETS["messages"].width=this.iconwidth * E.clip(msgs.length, 0, 3); + WIDGETS["messages"].width=this.iconwidth * E.clip(msgs.length, 0, settings.maxMessages); + WIDGETS["messages"].msgs = msgs; Bangle.drawWidgets(); if (msgs.length !== 0) Bangle.setLCDPower(1);// turns screen on },buzz:function() { @@ -68,6 +69,7 @@ draw:function(recall) { /* We might have returned here if we were in the Messages app for a message but then the watch was never viewed. In that case we don't want to buzz but should still show that there are unread messages. */ -WIDGETS["messages"].update(true); +if (global.MESSAGES===undefined) + WIDGETS["messages"].update(getMessages(), true); })(); From f3d309170675929ec667f0d44dba88e3eea83028 Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 28 Jun 2022 22:27:22 +1000 Subject: [PATCH 4/4] Remove pointless functions --- apps/messages/lib.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 90847ccb0..3c6fbc880 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -105,13 +105,6 @@ exports.clearAll = function(event) { WIDGETS.messages.update(messages); } -function getNotificationImage() { - return atob("GBIBP//8H//4n//5z//z5//n8//H+P+f/H4//n5//Dw/+Jkf8YGP48PH5//nz//zn//5H//4P//8"); -} -function getFBIcon() { - return atob("GBiBAAAAAAAAAAAYAAD/AAP/wAf/4A/48A/g8B/g+B/j+B/n+D/n/D8A/B8A+B+B+B/n+A/n8A/n8Afn4APnwADnAAAAAAAAAAAAAA=="); -} - exports.getMessageImage = function(msg) { /* * icons should be 24x24px with 1bpp colors and 'Transparency to Color'