summaryrefslogtreecommitdiff
path: root/rockworkd/libpebble
diff options
context:
space:
mode:
Diffstat (limited to 'rockworkd/libpebble')
-rw-r--r--rockworkd/libpebble/appmsgmanager.cpp28
-rw-r--r--rockworkd/libpebble/appmsgmanager.h2
-rw-r--r--rockworkd/libpebble/blobdb.cpp15
-rw-r--r--rockworkd/libpebble/blobdb.h2
-rw-r--r--rockworkd/libpebble/calendarevent.cpp16
-rw-r--r--rockworkd/libpebble/calendarevent.h4
-rw-r--r--rockworkd/libpebble/jskit/jskitconsole.cpp201
-rw-r--r--rockworkd/libpebble/jskit/jskitconsole.h56
-rw-r--r--rockworkd/libpebble/jskit/jskitmanager.cpp2
-rw-r--r--rockworkd/libpebble/jskit/jskitpebble.cpp9
-rw-r--r--rockworkd/libpebble/jskit/jskitpebble.h1
-rw-r--r--rockworkd/libpebble/jskit/jskitsetup.js104
-rw-r--r--rockworkd/libpebble/jskit/jskitwebsocket.cpp311
-rw-r--r--rockworkd/libpebble/jskit/jskitwebsocket.h79
-rw-r--r--rockworkd/libpebble/pebble.cpp28
-rw-r--r--rockworkd/libpebble/pebble.h2
16 files changed, 817 insertions, 43 deletions
diff --git a/rockworkd/libpebble/appmsgmanager.cpp b/rockworkd/libpebble/appmsgmanager.cpp
index e20c8d0..350383b 100644
--- a/rockworkd/libpebble/appmsgmanager.cpp
+++ b/rockworkd/libpebble/appmsgmanager.cpp
@@ -11,10 +11,17 @@ AppMsgManager::AppMsgManager(Pebble *pebble, AppManager *apps, WatchConnection *
: QObject(pebble),
m_pebble(pebble),
apps(apps),
- m_connection(connection), _lastTransactionId(0), _timeout(new QTimer(this))
+ m_connection(connection),
+ _lastTransactionId(0),
+ m_currentUuid(QUuid()),
+ _timeout(new QTimer(this))
{
connect(m_connection, &WatchConnection::watchConnected,
this, &AppMsgManager::handleWatchConnectedChanged);
+ connect(m_connection, &WatchConnection::watchDisconnected,
+ this, &AppMsgManager::handleWatchConnectedChanged);
+ connect(m_pebble, &Pebble::pebbleConnected,
+ this, &AppMsgManager::handlePebbleConnected);
_timeout->setSingleShot(true);
_timeout->setInterval(3000);
@@ -250,7 +257,9 @@ QByteArray AppMsgManager::buildLaunchMessage(quint8 messageType, const QUuid &uu
QByteArray ba;
WatchDataWriter writer(&ba);
writer.write<quint8>(messageType);
- writer.writeUuid(uuid);
+ if (!uuid.isNull()) {
+ writer.writeUuid(uuid);
+ }
return ba;
}
@@ -282,6 +291,7 @@ void AppMsgManager::handleAppLaunchMessage(const QByteArray &data)
switch (data.at(0)) {
case LauncherActionStart:
qDebug() << "App starting in watch:" << uuid;
+ m_currentUuid = uuid;
emit appStarted(uuid);
break;
case LauncherActionStop:
@@ -317,6 +327,7 @@ void AppMsgManager::handleLauncherPushMessage(const QByteArray &data)
case LauncherActionStart:
qDebug() << "App starting in watch:" << uuid;
m_connection->writeToPebble(WatchConnection::EndpointLauncher, buildAckMessage(transaction));
+ m_currentUuid = uuid;
emit appStarted(uuid);
break;
case LauncherActionStop:
@@ -412,13 +423,22 @@ void AppMsgManager::handleAckMessage(const QByteArray &data, bool ack)
void AppMsgManager::handleWatchConnectedChanged()
{
- // If the watch is disconnected, everything breaks loose
- // TODO In the future we may want to avoid doing the following.
if (!m_connection->isConnected()) {
+ emit appStopped(m_currentUuid);
+
+ // If the watch is disconnected, everything breaks loose
+ // TODO In the future we may want to avoid doing the following.
+
abortPendingTransactions();
}
}
+void AppMsgManager::handlePebbleConnected()
+{
+ //Now that we have all the info from the pebble "relaunch" the current app
+ emit appStarted(m_currentUuid);
+}
+
void AppMsgManager::handleTimeout()
{
// Abort the first transaction
diff --git a/rockworkd/libpebble/appmsgmanager.h b/rockworkd/libpebble/appmsgmanager.h
index 77ee480..374ed98 100644
--- a/rockworkd/libpebble/appmsgmanager.h
+++ b/rockworkd/libpebble/appmsgmanager.h
@@ -67,6 +67,7 @@ private:
private slots:
void handleWatchConnectedChanged();
+ void handlePebbleConnected();
void handleTimeout();
void handleAppLaunchMessage(const QByteArray &data);
@@ -79,6 +80,7 @@ private:
WatchConnection *m_connection;
QHash<QUuid, MessageHandlerFunc> _handlers;
quint8 _lastTransactionId;
+ QUuid m_currentUuid;
struct PendingTransaction {
quint8 transactionId;
diff --git a/rockworkd/libpebble/blobdb.cpp b/rockworkd/libpebble/blobdb.cpp
index e5a2f77..2faa499 100644
--- a/rockworkd/libpebble/blobdb.cpp
+++ b/rockworkd/libpebble/blobdb.cpp
@@ -108,13 +108,13 @@ void BlobDB::insertNotification(const Notification &notification)
TimelineItem timelineItem(itemUuid, TimelineItem::TypeNotification);
timelineItem.setFlags(TimelineItem::FlagSingleEvent);
- TimelineAttribute titleAttribute(TimelineAttribute::TypeTitle, notification.sender().left(64).toUtf8());
+ TimelineAttribute titleAttribute(TimelineAttribute::TypeTitle, notification.sender().remove(QRegExp("<[^>]*>")).left(64).toUtf8());
timelineItem.appendAttribute(titleAttribute);
- TimelineAttribute subjectAttribute(TimelineAttribute::TypeSubtitle, notification.subject().left(64).toUtf8());
+ TimelineAttribute subjectAttribute(TimelineAttribute::TypeSubtitle, notification.subject().remove(QRegExp("<[^>]*>")).left(64).toUtf8());
timelineItem.appendAttribute(subjectAttribute);
- TimelineAttribute bodyAttribute(TimelineAttribute::TypeBody, notification.body().toUtf8());
+ TimelineAttribute bodyAttribute(TimelineAttribute::TypeBody, notification.body().remove(QRegExp("<[^>]*>")).toUtf8());
timelineItem.appendAttribute(bodyAttribute);
TimelineAttribute iconAttribute(TimelineAttribute::TypeTinyIcon, iconId);
@@ -144,13 +144,14 @@ void BlobDB::insertNotification(const Notification &notification)
m_notificationSources.insert(itemUuid, notification);
}
-void BlobDB::insertTimelinePin(const QUuid &uuid, TimelineItem::Layout layout, const QDateTime &startTime, const QDateTime &endTime, const QString &title, const QString &desctiption, const QMap<QString, QString> fields, bool recurring)
+void BlobDB::insertTimelinePin(const QUuid &uuid, TimelineItem::Layout layout, bool isAllDay, const QDateTime &startTime, const QDateTime &endTime, const QString &title, const QString &desctiption, const QMap<QString, QString> fields, bool recurring)
{
// TimelineItem item(TimelineItem::TypePin, TimelineItem::FlagSingleEvent, QDateTime::currentDateTime().addMSecs(1000 * 60 * 2), 60);
qDebug() << "inserting timeline pin:" << title << startTime << endTime;
int duration = (endTime.toMSecsSinceEpoch() - startTime.toMSecsSinceEpoch()) / 1000 / 60;
- TimelineItem item(uuid, TimelineItem::TypePin, TimelineItem::FlagSingleEvent, startTime, duration);
+ TimelineItem::Flag flag = isAllDay ? TimelineItem::FlagAllDay : TimelineItem::FlagSingleEvent;
+ TimelineItem item(uuid, TimelineItem::TypePin, flag, startTime, duration);
item.setLayout(layout);
TimelineAttribute titleAttribute(TimelineAttribute::TypeTitle, title.toUtf8());
@@ -239,7 +240,7 @@ void BlobDB::syncCalendar(const QList<CalendarEvent> &events)
// Filter out invalid items
foreach (const CalendarEvent &event, events) {
- if (event.startTime().isValid() && event.endTime().isValid()
+ if (event.startTime().isValid() && (event.endTime().isValid() || event.isAllDay())
&& event.startTime().addDays(2) > QDateTime::currentDateTime()
&& QDateTime::currentDateTime().addDays(5) > event.startTime()) {
itemsToSync.append(event);
@@ -286,7 +287,7 @@ void BlobDB::syncCalendar(const QList<CalendarEvent> &events)
if (!event.calendar().isEmpty()) fields.insert("Calendar", event.calendar());
if (!event.comment().isEmpty()) fields.insert("Comments", event.comment());
if (!event.guests().isEmpty()) fields.insert("Guests", event.guests().join(", "));
- insertTimelinePin(event.uuid(), TimelineItem::LayoutCalendar, event.startTime(), event.endTime(), event.title(), event.description(), fields, event.recurring());
+ insertTimelinePin(event.uuid(), TimelineItem::LayoutCalendar, event.isAllDay(), event.startTime(), event.endTime(), event.title(), event.description(), fields, event.recurring());
m_calendarEntries.append(event);
event.saveToCache(m_blobDBStoragePath);
}
diff --git a/rockworkd/libpebble/blobdb.h b/rockworkd/libpebble/blobdb.h
index b1db403..58d7f51 100644
--- a/rockworkd/libpebble/blobdb.h
+++ b/rockworkd/libpebble/blobdb.h
@@ -42,7 +42,7 @@ public:
explicit BlobDB(Pebble *pebble, WatchConnection *connection);
void insertNotification(const Notification &notification);
- void insertTimelinePin(const QUuid &uuid, TimelineItem::Layout layout, const QDateTime &startTime, const QDateTime &endTime, const QString &title, const QString &desctiption, const QMap<QString, QString> fields, bool recurring);
+ void insertTimelinePin(const QUuid &uuid, TimelineItem::Layout layout, bool isAllDay, const QDateTime &startTime, const QDateTime &endTime, const QString &title, const QString &desctiption, const QMap<QString, QString> fields, bool recurring);
void removeTimelinePin(const QUuid &uuid);
void insertReminder();
void clearTimeline();
diff --git a/rockworkd/libpebble/calendarevent.cpp b/rockworkd/libpebble/calendarevent.cpp
index ea99b56..ea3a3a7 100644
--- a/rockworkd/libpebble/calendarevent.cpp
+++ b/rockworkd/libpebble/calendarevent.cpp
@@ -124,6 +124,16 @@ void CalendarEvent::setRecurring(bool recurring)
m_recurring = recurring;
}
+bool CalendarEvent::isAllDay() const
+{
+ return m_isAllDay;
+}
+
+void CalendarEvent::setIsAllDay(bool isAllDay)
+{
+ m_isAllDay = isAllDay;
+}
+
bool CalendarEvent::operator==(const CalendarEvent &other) const
{
// Storing a QDateTime to QSettings seems to lose time zone information. Lets ignore the time zone when
@@ -141,8 +151,8 @@ bool CalendarEvent::operator==(const CalendarEvent &other) const
&& m_calendar == other.calendar()
&& m_comment == other.comment()
&& m_guests == other.guests()
- && m_recurring == other.recurring();
-
+ && m_recurring == other.recurring()
+ && m_isAllDay == other.isAllDay();
}
void CalendarEvent::saveToCache(const QString &cachePath) const
@@ -159,6 +169,7 @@ void CalendarEvent::saveToCache(const QString &cachePath) const
s.setValue("comment", m_comment);
s.setValue("guests", m_guests);
s.setValue("recurring", m_recurring);
+ s.setValue("isAllDay", m_isAllDay);
}
void CalendarEvent::loadFromCache(const QString &cachePath, const QString &uuid)
@@ -175,6 +186,7 @@ void CalendarEvent::loadFromCache(const QString &cachePath, const QString &uuid)
m_comment = s.value("comment").toString();
m_guests = s.value("guests").toStringList();
m_recurring = s.value("recurring").toBool();
+ m_isAllDay = s.value("isAllDay").toBool();
}
void CalendarEvent::removeFromCache(const QString &cachePath) const
diff --git a/rockworkd/libpebble/calendarevent.h b/rockworkd/libpebble/calendarevent.h
index 5361a48..30ce49f 100644
--- a/rockworkd/libpebble/calendarevent.h
+++ b/rockworkd/libpebble/calendarevent.h
@@ -46,6 +46,9 @@ public:
bool recurring() const;
void setRecurring(bool recurring);
+ bool isAllDay() const;
+ void setIsAllDay(bool isAllDay);
+
bool operator==(const CalendarEvent &other) const;
void saveToCache(const QString &cachePath) const;
@@ -64,6 +67,7 @@ private:
QString m_comment;
QStringList m_guests;
bool m_recurring = false;
+ bool m_isAllDay = false;
};
#endif // CALENDAREVENT_H
diff --git a/rockworkd/libpebble/jskit/jskitconsole.cpp b/rockworkd/libpebble/jskit/jskitconsole.cpp
index 3d6c85c..384965b 100644
--- a/rockworkd/libpebble/jskit/jskitconsole.cpp
+++ b/rockworkd/libpebble/jskit/jskitconsole.cpp
@@ -4,26 +4,209 @@
JSKitConsole::JSKitConsole(QObject *parent) :
QObject(parent),
- l(metaObject()->className())
+ l("JSKit Log"),
+ w("JSKit Warning"),
+ e("JSKit Error"),
+ i("JSKit Info")
{
}
-void JSKitConsole::log(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
{
- qCDebug(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
}
-void JSKitConsole::warn(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
{
- qCWarning(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
}
-void JSKitConsole::error(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
{
- qCCritical(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
}
-void JSKitConsole::info(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
{
- qCDebug(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCDebug(l) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1)
+{
+ qCDebug(l) << msg0 << msg1;
+}
+
+void JSKitConsole::log(const QString &msg0)
+{
+ qCDebug(l) << msg0;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCWarning(w) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1)
+{
+ qCWarning(w) << msg0 << msg1;
+}
+
+void JSKitConsole::warn(const QString &msg0)
+{
+ qCWarning(w) << msg0;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCCritical(e) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1)
+{
+ qCCritical(e) << msg0 << msg1;
+}
+
+void JSKitConsole::error(const QString &msg0)
+{
+ qCCritical(e) << msg0;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCDebug(i) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1)
+{
+ qCDebug(i) << msg0 << msg1;
+}
+
+void JSKitConsole::info(const QString &msg0)
+{
+ qCDebug(i) << msg0;
}
diff --git a/rockworkd/libpebble/jskit/jskitconsole.h b/rockworkd/libpebble/jskit/jskitconsole.h
index 3896ae3..6f8970d 100644
--- a/rockworkd/libpebble/jskit/jskitconsole.h
+++ b/rockworkd/libpebble/jskit/jskitconsole.h
@@ -3,18 +3,66 @@
#include <QLoggingCategory>
+/*
+ We opted to do multiple overloaded functions rather than one with default
+ arguments as this method produces nicer log messages and wont omit (possibly)
+ important messages like empty string, undefined, or null.
+*/
+
class JSKitConsole : public QObject
{
Q_OBJECT
QLoggingCategory l;
+ QLoggingCategory w;
+ QLoggingCategory e;
+ QLoggingCategory i;
public:
explicit JSKitConsole(QObject *parent=0);
- Q_INVOKABLE void log(const QString &msg);
- Q_INVOKABLE void warn(const QString &msg);
- Q_INVOKABLE void error(const QString &msg);
- Q_INVOKABLE void info(const QString &msg);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void log(const QString &msg0);
+
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void warn(const QString &msg0);
+
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void error(const QString &msg0);
+
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void info(const QString &msg0);
};
#endif // JSKITCONSOLE_H
diff --git a/rockworkd/libpebble/jskit/jskitmanager.cpp b/rockworkd/libpebble/jskit/jskitmanager.cpp
index 04bf674..8a03afd 100644
--- a/rockworkd/libpebble/jskit/jskitmanager.cpp
+++ b/rockworkd/libpebble/jskit/jskitmanager.cpp
@@ -82,7 +82,7 @@ AppInfo JSKitManager::currentApp()
void JSKitManager::handleAppStarted(const QUuid &uuid)
{
AppInfo info = m_apps->info(uuid);
- if (!info.uuid().isNull() && info.isJSKit()) {
+ if (!info.uuid().isNull() && info.isJSKit() && info.uuid() != m_curApp.uuid()) {
qCDebug(l) << "Preparing to start JSKit app" << info.uuid() << info.shortName();
m_curApp = info;
diff --git a/rockworkd/libpebble/jskit/jskitpebble.cpp b/rockworkd/libpebble/jskit/jskitpebble.cpp
index a300aef..e755d60 100644
--- a/rockworkd/libpebble/jskit/jskitpebble.cpp
+++ b/rockworkd/libpebble/jskit/jskitpebble.cpp
@@ -4,6 +4,7 @@
#include "jskitpebble.h"
#include "jskitxmlhttprequest.h"
+#include "jskitwebsocket.h"
static const char *token_salt = "0feeb7416d3c4546a19b04bccd8419b1";
@@ -315,10 +316,16 @@ void JSKitPebble::openURL(const QUrl &url)
QJSValue JSKitPebble::createXMLHttpRequest()
{
JSKitXMLHttpRequest *xhr = new JSKitXMLHttpRequest(m_mgr->engine());
- // Should be deleted by JS engine.
return m_mgr->engine()->newQObject(xhr);
}
+QJSValue JSKitPebble::createWebSocket(const QString &url, const QJSValue &protocols)
+{
+ JSKitWebSocket *ws = new JSKitWebSocket(m_mgr->engine(), url, protocols);
+ return m_mgr->engine()->newQObject(ws);
+}
+
+
QJSValue JSKitPebble::buildAckEventObject(uint transaction, const QString &message) const
{
QJSEngine *engine = m_mgr->engine();
diff --git a/rockworkd/libpebble/jskit/jskitpebble.h b/rockworkd/libpebble/jskit/jskitpebble.h
index d9cd670..c461adb 100644
--- a/rockworkd/libpebble/jskit/jskitpebble.h
+++ b/rockworkd/libpebble/jskit/jskitpebble.h
@@ -32,6 +32,7 @@ public:
Q_INVOKABLE void openURL(const QUrl &url);
Q_INVOKABLE QJSValue createXMLHttpRequest();
+ Q_INVOKABLE QJSValue createWebSocket(const QString &url, const QJSValue &protocols=QJSValue{});
void invokeCallbacks(const QString &type, const QJSValueList &args = QJSValueList());
diff --git a/rockworkd/libpebble/jskit/jskitsetup.js b/rockworkd/libpebble/jskit/jskitsetup.js
index 340c4f1..2f85c7d 100644
--- a/rockworkd/libpebble/jskit/jskitsetup.js
+++ b/rockworkd/libpebble/jskit/jskitsetup.js
@@ -81,16 +81,6 @@ console = new (function() {
);
})();
-/*localStorage = new (function() {
- _jskit.make_proxies(this, _jskit.localstorage,
- ['clear', 'getItem', 'setItem', 'removeItem', 'key']
- );
-
- _jskit.make_properties(this, _jskit.localstorage,
- ['length']
- );
-})();*/
-
//It appears that Proxy is not available since Qt is using Javascript v5
/*(function() {
var proxy = _jskit.make_proxies({}, _jskit.localstorage, ['set', 'has', 'deleteProperty', 'keys', 'enumerate']);
@@ -194,3 +184,97 @@ Object.defineProperty(window, "localStorage", new (function () {
localStorage.setItem(keys[index], value);
}
})();
+
+function WebSocket(url, protocols) {
+ var ws = _jskit.pebble.createWebSocket(url, protocols);
+ _jskit.make_proxies(this, ws, ['close', 'send']);
+ _jskit.make_properties(this, ws,
+ ['readyState', 'bufferedAmount', 'onopen', 'onerror', 'onclose', 'onmessage',
+ 'extensions', 'protocol', 'binaryType']);
+
+ this.CONNECTING = 0;
+ this.OPEN = 1;
+ this.CLOSING = 2;
+ this.CLOSED = 3;
+}
+
+//Borrowed from https://github.com/pebble/pypkjs/blob/master/pypkjs/javascript/events.py#L9
+Event = function(event_type, event_init_dict) {
+ var self = this;
+ this.stopPropagation = function() {};
+ this.stopImmediatePropagation = function() { self._aborted = true; }
+ this.preventDefault = function() { self.defaultPrevented = true; }
+ this.initEvent = function(event_type, bubbles, cancelable) {
+ self.type = event_type;
+ self.bubbles = bubbles;
+ self.cancelable = cancelable
+ };
+
+ if(!event_init_dict) event_init_dict = {};
+ this.type = event_type;
+ this.bubbles = event_init_dict.bubbles || false;
+ this.cancelable = event_init_dict.cancelable || false;
+ this.defaultPrevented = false;
+ this.target = null;
+ this.currentTarget = null;
+ this.eventPhase = 2;
+ this._aborted = false;
+};
+Event._init = function(event_type, event_init_dict) {
+ //Convenience function to call from the engine
+ return new Event(event_type, event_init_dict)
+};
+
+Event.NONE = 0;
+Event.CAPTURING_PHASE = 1;
+Event.AT_TARGET = 2;
+Event.BUBBLING_PHASE = 3;
+
+//Borrowed from https://github.com/pebble/pypkjs/blob/master/pypkjs/javascript/ws.py#L14
+CloseEvent = function(wasClean, code, reason, eventInitDict) {
+ Event.call(this, "close", eventInitDict);
+
+ Object.defineProperties(this, {
+ wasClean: {
+ get: function() { return wasClean; },
+ enumerable: true,
+ },
+ code: {
+ get: function() { return code; },
+ enumerable: true,
+ },
+ reason: {
+ get: function() { return reason; },
+ enumerable: true,
+ },
+ });
+};
+
+CloseEvent.prototype = Object.create(Event.prototype);
+CloseEvent.prototype.constructor = CloseEvent;
+CloseEvent._init = function(wasClean, code, reason) {
+ //Convenience function to call from the engine
+ return new CloseEvent(wasClean, code, reason)
+};
+
+MessageEvent = function(origin, data, eventInitDict) {
+ Event.call(this, "message", eventInitDict);
+
+ Object.defineProperties(this, {
+ origin: {
+ get: function() { return origin; },
+ enumerable: true,
+ },
+ data: {
+ get: function() { return data; },
+ enumerable: true,
+ }
+ });
+};
+
+MessageEvent.prototype = Object.create(Event.prototype);
+MessageEvent.prototype.constructor = MessageEvent;
+MessageEvent._init = function(origin, data) {
+ //Convenience function to call from the engine
+ return new MessageEvent(origin, data)
+}; \ No newline at end of file
diff --git a/rockworkd/libpebble/jskit/jskitwebsocket.cpp b/rockworkd/libpebble/jskit/jskitwebsocket.cpp
new file mode 100644
index 0000000..e66cdfb
--- /dev/null
+++ b/rockworkd/libpebble/jskit/jskitwebsocket.cpp
@@ -0,0 +1,311 @@
+#include "jskitwebsocket.h"
+#include "jskitmanager.h"
+
+JSKitWebSocket::JSKitWebSocket(QJSEngine *engine, const QString &url, const QJSValue &protocols) :
+ QObject(engine),
+ l(metaObject()->className()),
+ m_engine(engine),
+ m_webSocket(new QWebSocket("", QWebSocketProtocol::VersionLatest, this)),
+ m_url(url)
+{
+ //As of QT 5.5: "QWebSocket currently does not support extensions and subprotocols"
+ Q_UNUSED(protocols)
+
+ connect(m_webSocket, &QWebSocket::connected,
+ this, &JSKitWebSocket::handleConnected);
+ connect(m_webSocket, &QWebSocket::disconnected,
+ this, &JSKitWebSocket::handleDisconnected);
+ connect(m_webSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error),
+ this, &JSKitWebSocket::handleError);
+ connect(m_webSocket, &QWebSocket::sslErrors,
+ this, &JSKitWebSocket::handleSslErrors);
+ connect(m_webSocket, &QWebSocket::textMessageReceived,
+ this, &JSKitWebSocket::handleTextMessageReceived);
+ connect(m_webSocket, &QWebSocket::binaryMessageReceived,
+ this, &JSKitWebSocket::handleBinaryMessageReceived);
+
+ qCDebug(l) << "WebSocket opened for" << url;
+ //m_webSocket->ignoreSslErrors();
+ m_webSocket->open(QUrl(url));
+}
+
+void JSKitWebSocket::send(const QJSValue &data)
+{
+ //TODO throw SYNTAX_ERR if "The data is a string that has unpaired surrogates" - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+
+ if (m_readyState != OPEN) {
+ //TODO throw INVALID_STATE_ERR if not opened - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+ qCDebug(l) << "trying to send when connection is not yet open";
+
+ return;
+ }
+
+ if (data.isUndefined() || data.isNull()) {
+ qCDebug(l) << "Refusing to send a null or undefined message";
+ } else if (data.isString()) {
+ qCDebug(l) << "Sending text message:" << data.toString();
+
+ QByteArray byteData = data.toString().toUtf8();
+ m_bufferedAmount += byteData.size();
+
+ m_webSocket->sendTextMessage(data.toString());
+ } else if (data.isObject()) {
+ if (data.hasProperty("byteLength")) {
+ // Looks like an ArrayView or an ArrayBufferView!
+ QJSValue buffer = data.property("buffer");
+ if (buffer.isUndefined()) {
+ // We must assume we've been passed an ArrayBuffer directly
+ buffer = data;
+ }
+
+ QJSValue array = buffer.property("_bytes");
+ int byteLength = buffer.property("byteLength").toInt();
+
+ if (array.isArray()) {
+ QByteArray byteData;
+ byteData.reserve(byteLength);
+
+ for (int i = 0; i < byteLength; i++) {
+ byteData.append(array.property(i).toInt());
+ }
+
+ qCDebug(l) << "sending binary message with" << byteData.length() << "bytes";
+
+ m_bufferedAmount += byteData.size();
+ m_webSocket->sendBinaryMessage(byteData);
+ } else {
+ qCWarning(l) << "Refusing to send an unknown/invalid ArrayBuffer" << data.toString();
+ }
+ } else {
+ qCWarning(l) << "Refusing to send an unknown object:" << data.toString();
+ }
+ }
+}
+
+void JSKitWebSocket::close(quint32 code, const QString &reason)
+{
+ //TODO throw SYNTAX_ERR if "The reason string contains unpaired surrogates" - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+
+
+ QByteArray byteData = reason.toUtf8();
+ if (byteData.size() >= 123) {
+ //TODO throw SYNTAX_ERR for invalid reason - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown
+ qCDebug(l) << "Invalid reason";
+
+ return;
+ }
+
+ QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CloseCodeNormal;
+ if ((code >= 1000 && code <= 1011) || code == 1015) {
+ closeCode = static_cast<QWebSocketProtocol::CloseCode>(code);;
+ }
+ else {
+ //TODO throw INVALID_ACCESS_ERR for invalide code - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown
+ qCDebug(l) << "Invalid close code";
+
+ return;
+ }
+
+ m_webSocket->close(closeCode, reason);
+ m_readyState = CLOSING;
+}
+
+void JSKitWebSocket::setOnclose(const QJSValue &onclose)
+{
+ m_onclose = onclose;
+}
+
+void JSKitWebSocket::setOnerror(const QJSValue &onerror)
+{
+ m_onerror = onerror;
+}
+
+void JSKitWebSocket::setOnmessage(const QJSValue &onmessage)
+{
+ m_onmessage = onmessage;
+}
+
+void JSKitWebSocket::setOnopen(const QJSValue &onopen)
+{
+ m_onopen = onopen;
+}
+
+QJSValue JSKitWebSocket::onclose() const
+{
+ return m_onclose;
+}
+
+QJSValue JSKitWebSocket::onerror() const
+{
+ return m_onerror;
+}
+
+QJSValue JSKitWebSocket::onmessage() const
+{
+ return m_onmessage;
+}
+
+QJSValue JSKitWebSocket::onopen() const
+{
+ return m_onopen;
+}
+
+quint32 JSKitWebSocket::bufferedAmount()
+{
+ return m_bufferedAmount;
+}
+
+quint8 JSKitWebSocket::readyState()
+{
+ return m_readyState;
+}
+
+QString JSKitWebSocket::url()
+{
+ return m_url;
+}
+
+void JSKitWebSocket::handleConnected()
+{
+ m_readyState = OPEN;
+ qCDebug(l) << "Connection opened";
+
+ if (m_onopen.isCallable()) {
+ qCDebug(l) << "Going to call onopen";
+
+ QJSValueList eventArgs;
+ eventArgs.append("open");
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onopen.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onopen handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleDisconnected()
+{
+ m_readyState = CLOSED;
+ qCDebug(l) << "Connection closed";
+
+ if (m_onclose.isCallable()) {
+ qCDebug(l) << "Going to call onclose";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue(true)); //wasClean
+ eventArgs.append(QJSValue(m_webSocket->closeCode()));
+ eventArgs.append(QJSValue(m_webSocket->closeReason()));
+
+ QJSValue event = m_engine->globalObject().property("CloseEvent").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+
+ QJSValue result = m_onclose.callWithInstance(m_engine->newQObject(this));
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleError(QAbstractSocket::SocketError error)
+{
+ qCDebug(l) << "Error:" << error;
+
+ if (m_onerror.isCallable()) {
+ qCDebug(l) << "Going to call onerror";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue("error"));
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onerror.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleSslErrors(const QList<QSslError> &errors)
+{
+ qCDebug(l) << "Ssl Errors:" << errors;
+
+ if (m_onerror.isCallable()) {
+ qCDebug(l) << "Going to call onerror";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue("error"));
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onerror.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleTextMessageReceived(const QString &message)
+{
+ qCDebug(l) << "Text message recieved: " << message;
+
+ callOnmessage(QJSValue(message));
+}
+
+void JSKitWebSocket::handleBinaryMessageReceived(const QByteArray &message)
+{
+ qCDebug(l) << "Binary message recieved";
+
+ if (m_onmessage.isCallable()) {
+ if (m_binaryType == "arraybuffer") {
+ QJSValue arrayBufferProto = m_engine->globalObject().property("ArrayBuffer").property("prototype");
+ QJSValue arrayBuf = m_engine->newObject();
+
+ if (arrayBufferProto.isUndefined()) {
+ qCWarning(l) << "Cannot find proto of ArrayBuffer";
+ } else {
+ arrayBuf.setPrototype(arrayBufferProto);
+ arrayBuf.setProperty("byteLength", m_engine->toScriptValue<uint>(message.size()));
+
+ QJSValue array = m_engine->newArray(message.size());
+ for (int i = 0; i < message.size(); i++) {
+ array.setProperty(i, m_engine->toScriptValue<int>(message[i]));
+ }
+
+ arrayBuf.setProperty("_bytes", array);
+ qCDebug(l) << "calling onmessage with ArrayBuffer of" << message.size() << "bytes";
+
+ callOnmessage(arrayBuf);
+ }
+ } else {
+ qCWarning(l) << "unsupported binaryType:" << m_binaryType;
+ }
+ }
+}
+
+void JSKitWebSocket::callOnmessage(QJSValue data)
+{
+ if (m_onmessage.isCallable()) {
+ qCDebug(l) << "Going to call onmessage";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue(m_webSocket->origin()));
+ eventArgs.append(data);
+
+ QJSValue messageEvent = m_engine->globalObject().property("MessageEvent").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(messageEvent);
+
+ QJSValue result = m_onmessage.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onmessage handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
diff --git a/rockworkd/libpebble/jskit/jskitwebsocket.h b/rockworkd/libpebble/jskit/jskitwebsocket.h
new file mode 100644
index 0000000..192e9a4
--- /dev/null
+++ b/rockworkd/libpebble/jskit/jskitwebsocket.h
@@ -0,0 +1,79 @@
+#ifndef JSKITWEBSOCKET_P_H
+#define JSKITWEBSOCKET_P_H
+
+#include <QLoggingCategory>
+#include <QWebSocket>
+#include <QJSEngine>
+
+class JSKitWebSocket : public QObject
+{
+ Q_OBJECT
+ QLoggingCategory l;
+
+ Q_PROPERTY(QString binaryType MEMBER m_binaryType)
+ Q_PROPERTY(quint32 bufferedAmount READ bufferedAmount)
+ Q_PROPERTY(QString extensions MEMBER m_extensions)
+ Q_PROPERTY(QJSValue onclose READ onclose WRITE setOnclose)
+ Q_PROPERTY(QJSValue onerror READ onerror WRITE setOnerror)
+ Q_PROPERTY(QJSValue onmessage READ onmessage WRITE setOnmessage)
+ Q_PROPERTY(QJSValue onopen READ onopen WRITE setOnopen)
+ Q_PROPERTY(QString protocol MEMBER m_protocol)
+ Q_PROPERTY(quint8 readyState READ readyState)
+ Q_PROPERTY(QString url READ url)
+
+public:
+ explicit JSKitWebSocket(QJSEngine *engine, const QString &url, const QJSValue &protocols=QJSValue());
+
+ enum ReadyStates {
+ CONNECTING = 0,
+ OPEN = 1,
+ CLOSING = 2,
+ CLOSED = 3
+ };
+ Q_ENUMS(ReadyStates)
+
+ Q_INVOKABLE void send(const QJSValue &data);
+ Q_INVOKABLE void close(quint32 code=1000, const QString &reason=QString());
+
+ void setOnclose(const QJSValue &onclose);
+ void setOnerror(const QJSValue &onerror);
+ void setOnmessage(const QJSValue &onmessage);
+ void setOnopen(const QJSValue &onopen);
+
+ QJSValue onclose() const;
+ QJSValue onerror() const;
+ QJSValue onmessage() const;
+ QJSValue onopen() const;
+
+ quint32 bufferedAmount();
+ quint8 readyState();
+ QString url();
+
+private slots:
+ void handleConnected();
+ void handleDisconnected();
+ void handleError(QAbstractSocket::SocketError error);
+ void handleSslErrors(const QList<QSslError> &errors);
+ void handleTextMessageReceived(const QString &message);
+ void handleBinaryMessageReceived(const QByteArray &message);
+
+private:
+ void callOnmessage(QJSValue data);
+
+private:
+ QJSEngine *m_engine;
+ QWebSocket *m_webSocket;
+
+ QString m_binaryType = "arraybuffer";
+ quint32 m_bufferedAmount = 0;
+ QString m_extensions;
+ QJSValue m_onclose;
+ QJSValue m_onerror;
+ QJSValue m_onmessage;
+ QJSValue m_onopen;
+ QString m_protocol;
+ quint8 m_readyState = CONNECTING;
+ QString m_url;
+};
+
+#endif // JSKITWEBSOCKET_P_H
diff --git a/rockworkd/libpebble/pebble.cpp b/rockworkd/libpebble/pebble.cpp
index e421545..d2e44f5 100644
--- a/rockworkd/libpebble/pebble.cpp
+++ b/rockworkd/libpebble/pebble.cpp
@@ -60,7 +60,8 @@ Pebble::Pebble(const QBluetoothAddress &address, QObject *parent):
m_appMsgManager = new AppMsgManager(this, m_appManager, m_connection);
m_jskitManager = new JSKitManager(this, m_connection, m_appManager, m_appMsgManager, this);
- QObject::connect(m_jskitManager, SIGNAL(openURL(const QString&, const QString&)), this, SIGNAL(openURL(const QString&, const QString&)));
+ QObject::connect(m_jskitManager, &JSKitManager::openURL, this, &Pebble::openURL);
+ QObject::connect(m_appMsgManager, &AppMsgManager::appStarted, this, &Pebble::appStarted);
m_blobDB = new BlobDB(this, m_connection);
QObject::connect(m_blobDB, &BlobDB::muteSource, this, &Pebble::muteNotificationSource);
@@ -536,7 +537,7 @@ void Pebble::pebbleVersionReceived(const QByteArray &data)
qDebug() << "Is Unfaithful" << m_isUnfaithful;
// This is useful for debugging
- //m_isUnfaithful = true;
+// m_isUnfaithful = true;
if (!m_recovery) {
m_appManager->rescan();
@@ -624,6 +625,25 @@ void Pebble::appInstalled(const QUuid &uuid) {
if (m_pendingInstallations.contains(uuid)) {
m_appMsgManager->launchApp(uuid);
}
+
+ if (uuid == m_lastSyncedAppUuid) {
+ m_lastSyncedAppUuid = QUuid();
+
+ m_appManager->setAppOrder(m_appManager->appUuids());
+ QSettings settings(m_storagePath + "/appsettings.conf", QSettings::IniFormat);
+ if (settings.contains("watchface")) {
+ m_appMsgManager->launchApp(settings.value("watchface").toUuid());
+ }
+ }
+}
+
+void Pebble::appStarted(const QUuid &uuid)
+{
+ AppInfo info = m_appManager->info(uuid);
+ if (info.isWatchface()) {
+ QSettings settings(m_storagePath + "/appsettings.conf", QSettings::IniFormat);
+ settings.setValue("watchface", uuid.toString());
+ }
}
void Pebble::muteNotificationSource(const QString &source)
@@ -642,14 +662,14 @@ void Pebble::resetPebble()
void Pebble::syncApps()
{
+ QUuid lastSyncedAppUuid;
foreach (const QUuid &appUuid, m_appManager->appUuids()) {
if (!m_appManager->info(appUuid).isSystemApp()) {
qDebug() << "Inserting app" << m_appManager->info(appUuid).shortName() << "into BlobDB";
m_blobDB->insertAppMetaData(m_appManager->info(appUuid));
+ m_lastSyncedAppUuid = appUuid;
}
}
- // make sure the order is synced too
- m_appManager->setAppOrder(m_appManager->appUuids());
}
void Pebble::syncTime()
diff --git a/rockworkd/libpebble/pebble.h b/rockworkd/libpebble/pebble.h
index 8650d74..239b74b 100644
--- a/rockworkd/libpebble/pebble.h
+++ b/rockworkd/libpebble/pebble.h
@@ -115,6 +115,7 @@ private slots:
void phoneVersionAsked(const QByteArray &data);
void appDownloadFinished(const QString &id);
void appInstalled(const QUuid &uuid);
+ void appStarted(const QUuid &uuid);
void muteNotificationSource(const QString &source);
void resetPebble();
@@ -174,6 +175,7 @@ private:
QString m_storagePath;
QList<QUuid> m_pendingInstallations;
+ QUuid m_lastSyncedAppUuid;
bool m_calendarSyncEnabled = true;
HealthParams m_healthParams;