BangleApps/apps/ios/boot.js

343 lines
9.9 KiB
JavaScript
Raw Normal View History

bleServiceOptions.ancs = true;
bleServiceOptions.cts = true;
if (NRF.amsIsActive) bleServiceOptions.ams = true; // amsIsActive was added at the same time as the "am" option
Bangle.ancsMessageQueue = [];
/* Handle ANCS events coming in, and fire off 'notify' events
when we actually have all the information we need */
E.on('ANCS',msg=>{
/* eg:
{
event:"add",
uid:42,
category:4,
categoryCnt:42,
silent:true,
important:false,
preExisting:true,
positive:false,
negative:true
} */
//console.log("ANCS",msg.event,msg.id);
// don't need info for remove events - pass these on
if (msg.event=="remove")
return E.emit("notify", msg);
// not a remove - we need to get the message info first
function ancsHandler() {
var msg = Bangle.ancsMessageQueue[0];
NRF.ancsGetNotificationInfo( msg.uid ).then( info => { // success
if(msg.preExisting === true){
info.new = false;
} else {
info.new = true;
}
E.emit("notify", Object.assign(msg, info));
Bangle.ancsMessageQueue.shift();
if (Bangle.ancsMessageQueue.length)
ancsHandler();
}, err=>{ // failure
console.log("ancsGetNotificationInfo failed",err);
if (Bangle.ancsMessageQueue.length)
ancsHandler();
});
}
Bangle.ancsMessageQueue.push(msg);
// if this is the first item in the queue, kick off ancsHandler,
// otherwise ancsHandler will handle the rest
if (Bangle.ancsMessageQueue.length==1)
ancsHandler();
});
// Handle ANCS events with all the data
E.on('notify',msg=>{
/* Info from ANCS event plus
"uid" : int,
"appId" : string,
"title" : string,
"subtitle" : string,
"message" : string,
"messageSize" : string,
"date" : string,
"new" : boolean,
"posAction" : string,
"negAction" : string,
"name" : string,
*/
var appNames = {
2022-07-10 16:26:50 +00:00
"ch.publisheria.bring": "Bring",
"com.apple.facetime": "FaceTime",
"com.apple.mobilecal": "Calendar",
"com.apple.mobilemail": "Mail",
2021-12-12 22:50:02 +00:00
"com.apple.mobilephone": "Phone",
"com.apple.mobileslideshow": "Pictures",
"com.apple.MobileSMS": "SMS Message",
"com.apple.Passbook": "iOS Wallet",
"com.apple.podcasts": "Podcasts",
"com.apple.reminders": "Reminders",
"com.apple.shortcuts": "Shortcuts",
2022-07-10 15:26:50 +00:00
"com.apple.TestFlight": "TestFlight",
"com.apple.ScreenTimeNotifications": "ScreenTime",
"com.apple.wifid.usernotification": "WiFi",
"com.atebits.Tweetie2": "Twitter",
"com.burbn.instagram" : "Instagram",
"com.facebook.Facebook": "Facebook",
2021-12-12 22:50:02 +00:00
"com.facebook.Messenger": "Messenger",
"com.google.Chromecast" : "Google Home",
"com.google.Gmail" : "GMail",
2021-11-04 19:38:06 +00:00
"com.google.hangouts" : "Hangouts",
"com.google.ios.youtube" : "YouTube",
"com.hammerandchisel.discord" : "Discord",
"com.ifttt.ifttt" : "IFTTT",
"com.jumbo.app" : "Jumbo",
"com.linkedin.LinkedIn" : "LinkedIn",
"com.marktplaats.iphone": "Marktplaats",
"com.microsoft.Office.Outlook" : "Outlook Mail",
"com.nestlabs.jasper.release" : "Nest",
"com.netflix.Netflix" : "Netflix",
"com.reddit.Reddit" : "Reddit",
"com.skype.skype": "Skype",
2021-11-04 19:38:06 +00:00
"com.skype.SkypeForiPad": "Skype",
"com.spotify.client": "Spotify",
"com.storytel.iphone": "Storytel",
"com.strava.stravaride": "Strava",
"com.tinyspeck.chatlyio": "Slack",
"com.toyopagroup.picaboo": "Snapchat",
"com.ubercab.UberClient": "Uber",
"com.ubercab.UberEats": "UberEats",
2022-07-10 16:26:50 +00:00
"com.unitedinternet.mmc.mobile.gmx.iosmailer": "GMX",
"com.valvesoftware.Steam": "Steam",
"com.vilcsak.bitcoin2": "Coinbase",
"com.wordfeud.free": "WordFeud",
2022-07-10 16:26:50 +00:00
"com.yourcompany.PPClient": "PayPal",
"com.zhiliaoapp.musically": "TikTok",
2022-07-10 16:26:50 +00:00
"de.no26.Number26": "N26",
"io.robbie.HomeAssistant": "Home Assistant",
2022-07-10 16:26:50 +00:00
"net.superblock.Pushover": "Pushover",
"net.weks.prowl": "Prowl",
"net.whatsapp.WhatsApp": "WhatsApp",
"nl.ah.Appie": "Albert Heijn",
2021-12-07 19:23:15 +00:00
"nl.postnl.TrackNTrace": "PostNL",
2022-04-11 14:37:16 +00:00
"org.whispersystems.signal": "Signal",
"ph.telegra.Telegraph": "Telegram",
"tv.twitch": "Twitch",
// could also use NRF.ancsGetAppInfo(msg.appId) here
};
2021-12-14 01:08:33 +00:00
//if (appNames[msg.appId]) msg.a
if (msg.title === "BangleDumpCalendar") {
2023-11-10 20:38:03 +00:00
// parse the message body into json:
const d = JSON.parse(msg.message);
/* Example:
{
"title": "Test Event",
"start_time": "2023-11-10T11:00:00-08:00",
"duration":"1:00:00",
"notes": "This is a test event.",
"location": "Stonehenge Amesbury, Wiltshire, SP4 7DE, England",
2023-11-10 21:29:30 +00:00
"calName": "Home",
"id": "1234567890"
2023-11-10 20:38:03 +00:00
}
2023-11-10 21:29:30 +00:00
and we want to convert to:
{t:"calendar", id:int, type:int, timestamp:seconds, durationInSeconds, title:string, description:string,location:string,calName:string.color:int,allDay:bool
for gadgetbridge
2023-11-10 20:38:03 +00:00
*/
let calEvent = {
2023-11-10 21:29:30 +00:00
t: "calendar",
id: parseInt(d.id),
type: 0,
2023-11-10 22:14:37 +00:00
timestamp: Date.parse(d.start_time.slice(0, -5)) / 1000,
2023-11-10 21:29:30 +00:00
durationInSeconds: d.duration ? d.duration.split(":").reduce((a, b) => a * 60 + parseInt(b)) : 0,
title: d.title,
description: d.notes,
location: d.location,
calName: d.calName,
color: 0,
allday: false
}
calEvent.allday = calEvent.durationInSeconds >= 24 * 56 * 60 - 1; // 24 hours for IOS is 23:59:59
2023-11-10 20:38:03 +00:00
2023-11-10 21:29:30 +00:00
var cal = require("Storage").readJSON("android.calendar.json",true);
if (!cal || !Array.isArray(cal)) cal = [];
var i = cal.findIndex(e=>e.id==calEvent.id);
if(i<0)
cal.push(calEvent);
else
cal[i] = calEvent;
2023-11-11 05:28:40 +00:00
cal = cal.filter(e=>e.timestamp>=Date.now()/1000);
2023-11-10 21:29:30 +00:00
require("Storage").writeJSON("android.calendar.json", cal);
NRF.ancsAction(msg.uid, false);
return;
2023-11-10 20:38:03 +00:00
}
if (msg.title === "BangleDumpWeather") {
2023-11-11 01:02:12 +00:00
const d = JSON.parse(msg.message);
/* Example:
{"temp":"291.07","hi":"293.02","lo":"288.18","hum":"49","rain":"0","uv":"0","wind":"1.54","code":"01d","txt":"Mostly Sunny","wdir":"303","loc":"Berlin"}
what we want:
t:"weather", temp,hi,lo,hum,rain,uv,code,txt,wind,wdir,loc
*/
let weatherEvent = {
2023-11-11 01:02:12 +00:00
t: "weather",
temp: d.temp,
hi: d.hi,
lo: d.lo,
hum: d.hum,
rain: d.rain,
uv: d.uv,
code: d.code,
txt: d.txt,
wind: d.wind,
wdir: d.wdir,
loc: d.loc
}
require("weather").update(weatherEvent);
NRF.ancsAction(msg.uid, false);
return;
}
require("messages").pushMessage({
t : msg.event,
id : msg.uid,
2021-12-08 00:45:29 +00:00
src : appNames[msg.appId] || msg.appId,
new : msg.new,
title : msg.title&&Bangle.ancsConvertUTF8(msg.title),
subject : msg.subtitle&&Bangle.ancsConvertUTF8(msg.subtitle),
body : msg.message&&Bangle.ancsConvertUTF8(msg.message) || "Cannot display",
positive : msg.positive,
negative : msg.negative
});
// TODO: posaction/negaction?
});
// Apple media service
E.on('AMS',a=>{
function push(m) {
var msg = { t : "modify", id : "music", title:"Music" };
if (a.id=="artist") msg.artist = m;
2021-12-12 22:50:02 +00:00
else if (a.id=="album") msg.album = m;
2021-12-13 08:13:04 +00:00
else if (a.id=="title") msg.track = m;
else if (a.id=="duration") msg.dur = m;
else return;
require("messages").pushMessage(msg);
}
if (a.truncated) NRF.amsGetMusicInfo(a.id).then(push)
else push(a.value);
});
// Music control
Bangle.musicControl = cmd => {
// play, pause, playpause, next, prev, volup, voldown, repeat, shuffle, skipforward, skipback, like, dislike, bookmark
NRF.amsCommand(cmd);
};
// Message response
Bangle.messageResponse = (msg,response) => {
if (isFinite(msg.id)) return NRF.ancsAction(msg.id, response);//true/false
// error/warn here?
};
// remove all messages on disconnect
NRF.on("disconnect", () => {
require("messages").clearAll();
// Remove any messages from the ANCS queue
Bangle.ancsMessageQueue = [];
});
/*
// For testing...
NRF.ancsGetNotificationInfo = function(uid) {
print("ancsGetNotificationInfo",uid);
return Promise.resolve({
"uid" : uid,
"appId" : "Hangouts",
"title" : "Hello",
"subtitle" : "There",
"message" : "Lots and lots of text",
"messageSize" : 100,
"date" : "...",
"posAction" : "ok",
"negAction" : "cancel",
"name" : "Fred",
});
};
E.on("notify", n => print("NOTIFY", n));
E.emit("ANCS", {
event:"add",
uid:42,
category:4,
categoryCnt:42,
silent:true,
important:false,
preExisting:false,
positive:false,
negative:true
});
*/
{
let settings = require("Storage").readJSON("ios.settings.json",1)||{};
let ctsUpdate = e=>{
if (process.env.VERSION=="2v19")
e.date.setMonth(e.date.getMonth()-1); // fix for bug in 2v19 firmware
var tz = 0;
if (e.timezone!==undefined) {
E.setTimeZone(e.timezone);
tz = e.timezone*3600;
var settings = require('Storage').readJSON('setting.json',1)||{};
settings.timezone = e.timezone;
require('Storage').writeJSON('setting.json',settings);
}
setTime((e.date.getTime()/1000) - tz);
};
if (settings.timeSync && NRF.ctsGetTime) {
if (NRF.ctsIsActive())
NRF.ctsGetTime().then(ctsUpdate, function(){ /* */ })
E.on('CTS',ctsUpdate);
}
if (settings.no_utf8 || !require("Storage").read("font")) {
// if UTF8 disabled or there is no fonts lib, convert UTF8 to ISO8859-1
let unicodeRemap = {
'2019':"'",
'260':"A",
'261':"a",
'262':"C",
'263':"c",
'268':"C",
'269':"c",
'270':"D",
'271':"d",
'280':"E",
'281':"e",
'282':"E",
'283':"e",
'321':"L",
'322':"l",
'323':"N",
'324':"n",
'327':"N",
'328':"n",
'344':"R",
'345':"r",
'346':"S",
'347':"s",
'352':"S",
'353':"s",
'356':"T",
'357':"t",
'377':"Z",
'378':"z",
'379':"Z",
'380':"z",
'381':"Z",
'382':"z",
};
let replacer = ""; //(n)=>print('Unknown unicode '+n.toString(16));
Bangle.ancsConvertUTF8 = text => E.decodeUTF8(text, unicodeRemap, replacer);
} else {
Bangle.ancsConvertUTF8 = E.asUTF8;
}
}