diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-14 22:33:35 +0100 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-14 22:33:35 +0100 |
| commit | a73ceae865428cdfcf7022677bad5f932379fbf6 (patch) | |
| tree | 6f0b994923e1c1f3ce1b3b1c89301e69a7867997 | |
| parent | e8f9a4da6c486ee4da9ae300019856976ff0a760 (diff) | |
| parent | 0da3325dcab2ebd419d1d0b1a59428f3201a5732 (diff) | |
Merge pull request #29 from smurfy/pebble-store
Pebble store support
| -rw-r--r-- | app/app.pro | 11 | ||||
| -rw-r--r-- | app/pebble.cpp | 3 | ||||
| -rw-r--r-- | app/pebblestoreview.cpp | 149 | ||||
| -rw-r--r-- | app/pebblestoreview.h | 52 | ||||
| -rw-r--r-- | app/qml/pages/AppStorePage.qml | 101 | ||||
| -rw-r--r-- | app/qml/pages/InstallAppDialog.qml | 4 |
6 files changed, 316 insertions, 4 deletions
diff --git a/app/app.pro b/app/app.pro index 97c6232..9600919 100644 --- a/app/app.pro +++ b/app/app.pro @@ -2,7 +2,7 @@ TARGET = pebble CONFIG += sailfishapp -QT += dbus +QT += dbus webkit quick-private webkit-private CONFIG += c++11 DEFINES += APP_VERSION=\\\"$$VERSION\\\" @@ -10,11 +10,13 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\" SOURCES += \ pebble.cpp \ pebbledinterface.cpp \ - pebbleappiconprovider.cpp + pebbleappiconprovider.cpp \ + pebblestoreview.cpp HEADERS += \ pebbledinterface.h \ - pebbleappiconprovider.h + pebbleappiconprovider.h \ + pebblestoreview.h DBUS_INTERFACES += ../org.pebbled.Watch.xml @@ -30,7 +32,8 @@ OTHER_FILES += \ qml/images/* \ translations/*.ts \ pebble.desktop \ - pebble.png + pebble.png \ + qml/pages/AppStorePage.qml CONFIG += sailfishapp_i18n TRANSLATIONS += translations/pebble-es.ts diff --git a/app/pebble.cpp b/app/pebble.cpp index 22f6ac1..dd3c915 100644 --- a/app/pebble.cpp +++ b/app/pebble.cpp @@ -34,6 +34,7 @@ #include <sailfishapp.h> #include "pebbledinterface.h" #include "pebbleappiconprovider.h" +#include "pebblestoreview.h" int main(int argc, char *argv[]) { @@ -48,6 +49,8 @@ int main(int argc, char *argv[]) qmlRegisterUncreatableType<PebbledInterface>("org.pebbled", 0, 1, "PebbledInterface", "Please use pebbled context property"); + qmlRegisterType<PebbleStoreView>("org.pebbled", 0, 1, "PebbleStoreView"); + QScopedPointer<QQuickView> view(SailfishApp::createView()); QScopedPointer<PebbledInterface> pebbled(new PebbledInterface); QScopedPointer<PebbleAppIconProvider> appicons(new PebbleAppIconProvider(pebbled.data())); diff --git a/app/pebblestoreview.cpp b/app/pebblestoreview.cpp new file mode 100644 index 0000000..0ea5c14 --- /dev/null +++ b/app/pebblestoreview.cpp @@ -0,0 +1,149 @@ +#include "pebblestoreview.h" +#include <QUrlQuery> +#include <QStandardPaths> +#include <QDir> +#include <QFile> + +PebbleStoreView::PebbleStoreView() + : QQuickWebView() +{ + connect(this, SIGNAL(navigationRequested(QWebNavigationRequest*)), this, SLOT(onNavigationRequested(QWebNavigationRequest*))); + + this->m_networkManager = new QNetworkAccessManager(this); + connect(this->m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onNetworkReplyFinished(QNetworkReply*))); + + this->m_configUrl = QUrl("https://boot.getpebble.com/api/config/android/v1/3"); + this->m_downloadInProgress = false; + emit downloadInProgressChanged(); + + //Fetching urls to use by the store + fetchData(this->m_configUrl); +} + +QString PebbleStoreView::accessToken() const +{ + return this->m_accessToken; +} + +void PebbleStoreView::setAccessToken(const QString &accessToken) +{ + this->m_accessToken = accessToken; + emit accessTokenChanged(accessToken); +} + +void PebbleStoreView::logout() +{ + setAccessToken(""); + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("authentication").toString())); +} + +bool PebbleStoreView::loggedin() +{ + return (!this->m_accessToken.isEmpty()); +} + +bool PebbleStoreView::downloadInProgress() +{ + return this->m_downloadInProgress; +} + +void PebbleStoreView::gotoWatchFaces() +{ + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("appstore/watchfaces").toString())); +} + +void PebbleStoreView::gotoWatchApps() +{ + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("appstore/watchapps").toString())); +} + +void PebbleStoreView::fetchData(QUrl url) +{ + QNetworkRequest request; + request.setUrl(url); + request.setRawHeader("Cache-Control", "no-cache"); + this->m_networkManager->get(request); +} + +void PebbleStoreView::onNetworkReplyFinished(QNetworkReply* reply) +{ + qDebug()<<"Download finished"; + if (reply->request().url() == this->m_configUrl) { + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll()); + QJsonObject jsonObject = jsonResponse.object(); + this->storeConfigObject = jsonObject.value("config").toObject(); + + if (this->m_accessToken.isEmpty()) { + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("authentication").toString())); + } else { + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("onboarding/get_some_apps").toString())); + } + } else { + QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); + QFile file(dataDir.absoluteFilePath("apps") + "/" + this->downloadObject.value("uuid").toString() + ".pbw"); + file.open(QIODevice::WriteOnly); + file.write(reply->readAll()); + file.close(); + + qDebug()<<this->downloadObject; + + this->m_downloadInProgress = false; + emit downloadInProgressChanged(); + } +} + +QUrl PebbleStoreView::prepareUrl(QString baseUrl) +{ + baseUrl = baseUrl.replace("$$user_id$$", "ZZZ"); + baseUrl = baseUrl.replace("$$phone_id$$", "XXX"); + baseUrl = baseUrl.replace("$$pebble_id$$", "YYY"); + baseUrl = baseUrl.replace("$$access_token$$", this->m_accessToken); + + qDebug()<<baseUrl; + + return QUrl(baseUrl); +} + +void PebbleStoreView::onNavigationRequested(QWebNavigationRequest* request) +{ + if (request->url().scheme() == "pebble") { + if (request->url().host() == "login") { + QUrlQuery *accessTokenFragment = new QUrlQuery(request->url().fragment()); + this->m_accessToken = accessTokenFragment->queryItemValue("access_token"); + emit accessTokenChanged(accessTokenFragment->queryItemValue("access_token")); + setUrl(prepareUrl(this->storeConfigObject.value("webviews").toObject().value("onboarding/get_some_apps").toString())); + } + } + if (request->url().scheme() == "pebble-method-call-js-frame") { + QString urlStr = ""; + + //Basic parse error string + QRegExp reg(".*; source was \"(.*)\";.*"); + reg.setMinimal(true); + if (reg.indexIn(request->url().errorString()) > -1) { + urlStr = reg.cap(1); + reg.setPattern("method=(.*)&args=(.*)$"); + reg.setMinimal(true); + if (reg.indexIn(urlStr) > -1) { + QString methodStr = reg.cap(1); + QString argsStr = QUrl::fromPercentEncoding(reg.cap(2).toUtf8()); + emit call(methodStr, argsStr); + if (methodStr == "loadAppToDeviceAndLocker") { + QJsonDocument jsonResponse = QJsonDocument::fromJson(argsStr.toUtf8()); + QJsonObject jsonObject = jsonResponse.object(); + QJsonObject data = jsonObject.value("data").toObject(); + qDebug()<<"download"<<data.value("title").toString()<<data.value("pbw_file").toString(); + this->downloadObject = data;; + this->m_downloadInProgress = true; + emit downloadInProgressChanged(); + fetchData(QUrl(data.value("pbw_file").toString())); + emit downloadPebbleApp(data.value("title").toString(), data.value("pbw_file").toString()); + } + } + } + } +} + + + + diff --git a/app/pebblestoreview.h b/app/pebblestoreview.h new file mode 100644 index 0000000..a19b43d --- /dev/null +++ b/app/pebblestoreview.h @@ -0,0 +1,52 @@ +#ifndef PEBBLESTOREVIEW_H +#define PEBBLESTOREVIEW_H + +#include <private/qquickwebview_p.h> +#include <private/qwebnavigationrequest_p.h> +#include <QNetworkReply> +#include <QNetworkAccessManager> +#include <QJsonDocument> +#include <QJsonObject> + +class PebbleStoreView : public QQuickWebView +{ + Q_OBJECT +public: + PebbleStoreView(); + Q_PROPERTY(bool loggedin READ loggedin NOTIFY accessTokenChanged) + Q_PROPERTY(bool downloadInProgress READ downloadInProgress NOTIFY downloadInProgressChanged) + Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken NOTIFY accessTokenChanged) + + bool loggedin(); + bool downloadInProgress(); + QString accessToken() const; + void setAccessToken(const QString &accessToken); + +public slots: + void gotoWatchFaces(); + void gotoWatchApps(); + void logout(); + +private slots: + void onNavigationRequested(QWebNavigationRequest* request); + void onNetworkReplyFinished(QNetworkReply* reply); + +signals: + void accessTokenChanged(const QString & accessToken); + void downloadPebbleApp(const QString & downloadTitle, const QString & downloadUrl); + void downloadInProgressChanged(); + void call(const QString &, const QString &); + +private: + QNetworkAccessManager* m_networkManager; + QUrl m_configUrl; + QString m_accessToken; + QJsonObject downloadObject; + QJsonObject storeConfigObject; + bool m_downloadInProgress; + + QUrl prepareUrl(QString baseUrl); + void fetchData(QUrl url); +}; + +#endif // PEBBLESTOREVIEW_H diff --git a/app/qml/pages/AppStorePage.qml b/app/qml/pages/AppStorePage.qml new file mode 100644 index 0000000..680ac50 --- /dev/null +++ b/app/qml/pages/AppStorePage.qml @@ -0,0 +1,101 @@ +import QtQuick 2.0 +import QtQml 2.1 +import Sailfish.Silica 1.0 +import org.pebbled 0.1 +import org.nemomobile.configuration 1.0 + +Page { + id: page + + ConfigurationGroup { + id: settings + path: "/org/pebbled/settings" + property string storeAccessToken: "" + } + + SilicaFlickable { + id: flickable + anchors.fill: parent + contentHeight: column.height + webview.height + + PullDownMenu { + visible: webview.loggedin; + + MenuItem { + text: qsTr("Logout") + onClicked: { + webview.logout(); + } + } + } + + Column { + id: column + width: page.width + spacing: Theme.paddingLarge + + PageHeader { + title: qsTr("Pebble Appstore") + } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + visible: webview.loggedin; + Button { + text: qsTr("WatchApps") + onClicked: { + webview.gotoWatchApps(); + } + } + Button { + text: qsTr("WatchFaces") + onClicked: { + webview.gotoWatchFaces(); + } + } + } + + Column { + id: download + visible: webview.downloadInProgress + width: parent.width + + Label { + anchors.horizontalCenter: parent.horizontalCenter + id: downloadLabel + text: qsTr("Downloading...") + } + + BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: true + size: BusyIndicatorSize.Large + } + } + } + + PebbleStoreView { + id: webview + visible: !webview.downloadInProgress + width: page.width + height: page.height - column.height + + anchors { + top: column.bottom + } + + accessToken: settings.storeAccessToken + + onAccessTokenChanged: { + settings.storeAccessToken = accessToken; + } + + onDownloadPebbleApp: { + downloadLabel.text = qsTr("Downloading %1...").arg(downloadTitle) + } + } + } + + +} + diff --git a/app/qml/pages/InstallAppDialog.qml b/app/qml/pages/InstallAppDialog.qml index ecc3d78..4661cf0 100644 --- a/app/qml/pages/InstallAppDialog.qml +++ b/app/qml/pages/InstallAppDialog.qml @@ -84,6 +84,10 @@ Dialog { } } + MenuItem { + text: qsTr("Pebble Appstore") + onClicked: pageStack.push(Qt.resolvedUrl("AppStorePage.qml")) + } } currentIndex: -1 |
