diff options
| author | Andrew Branson <andrew.branson@cern.ch> | 2016-02-18 09:13:32 +0100 |
|---|---|---|
| committer | Andrew Branson <andrew.branson@cern.ch> | 2016-02-18 09:13:32 +0100 |
| commit | f4910b3ac84c72a7e17c99895a3b9abb0e9534fe (patch) | |
| tree | 91ae8cfd80dc3d7a2adedee9cab0d407c5c23c84 /rockworkd/libpebble | |
| parent | 7305ce8e080d0a6ee7505fe978a2e601b56a5ce8 (diff) | |
| parent | 8f014f0915c7bdc97573f953aa9a3ae25a5f953a (diff) | |
Merge branch 'rockwork'
Conflicts:
po/de.po
po/en_GB.po
po/eu.po
po/fr.po
po/hu.po
po/it.po
po/pt.po
po/rockwork.mzanetti.pot
po/ru.po
po/template.pot
rockwork/InfoPage.qml
rockwork/Main.qml
rockwork/NotificationsPage.qml
rockworkd/rockworkd.pro
version.pri
Diffstat (limited to 'rockworkd/libpebble')
| -rw-r--r-- | rockworkd/libpebble/appmsgmanager.cpp | 28 | ||||
| -rw-r--r-- | rockworkd/libpebble/appmsgmanager.h | 2 | ||||
| -rw-r--r-- | rockworkd/libpebble/blobdb.cpp | 15 | ||||
| -rw-r--r-- | rockworkd/libpebble/blobdb.h | 2 | ||||
| -rw-r--r-- | rockworkd/libpebble/calendarevent.cpp | 16 | ||||
| -rw-r--r-- | rockworkd/libpebble/calendarevent.h | 4 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitconsole.cpp | 201 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitconsole.h | 56 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitmanager.cpp | 2 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitpebble.cpp | 9 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitpebble.h | 1 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitsetup.js | 104 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitwebsocket.cpp | 311 | ||||
| -rw-r--r-- | rockworkd/libpebble/jskit/jskitwebsocket.h | 79 | ||||
| -rw-r--r-- | rockworkd/libpebble/pebble.cpp | 28 | ||||
| -rw-r--r-- | rockworkd/libpebble/pebble.h | 2 |
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 ¬ification) 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 ¬ification) 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 ¬ification); - 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; |
