mirror of https://github.com/espruino/BangleApps
513 lines
11 KiB
JavaScript
513 lines
11 KiB
JavaScript
/* MESSAGES is a list of:
|
|
{id:int,
|
|
src,
|
|
title,
|
|
subject,
|
|
body,
|
|
sender,
|
|
tel:string,
|
|
new:true // not read yet
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
let LOG=function(){
|
|
//print.apply(null, arguments);
|
|
}
|
|
|
|
|
|
let settings= {
|
|
NewEventFileName:"messages_light.NewEvent.json",
|
|
fontSmall : "6x8",
|
|
fontMedium : "Vector:16",
|
|
fontBig : "Vector:20",
|
|
fontLarge : "Vector:30",
|
|
|
|
colHeadBg : g.theme.dark ? "#141":"#4f4",
|
|
|
|
colBg : g.theme.dark ? "#000":"#fff",
|
|
colLock : g.theme.dark ? "#ff0000":"#ff0000",
|
|
|
|
quiet:!!((require('Storage').readJSON('setting.json', 1) || {}).quiet),
|
|
timeOut:(require('Storage').readJSON("messages_light.settings.json", true) || {}).timeOut || "Off",
|
|
};
|
|
|
|
|
|
|
|
|
|
let EventQueue=[]; //in posizione 0, c'è quello attualmente visualizzato
|
|
let callInProgress=false;
|
|
|
|
|
|
let justOpened=true;
|
|
|
|
|
|
|
|
//TODO: RICORDARSI DI FARE IL DELETE
|
|
var manageEvent = function(event) {
|
|
|
|
event.new=true;
|
|
|
|
LOG("manageEvent");
|
|
LOG(event);
|
|
|
|
if( event.id=="call"){
|
|
showCall(event);
|
|
}
|
|
else if( event.id=="music"){
|
|
//la musica non la gestisco più ( uso l'app standard o un altra app)
|
|
}
|
|
else{
|
|
|
|
//-----------------
|
|
//notification
|
|
//-----------------
|
|
if(event.t=="add"){
|
|
EventQueue.unshift(event);
|
|
|
|
if(!callInProgress)
|
|
showMessage(event);
|
|
}
|
|
else if(event.t=="modify"){
|
|
//cerco l'evento nella lista, se lo trovo, lo modifico, altrimenti lo pusho
|
|
let find=false;
|
|
EventQueue.forEach(element => {
|
|
if(element.id == event.id)
|
|
{
|
|
find=true;
|
|
Object.assign(element,event);
|
|
}
|
|
});
|
|
if(!find) //se non l'ho trovato, lo aggiungo in fondo
|
|
EventQueue.unshift(event);
|
|
|
|
if(!callInProgress)
|
|
showMessage(event);
|
|
}
|
|
else if(event.t=="remove"){
|
|
//se non c'è niente nella queue e non c'è una chiamata in corso
|
|
if( EventQueue.length==0 && !callInProgress)
|
|
next();
|
|
|
|
//se l'id è uguale a quello attualmente visualizzato ( e non siamo in chiamata )
|
|
if(!callInProgress && EventQueue[0] !== undefined && EventQueue[0].id == event.id)
|
|
next(); //passo al messaggio successivo ( per la rimozione ci penserà la next )
|
|
|
|
else{
|
|
//altrimenti rimuovo tutti gli elementi con quell'id( creando un nuovo array )
|
|
let newEventQueue=[];
|
|
EventQueue.forEach(element => {
|
|
if(element.id != event.id)
|
|
newEventQueue.push(element);
|
|
});
|
|
|
|
//non sovrascrivo, cosi uso lo stesso oggetto in memoria e dovrei avere meno problemi di memory leak
|
|
EventQueue.length=0;
|
|
newEventQueue.forEach(element => {
|
|
EventQueue.push(element);
|
|
});
|
|
}
|
|
}
|
|
//-----------------
|
|
//notification
|
|
//-----------------
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let showMessage = function(msg){
|
|
LOG("showMessage");
|
|
LOG(msg);
|
|
|
|
updateTimeout();
|
|
|
|
|
|
g.setBgColor(settings.colBg);
|
|
|
|
|
|
if(typeof msg.CanScrollDown==="undefined")
|
|
msg.CanScrollDown=false;
|
|
if(typeof msg.CanScrollUp==="undefined")
|
|
msg.CanScrollUp=false;
|
|
|
|
|
|
|
|
|
|
|
|
// Normal text message display
|
|
let title=msg.title, titleFont = settings.fontLarge, lines;
|
|
if (title) {
|
|
let w = g.getWidth()-48;
|
|
if (g.setFont(titleFont).stringWidth(title) > w)
|
|
titleFont = settings.fontMedium;
|
|
if (g.setFont(titleFont).stringWidth(title) > w) {
|
|
lines = g.wrapString(title, w);
|
|
title = (lines.length>2) ? lines.slice(0,2).join("\n")+"..." : lines.join("\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let Layout = require("Layout");
|
|
layout = new Layout({ type:"v", c: [
|
|
{type:"h", fillx:1, bgCol:settings.colHeadBg, c: [
|
|
{ type:"btn", src:require("messageicons").getImage(msg), col:require("messageicons").getColor(msg), pad: 3},
|
|
{ type:"v", fillx:1, c: [
|
|
{type:"txt", font:settings.fontSmall, label:msg.src||/*LANG*/"Message", bgCol:settings.colHeadBg, fillx:1, pad:2, halign:1 },
|
|
title?{type:"txt", font:titleFont, label:title, bgCol:settings.colHeadBg, fillx:1, pad:2 }:{},
|
|
]},
|
|
]},
|
|
{type:"v",fillx:1,filly:1,pad:2 ,halign:-1,c:[]},
|
|
|
|
|
|
|
|
|
|
]});
|
|
|
|
|
|
if (!settings.quiet && msg.new)
|
|
{
|
|
msg.new=false;
|
|
Bangle.buzz();
|
|
}
|
|
|
|
|
|
g.clearRect(Bangle.appRect);
|
|
layout.render();
|
|
|
|
PrintMessageStrings(msg);
|
|
Bangle.setLCDPower(1);
|
|
|
|
DrawLock();
|
|
|
|
};
|
|
let DrawLock=function()
|
|
{
|
|
let w=8,h=8;
|
|
let x = g.getWidth()-w;
|
|
let y = 0;
|
|
if(Bangle.isLocked())
|
|
g.setBgColor(settings.colLock);
|
|
else
|
|
g.setBgColor(settings.colHeadBg);
|
|
g.clearRect(x,y,x+w,y+h);
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let showCall = function(msg)
|
|
{
|
|
LOG("showCall");
|
|
LOG(msg);
|
|
// se anche prima era una call PrevMessage==msg.id
|
|
//non so perchè prima era cosi
|
|
if( msg.t=="remove")
|
|
{
|
|
LOG("hide call screen");
|
|
next(); //dont shift
|
|
return;
|
|
}
|
|
|
|
callInProgress=true;
|
|
updateTimeout();
|
|
|
|
|
|
//se è una chiamata ( o una nuova chiamata, diversa dalla precedente )
|
|
//la visualizzo
|
|
|
|
let title=msg.title, titleFont = settings.fontLarge, lines;
|
|
if (title) {
|
|
let w = g.getWidth()-48;
|
|
if (g.setFont(titleFont).stringWidth(title) > w)
|
|
titleFont = settings.fontMedium;
|
|
if (g.setFont(titleFont).stringWidth(title) > w) {
|
|
lines = g.wrapString(title, w);
|
|
title = (lines.length>2) ? lines.slice(0,2).join("\n")+"..." : lines.join("\n");
|
|
}
|
|
}
|
|
let Layout = require("Layout");
|
|
layout = new Layout({ type:"v", c: [
|
|
{type:"h", fillx:1, bgCol:settings.colHeadBg, c: [
|
|
{ type:"btn", src:require("messageicons").getImage(msg), col:require("messageicons").getColor(msg), pad: 3},
|
|
{ type:"v", fillx:1, c: [
|
|
{type:"txt", font:settings.fontSmall, label:msg.src||/*LANG*/"Message", bgCol:settings.colHeadBg, fillx:1, pad:2, halign:1 },
|
|
title?{type:"txt", font:titleFont, label:title, bgCol:settings.colHeadBg, fillx:1, pad:2 }:{},
|
|
]},
|
|
]},
|
|
{type:"txt", font:settings.fontMedium, label:msg.body, fillx:1,filly:1,pad:2 ,halign:0}
|
|
]});
|
|
|
|
|
|
StopBuzzCall();
|
|
if ( !settings.quiet ) {
|
|
if(msg.new)
|
|
{
|
|
msg.new=false;
|
|
CallBuzzTimer = setInterval(function() {
|
|
Bangle.buzz(500);
|
|
}, 1000);
|
|
|
|
Bangle.buzz(500);
|
|
}
|
|
}
|
|
g.clearRect(Bangle.appRect);
|
|
layout.render();
|
|
PrintMessageStrings(msg);
|
|
Bangle.setLCDPower(1);
|
|
DrawLock();
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let next=function(){
|
|
LOG("next");
|
|
StopBuzzCall();
|
|
|
|
|
|
//se c'è una chiamata, non shifto
|
|
if(!callInProgress)
|
|
EventQueue.shift(); //passa al messaggio successivo, se presente - tolgo il primo
|
|
|
|
callInProgress=false;
|
|
LOG(EventQueue.length);
|
|
if( EventQueue.length == 0)
|
|
{
|
|
LOG("no element in queue - closing");
|
|
setTimeout(_ => load());
|
|
return;
|
|
}
|
|
|
|
|
|
showMessage(EventQueue[0]);
|
|
|
|
};
|
|
|
|
|
|
|
|
let CallBuzzTimer=undefined;
|
|
let StopBuzzCall=function()
|
|
{
|
|
if (CallBuzzTimer){
|
|
clearInterval(CallBuzzTimer);
|
|
CallBuzzTimer=undefined;
|
|
}
|
|
}
|
|
let DrawTriangleUp=function()
|
|
{
|
|
g.fillPoly([169,46,164,56,174,56]);
|
|
}
|
|
let DrawTriangleDown=function()
|
|
{
|
|
g.fillPoly([169,170,164,160,174,160]);
|
|
}
|
|
|
|
|
|
|
|
|
|
let ScrollUp=function()
|
|
{
|
|
msg= EventQueue[0];
|
|
|
|
if(typeof msg.FirstLine==="undefined")
|
|
msg.FirstLine=0;
|
|
if(typeof msg.CanScrollUp==="undefined")
|
|
msg.CanScrollUp=false;
|
|
|
|
if(!msg.CanScrollUp) return;
|
|
|
|
msg.FirstLine = msg.FirstLine>0?msg.FirstLine-1:0;
|
|
|
|
PrintMessageStrings(msg);
|
|
}
|
|
let ScrollDown=function()
|
|
{
|
|
msg= EventQueue[0];
|
|
if(typeof msg.FirstLine==="undefined")
|
|
msg.FirstLine=0;
|
|
if(typeof msg.CanScrollDown==="undefined")
|
|
msg.CanScrollDown=false;
|
|
|
|
if(!msg.CanScrollDown) return;
|
|
|
|
msg.FirstLine = msg.FirstLine+1;
|
|
PrintMessageStrings(msg);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let PrintMessageStrings=function(msg)
|
|
{
|
|
let MyWrapString = function (str,maxWidth)
|
|
{
|
|
str=str.replace("\r\n","\n").replace("\r","\n");
|
|
return g.wrapString(str,maxWidth);
|
|
}
|
|
|
|
|
|
if(typeof msg.FirstLine==="undefined") msg.FirstLine=0;
|
|
|
|
let bodyFont = typeof msg.bodyFont==="undefined"? settings.fontMedium : msg.bodyFont;
|
|
let Padding=2;
|
|
if(typeof msg.lines==="undefined")
|
|
{
|
|
g.setFont(bodyFont);
|
|
msg.lines = MyWrapString(msg.body,g.getWidth()-(Padding*2))
|
|
if ( msg.lines.length<=2)
|
|
{
|
|
bodyFont= g.getFonts().includes("Vector")?"Vector:20":"6x8:3";
|
|
g.setFont(bodyFont);
|
|
msg.lines = MyWrapString(msg.body,g.getWidth()-(Padding*2))
|
|
msg.bodyFont = bodyFont;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//prendo le linee da stampare
|
|
let NumLines=8;
|
|
let linesToPrint = (msg.lines.length>NumLines) ? msg.lines.slice(msg.FirstLine,msg.FirstLine+NumLines):msg.lines;
|
|
|
|
|
|
let yText=45;
|
|
|
|
//invalido l'area e disegno il testo
|
|
g.setBgColor(settings.colBg);
|
|
g.clearRect(0,yText,176,176);
|
|
let xText=Padding;
|
|
yText+=Padding;
|
|
g.setFont(bodyFont);
|
|
let HText=g.getFontHeight();
|
|
|
|
yText=((176-yText)/2)-(linesToPrint.length * HText / 2) + yText;
|
|
|
|
if( linesToPrint.length<=2)
|
|
{
|
|
g.setFontAlign(0,-1);
|
|
xText = g.getWidth()/2;
|
|
}
|
|
else
|
|
g.setFontAlign(-1,-1);
|
|
|
|
|
|
linesToPrint.forEach((line, i)=>{
|
|
g.drawString(line,xText,yText+HText*i);
|
|
});
|
|
|
|
//disegno le freccie
|
|
if(msg.FirstLine!=0)
|
|
{
|
|
msg.CanScrollUp=true;
|
|
DrawTriangleUp();
|
|
}
|
|
else
|
|
msg.CanScrollUp=false;
|
|
|
|
if(msg.FirstLine+linesToPrint.length < msg.lines.length)
|
|
{
|
|
msg.CanScrollDown=true;
|
|
DrawTriangleDown();
|
|
}
|
|
else
|
|
msg.CanScrollDown=false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let doubleTapUnlock=function(data) {
|
|
updateTimeout();
|
|
if( data.double) //solo se in double
|
|
{
|
|
Bangle.setLocked(false);
|
|
Bangle.setLCDPower(1);
|
|
}
|
|
}
|
|
let toushScroll=function(_, xy) {
|
|
updateTimeout();
|
|
|
|
let height=176; //g.getHeight(); -> 176 B2
|
|
height/=2;
|
|
|
|
if(xy.y<height)
|
|
{
|
|
ScrollUp();
|
|
}
|
|
else
|
|
{
|
|
ScrollDown();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let timeout;
|
|
const updateTimeout = function(){
|
|
if (settings.timeOut!="Off"){
|
|
removeTimeout();
|
|
if( callInProgress) return; //c'è una chiamata in corso -> no timeout
|
|
//if( typeof music !== 'undefined' && EventQueue.length==0 ) return; //ho aperto l'interfaccia della musica e non ho messaggi davanti -> no timeout
|
|
|
|
|
|
let time=parseInt(settings.timeOut); //the "s" will be trimmed by the parseInt
|
|
timeout = setTimeout(next,time*1000); //next or Bangle.showClock/load()???
|
|
}
|
|
};
|
|
const removeTimeout=function(){
|
|
if (timeout) clearTimeout(timeout);
|
|
}
|
|
|
|
|
|
let main = function(){
|
|
LOG("Main");
|
|
|
|
g.clear();
|
|
|
|
Bangle.on('lock', DrawLock);
|
|
|
|
//se c'è una chiamata in corso NON devo togliere niente dal next ( in q)
|
|
setWatch(_=> next(), BTN1,{repeat: true});
|
|
|
|
//il tap è il tocco con l'accellerometro!
|
|
Bangle.on('tap', doubleTapUnlock);
|
|
Bangle.on('touch', toushScroll);
|
|
|
|
//quando apro quest'app, do per scontato che c'è un messaggio da leggere posto in un file particolare ( messages_light.NewEvent.json )
|
|
let eventToShow = require('Storage').readJSON(settings.NewEventFileName, true);
|
|
require("Storage").erase(settings.NewEventFileName)
|
|
if( eventToShow!==undefined)
|
|
manageEvent(eventToShow);
|
|
else
|
|
{
|
|
LOG("file event not found! -> ?? open debug text");
|
|
setTimeout(_=>{ GB({"t":"notify","id":15754117198411,"src":"Hangouts","title":"A Name","body":"Debug notification \nmessage contents demo demo demo demo"}) },0);
|
|
}
|
|
justOpened=false;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
main(); |