Add support for deep linking through push notification data
This commit is contained in:
parent
10c0e531b7
commit
aec0d7c5df
@ -222,8 +222,11 @@ int Thing::executeAction(const QString &actionName, const QVariantList ¶ms)
|
||||
{
|
||||
ActionType *actionType = m_thingClass->actionTypes()->findByName(actionName);
|
||||
if (!actionType) {
|
||||
qCWarning(dcThingManager) << "No such action name" << actionName << "in thing class" << m_thingClass->name();
|
||||
return -1;
|
||||
actionType = m_thingClass->actionTypes()->getActionType(QUuid(actionName));
|
||||
if (!actionType) {
|
||||
qCWarning(dcThingManager) << "No such action" << actionName << "in thing class" << m_thingClass->name();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
QVariantList finalParams;
|
||||
|
||||
@ -105,7 +105,8 @@ ubuntu_files.files += \
|
||||
packaging/ubuntu/click/appicon.svg \
|
||||
packaging/ubuntu/click/push.json \
|
||||
packaging/ubuntu/click/push-apparmor.json \
|
||||
packaging/ubuntu/click/pushexec
|
||||
packaging/ubuntu/click/pushexec \
|
||||
packaging/ubuntu/click/urls.json
|
||||
|
||||
INSTALLS += ubuntu_files
|
||||
}
|
||||
|
||||
@ -98,7 +98,13 @@ int main(int argc, char *argv[])
|
||||
// Initialize app log controller as early as possible, but after setting app name and printing initial startup info
|
||||
AppLogController::instance();
|
||||
|
||||
qCInfo(dcApplication()) << "*** nymea:app starting ***" << QDateTime::currentDateTime().toString();
|
||||
qCInfo(dcApplication()) << "*** nymea:app starting ***" << QDateTime::currentDateTime().toString() << application.arguments();
|
||||
|
||||
foreach (const QString &argument, application.arguments()) {
|
||||
if (argument.startsWith("nymea://notification")) {
|
||||
PlatformHelper::instance()->notificationActionReceived(QUrlQuery(QUrl(argument).query()).queryItemValue("nymeaData"));
|
||||
}
|
||||
}
|
||||
|
||||
QTranslator qtTranslator;
|
||||
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
|
||||
@ -183,7 +183,7 @@ ubports: {
|
||||
DEFINES += UBPORTS
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += connectivity-qt1
|
||||
PKGCONFIG += connectivity-qt1 dbus-1 libnih-dbus libnih
|
||||
|
||||
HEADERS += platformintegration/ubports/pushclient.h \
|
||||
platformintegration/ubports/platformhelperubports.h \
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#if defined Q_OS_ANDROID
|
||||
#include <QtAndroidExtras/QtAndroid>
|
||||
@ -56,9 +58,34 @@ PlatformHelper::PlatformHelper(QObject *parent) : QObject(parent)
|
||||
|
||||
}
|
||||
|
||||
PlatformHelper *PlatformHelper::instance()
|
||||
void PlatformHelper::notificationActionReceived(const QString &nymeaData)
|
||||
{
|
||||
if (!s_instance) {
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(nymeaData.toUtf8(), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPlatformIntegration()) << "Received a notification action but cannot parse it:" << error.errorString() << nymeaData;
|
||||
return;
|
||||
}
|
||||
QVariantMap map = jsonDoc.toVariant().toMap();
|
||||
QUuid id = QUuid::createUuid();
|
||||
map.insert("id", id);
|
||||
|
||||
// transforming data from a url query to a map for easier processing in QML
|
||||
QUrlQuery query(map.value("data").toString());
|
||||
QVariantMap dataMap;
|
||||
for (int i = 0; i < query.queryItems().count(); i++) {
|
||||
const QPair<QString, QString> &item = query.queryItems().at(i);
|
||||
dataMap.insert(item.first, item.second);
|
||||
}
|
||||
map.insert("dataMap", dataMap);
|
||||
|
||||
m_pendingNotificationActions.insert(id, map);
|
||||
emit pendingNotificationActionsChanged();
|
||||
}
|
||||
|
||||
PlatformHelper *PlatformHelper::instance(bool create)
|
||||
{
|
||||
if (!s_instance && create) {
|
||||
#ifdef Q_OS_ANDROID
|
||||
s_instance = new PlatformHelperAndroid();
|
||||
#elif defined(Q_OS_IOS)
|
||||
@ -178,6 +205,17 @@ bool PlatformHelper::darkModeEnabled() const
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantList PlatformHelper::pendingNotificationActions() const
|
||||
{
|
||||
return m_pendingNotificationActions.values();
|
||||
}
|
||||
|
||||
void PlatformHelper::notificationActionHandled(const QUuid &id)
|
||||
{
|
||||
m_pendingNotificationActions.remove(id);
|
||||
emit pendingNotificationActionsChanged();
|
||||
}
|
||||
|
||||
bool PlatformHelper::splashVisible() const
|
||||
{
|
||||
return m_splashVisible;
|
||||
|
||||
@ -33,6 +33,9 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QColor>
|
||||
#include <QHash>
|
||||
#include <QUuid>
|
||||
#include <QVariant>
|
||||
|
||||
class QQmlEngine;
|
||||
class QJSEngine;
|
||||
@ -54,6 +57,7 @@ class PlatformHelper : public QObject
|
||||
Q_PROPERTY(QColor topPanelColor READ topPanelColor WRITE setTopPanelColor NOTIFY topPanelColorChanged)
|
||||
Q_PROPERTY(QColor bottomPanelColor READ bottomPanelColor WRITE setBottomPanelColor NOTIFY bottomPanelColorChanged)
|
||||
Q_PROPERTY(bool darkModeEnabled READ darkModeEnabled NOTIFY darkModeEnabledChanged)
|
||||
Q_PROPERTY(QVariantList pendingNotificationActions READ pendingNotificationActions NOTIFY pendingNotificationActionsChanged)
|
||||
|
||||
public:
|
||||
enum HapticsFeedback {
|
||||
@ -63,7 +67,7 @@ public:
|
||||
};
|
||||
Q_ENUM(HapticsFeedback)
|
||||
|
||||
static PlatformHelper* instance();
|
||||
static PlatformHelper* instance(bool create = true);
|
||||
virtual ~PlatformHelper() = default;
|
||||
|
||||
virtual bool hasPermissions() const;
|
||||
@ -89,6 +93,9 @@ public:
|
||||
|
||||
virtual bool darkModeEnabled() const;
|
||||
|
||||
QVariantList pendingNotificationActions() const;
|
||||
Q_INVOKABLE void notificationActionHandled(const QUuid &id);
|
||||
|
||||
virtual bool splashVisible() const;
|
||||
virtual void setSplashVisible(bool splashVisible);
|
||||
Q_INVOKABLE virtual void hideSplashScreen();
|
||||
@ -102,6 +109,9 @@ public:
|
||||
Q_INVOKABLE virtual void shareFile(const QString &fileName);
|
||||
|
||||
static QObject *platformHelperProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||
|
||||
void notificationActionReceived(const QString &nymeaData);
|
||||
|
||||
signals:
|
||||
void permissionsRequestFinished();
|
||||
void screenTimeoutChanged();
|
||||
@ -110,6 +120,7 @@ signals:
|
||||
void bottomPanelColorChanged();
|
||||
void darkModeEnabledChanged();
|
||||
void splashVisibleChanged();
|
||||
void pendingNotificationActionsChanged();
|
||||
|
||||
protected:
|
||||
explicit PlatformHelper(QObject *parent = nullptr);
|
||||
@ -121,6 +132,8 @@ private:
|
||||
QColor m_bottomPanelColor = QColor("black");
|
||||
|
||||
bool m_splashVisible = true;
|
||||
|
||||
QHash<QUuid, QVariant> m_pendingNotificationActions;
|
||||
};
|
||||
|
||||
#endif // PLATFORMHELPER_H
|
||||
|
||||
@ -44,7 +44,13 @@ public class NymeaAppNotificationService extends FirebaseMessagingService {
|
||||
Intent intent = new Intent(this, NymeaAppActivity.class);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, 0);
|
||||
|
||||
Log.d(TAG, "adding extra data to intent: " + remoteMessage.getData().get("nymeaData"));
|
||||
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra("notificationData", remoteMessage.getData().get("nymeaData"));
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
// We can't directly access R.drawable.ic_stat_notification from here:
|
||||
// When the package is branded, the package name is not "io.guh.nymeaapp" and resources in
|
||||
@ -63,6 +69,17 @@ public class NymeaAppNotificationService extends FirebaseMessagingService {
|
||||
.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
// Action tests
|
||||
// Intent actionIntent = new Intent(this, NymeaAppActivity.class);
|
||||
// actionIntent.setAction(Intent.ACTION_SEND);
|
||||
// actionIntent.putExtra("foobar", "baz");
|
||||
// PendingIntent actionPendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, actionIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
// notificationBuilder.addAction(resId, "30%", actionPendingIntent);
|
||||
// notificationBuilder.addAction(resId, "50%", actionPendingIntent);
|
||||
// notificationBuilder.addAction(resId, "70%", actionPendingIntent);
|
||||
// Action tests end
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
@ -20,6 +20,7 @@ public class NymeaAppActivity extends org.qtproject.qt5.android.bindings.QtActiv
|
||||
private static Context context = null;
|
||||
|
||||
private static native void darkModeEnabledChangedJNI();
|
||||
private static native void notificationActionReceivedJNI(String data);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -27,12 +28,24 @@ public class NymeaAppActivity extends org.qtproject.qt5.android.bindings.QtActiv
|
||||
this.context = getApplicationContext();
|
||||
}
|
||||
|
||||
public void onNewIntent (Intent intent) {
|
||||
Log.d(TAG, "New intent: " + intent);
|
||||
String notificationData = intent.getStringExtra("notificationData");
|
||||
if (notificationData != null) {
|
||||
Log.d(TAG, "Intent data: " + notificationData);
|
||||
notificationActionReceivedJNI(notificationData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
NymeaAppActivity.darkModeEnabledChangedJNI();
|
||||
}
|
||||
|
||||
public String notificationData() {
|
||||
return getIntent().getStringExtra("notificationData");
|
||||
}
|
||||
|
||||
public static Context getAppContext() {
|
||||
return NymeaAppActivity.context;
|
||||
|
||||
@ -48,6 +48,7 @@ static PlatformHelperAndroid *m_instance = nullptr;
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
{ "darkModeEnabledChangedJNI", "()V", (void *)PlatformHelperAndroid::darkModeEnabledChangedJNI },
|
||||
{ "notificationActionReceivedJNI", "(Ljava/lang/String;)V", (void *)PlatformHelperAndroid::notificationActionReceivedJNI },
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
|
||||
@ -77,6 +78,10 @@ PlatformHelperAndroid::PlatformHelperAndroid(QObject *parent) : PlatformHelper(p
|
||||
{
|
||||
m_instance = this;
|
||||
|
||||
QString notificationData = QtAndroid::androidActivity().callObjectMethod("notificationData", "()Ljava/lang/String;").toString();
|
||||
if (!notificationData.isNull()) {
|
||||
notificationActionReceived(notificationData);
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformHelperAndroid::requestPermissions()
|
||||
@ -274,3 +279,13 @@ void PlatformHelperAndroid::darkModeEnabledChangedJNI()
|
||||
emit m_instance->darkModeEnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformHelperAndroid::notificationActionReceivedJNI(JNIEnv *env, jobject, jstring data)
|
||||
{
|
||||
// Only call the platformhelper if it exists yet. We may get this callback before the Qt part is created
|
||||
// and we don't want to create the PlatformHelper on the android thread.
|
||||
PlatformHelper* platformHelper = PlatformHelperAndroid::instance(false);
|
||||
if (platformHelper) {
|
||||
platformHelper->notificationActionReceived(env->GetStringUTFChars(data, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ public:
|
||||
void shareFile(const QString &fileName) override;
|
||||
|
||||
static void darkModeEnabledChangedJNI();
|
||||
static void notificationActionReceivedJNI(JNIEnv *env, jobject /*thiz*/, jstring data);
|
||||
|
||||
private:
|
||||
static void permissionRequestFinished(const QtAndroid::PermissionResultMap &);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#import "UIKit/UIKit.h"
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
|
||||
// Include our C++ class
|
||||
#include "pushnotifications.h"
|
||||
#include "platformhelper.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@ -76,6 +76,11 @@
|
||||
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
|
||||
NSLog(@"User Info : %@",response.notification.request.content.userInfo);
|
||||
qDebug() << "received notification response!";
|
||||
|
||||
NSString *nymeaData = response.notification.request.content.userInfo[@"gcm.notification.nymeaData"];
|
||||
|
||||
PlatformHelper::instance()->notificationActionReceived(QString::fromNSString(nymeaData));
|
||||
|
||||
completionHandler();
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,23 @@
|
||||
#include <libnih.h>
|
||||
#include <libnih-dbus.h>
|
||||
|
||||
#include "platformhelperubports.h"
|
||||
|
||||
|
||||
#include <QSettings>
|
||||
#include <QUuid>
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
#include <QDBusConnection>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
|
||||
PlatformHelperUBPorts::PlatformHelperUBPorts(QObject *parent) : PlatformHelper(parent)
|
||||
|
||||
PlatformHelperUBPorts::PlatformHelperUBPorts(QObject *parent):
|
||||
PlatformHelper(parent),
|
||||
m_uriHandlerObject(this)
|
||||
{
|
||||
|
||||
setupUriHandler();
|
||||
}
|
||||
|
||||
QString PlatformHelperUBPorts::platform() const
|
||||
@ -21,3 +33,49 @@ QString PlatformHelperUBPorts::deviceSerial() const
|
||||
}
|
||||
return s.value("deviceSerial").toString();
|
||||
}
|
||||
|
||||
void PlatformHelperUBPorts::setupUriHandler()
|
||||
{
|
||||
QString objectPath;
|
||||
|
||||
if (!QDBusConnection::sessionBus().isConnected()) {
|
||||
qWarning() << "UCUriHandler: D-Bus session bus is not connected, ignoring.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the object path based on the "APP_ID" environment variable.
|
||||
QByteArray applicationId = qgetenv("APP_ID");
|
||||
if (applicationId.isEmpty()) {
|
||||
qWarning() << "UCUriHandler: Empty \"APP_ID\" environment variable, ignoring.";
|
||||
return;
|
||||
}
|
||||
char* path = nih_dbus_path(NULL, "", applicationId.constData(), nullptr);
|
||||
objectPath = QString::fromLocal8Bit(path);
|
||||
nih_free(path);
|
||||
|
||||
// Ensure handler is running on the main thread.
|
||||
QCoreApplication* instance = QCoreApplication::instance();
|
||||
if (instance) {
|
||||
moveToThread(instance->thread());
|
||||
} else {
|
||||
qWarning() << "UCUriHandler: Created before QCoreApplication, application may misbehave.";
|
||||
}
|
||||
|
||||
QDBusConnection::sessionBus().registerObject(
|
||||
objectPath, &m_uriHandlerObject, QDBusConnection::ExportAllSlots);
|
||||
}
|
||||
|
||||
UriHandlerObject::UriHandlerObject(PlatformHelper *platformHelper):
|
||||
m_platformHelper(platformHelper)
|
||||
{
|
||||
}
|
||||
|
||||
void UriHandlerObject::Open(const QStringList& uris, const QHash<QString, QVariant>& platformData)
|
||||
{
|
||||
Q_UNUSED(platformData);
|
||||
foreach (const QString &uri, uris) {
|
||||
if (uri.startsWith("nymea://notification")) {
|
||||
m_platformHelper->notificationActionReceived(QUrlQuery(QUrl(uri)).queryItemValue("nymeaData"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,22 @@
|
||||
|
||||
#include "platformhelper.h"
|
||||
|
||||
class UriHandlerObject: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
|
||||
|
||||
public:
|
||||
UriHandlerObject(PlatformHelper* platformHelper);
|
||||
|
||||
public Q_SLOTS:
|
||||
void Open(const QStringList& uris, const QHash<QString, QVariant>& platformData);
|
||||
|
||||
private:
|
||||
PlatformHelper* m_platformHelper = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class PlatformHelperUBPorts : public PlatformHelper
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -16,6 +32,11 @@ public:
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
void setupUriHandler();
|
||||
|
||||
UriHandlerObject m_uriHandlerObject;
|
||||
|
||||
};
|
||||
|
||||
#endif // PLATFORMHELPERUBPORTS_H
|
||||
|
||||
@ -26,6 +26,10 @@
|
||||
{
|
||||
"name": "body",
|
||||
"value": "%0 runs out of battery"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"value": "open=$0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -58,6 +62,10 @@
|
||||
{
|
||||
"name": "body",
|
||||
"value": "%0 runs dry"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"value": "open=$0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -90,6 +98,10 @@
|
||||
{
|
||||
"name": "body",
|
||||
"value": "%0 has disconnected"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"value": "open=$0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -122,6 +134,10 @@
|
||||
{
|
||||
"name": "body",
|
||||
"value": "%0 has connected"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"value": "open=$0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -44,6 +44,11 @@ import "mainviews"
|
||||
Page {
|
||||
id: root
|
||||
|
||||
// Removing the background from this page only because the MainViewBase adds it again in
|
||||
// a deepter layer as we need to include it in the blurring of the header and footer.
|
||||
// We don't want to paint the background on the entire screen twice (overdraw is costly)
|
||||
background: null
|
||||
|
||||
function configureViews() {
|
||||
if (Configuration.hasOwnProperty("mainViewsFilter")) {
|
||||
console.warn("Main views configuration is disabled by app configuration")
|
||||
@ -54,10 +59,21 @@ Page {
|
||||
d.configOverlay = configComponent.createObject(contentContainer)
|
||||
}
|
||||
|
||||
// Removing the background from this page only because the MainViewBase adds it again in
|
||||
// a deepter layer as we need to include it in the blurring of the header and footer.
|
||||
// We don't want to paint the background on the entire screen twice (overdraw is costly)
|
||||
background: null
|
||||
function goToView(viewName, data) {
|
||||
// We allow separating the target by : and pass more stuff to
|
||||
console.log("Going to main view", viewName, filteredContentModel.count, data)
|
||||
for (var i = 0; i < filteredContentModel.count; i++) {
|
||||
console.log("got", i, filteredContentModel.modelData(i, "name"))
|
||||
if (filteredContentModel.modelData(i, "name") === viewName) {
|
||||
console.log("activating", i)
|
||||
// mainViewSettings.currentIndex = i;
|
||||
// tabBar.currentIndex = i;
|
||||
swipeView.setCurrentIndex(i)
|
||||
swipeView.currentItem.item.handleEvent(data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header: Item {
|
||||
id: mainHeader
|
||||
@ -245,6 +261,7 @@ Page {
|
||||
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
|
||||
|
||||
Repeater {
|
||||
id: mainViewsRepeater
|
||||
model: d.configOverlay != null ? null : filteredContentModel
|
||||
|
||||
delegate: Loader {
|
||||
|
||||
@ -426,12 +426,57 @@ Item {
|
||||
target: engine.thingManager
|
||||
onFetchingDataChanged: {
|
||||
if (!engine.thingManager.fetchingData) {
|
||||
processPendingPushNotificationActions();
|
||||
updatePushNotificationThings()
|
||||
}
|
||||
PlatformHelper.hideSplashScreen();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: PlatformHelper
|
||||
onPendingNotificationActionsChanged: {
|
||||
processPendingPushNotificationActions()
|
||||
}
|
||||
}
|
||||
function processPendingPushNotificationActions() {
|
||||
print("pending notification actions changed:", PlatformHelper.pendingNotificationActions)
|
||||
if (PlatformHelper.pendingNotificationActions.length > 0) {
|
||||
var notificationAction = PlatformHelper.pendingNotificationActions[0]
|
||||
if (notificationAction.serverUuid.replace(/[{]]/g, "") !== engine.jsonRpcClient.serverUuid.toString().replace(/[{}]/g, "")) {
|
||||
print("notification action for different server")
|
||||
return;
|
||||
}
|
||||
print("handling action", JSON.stringify(notificationAction))
|
||||
|
||||
if (notificationAction.dataMap.hasOwnProperty("open")) {
|
||||
// It could be just a thing ID
|
||||
var target = notificationAction.dataMap["open"]
|
||||
var thing = engine.thingManager.things.getThing(target)
|
||||
if (thing) {
|
||||
print("opening thing:", thing.name)
|
||||
pageStack.push("/ui/devicepages/" + NymeaUtils.interfaceListToDevicePage(thing.thingClass.interfaces), {thing: thing})
|
||||
} else {
|
||||
// or a view name
|
||||
console.log("going to main view:", target)
|
||||
pageStack.currentItem.goToView(target, notificationAction.dataMap)
|
||||
}
|
||||
}
|
||||
|
||||
if (notificationAction.dataMap.hasOwnProperty("execute")) {
|
||||
var action = notificationAction.dataMap["execute"]
|
||||
var thingId = notificationAction.dataMap["thingId"]
|
||||
var actionParams = JSON.parse(notificationAction.dataMap["actionParams"])
|
||||
print("executing:", thingId, action, actionParams)
|
||||
engine.thingManager.things.getThing(thingId).executeAction(action, actionParams);
|
||||
}
|
||||
|
||||
|
||||
PlatformHelper.notificationActionHandled(notificationAction.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: invalidVersionComponent
|
||||
Popup {
|
||||
|
||||
@ -49,6 +49,11 @@ Item {
|
||||
|
||||
property var headerButtons: []
|
||||
|
||||
// Override this to receive events (e.g. from push notification bubbles)
|
||||
function handleEvent(data) {
|
||||
print("handleEvent not implemented in", title)
|
||||
}
|
||||
|
||||
Background {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
@ -747,6 +747,8 @@ WizardPageBase {
|
||||
|
||||
content: ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Style.margins
|
||||
Layout.rightMargin: Style.margins
|
||||
Layout.maximumWidth: 500
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredHeight: visibleContentHeight
|
||||
@ -755,6 +757,7 @@ WizardPageBase {
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("You can now go ahead and configure your nymea system.")
|
||||
visible: wirelessConnectionCompletedPage.host != null
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
BusyIndicator {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
@ -278,6 +278,7 @@ Page {
|
||||
print("replacing args", typeof actionParam.value)
|
||||
if (typeof actionParam.value === "string") {
|
||||
actionParam.value = actionParam.value.replace("%" + selectionId, thingName);
|
||||
actionParam.value = actionParam.value.replace("$" + selectionId, selectedThings[selectionId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,6 +288,7 @@ Page {
|
||||
var actionParam = action.ruleActionParams.get(k);
|
||||
if (typeof actionParam.value === "string") {
|
||||
actionParam.value = actionParam.value.replace("%" + selectionId, thingName);
|
||||
actionParam.value = actionParam.value.replace("$" + selectionId, selectedThings[selectionId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -445,6 +447,11 @@ Page {
|
||||
for (var j = 0; j < ruleActionTemplate.ruleActionParamTemplates.count; j++) {
|
||||
var ruleActionParamTemplate = ruleActionTemplate.ruleActionParamTemplates.get(j)
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParamTemplate.paramName);
|
||||
if (!paramType) {
|
||||
print("Skipping template action param", ruleActionParamTemplate, "as action type does not have this param")
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ruleActionParamTemplate.value !== undefined) {
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParamTemplate.value)
|
||||
} else if (ruleActionParamTemplate.eventInterface && ruleActionParamTemplate.eventName && ruleActionParamTemplate.eventParamName) {
|
||||
|
||||
@ -11,7 +11,9 @@
|
||||
"qml-module-qtcharts",
|
||||
"qml-module-qt-labs-calendar",
|
||||
"libconnectivity-qt1-dev",
|
||||
"libunity-api-dev"
|
||||
"libunity-api-dev",
|
||||
"libnih-dbus-dev",
|
||||
"libdbus-1-dev"
|
||||
],
|
||||
"install_qml": [
|
||||
"/usr/lib/${ARCH_TRIPLET}/qt5/qml/Qt/labs/calendar/"
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
"hooks": {
|
||||
"nymea-app": {
|
||||
"apparmor": "nymea-app.apparmor",
|
||||
"desktop": "nymea-app.desktop"
|
||||
"desktop": "nymea-app.desktop",
|
||||
"urls": "urls.json"
|
||||
},
|
||||
"push": {
|
||||
"apparmor": "push-apparmor.json",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name=nymea:app
|
||||
Exec=usr/bin/nymea-app
|
||||
Exec=usr/bin/nymea-app %U
|
||||
Icon=appicon.svg
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
||||
@ -7,13 +7,25 @@ import json
|
||||
f1, f2 = sys.argv[1:3]
|
||||
|
||||
payloadJson = json.load(open(f1))
|
||||
print("<<<< Input: %s" % payloadJson)
|
||||
|
||||
# Set an icon
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
payloadJson["notification"]["card"]["icon"] = dir_path + "/appicon.svg"
|
||||
|
||||
payloadJson["notification"]["card"]["actions"] = ["appid://io.guh.nymeaapp/nymea-app/current-user-version"]
|
||||
|
||||
# Define the on-click action
|
||||
action = "appid://io.guh.nymeaapp/nymea-app/current-user-version" # The default action (just opening the app)
|
||||
if "nymeaData" in payloadJson["notification"]:
|
||||
action = "nymea://notification?nymeaData=%s" % json.dumps(payloadJson["notification"]["nymeaData"])
|
||||
|
||||
payloadJson["notification"]["card"]["actions"] = [action]
|
||||
#payloadJson["notification"]["emblem-counter"] = {"count": 1, "visible": True }
|
||||
|
||||
print(payloadJson)
|
||||
#print("nymeaData: %s" % nymeaData)
|
||||
print("action: %s" % action)
|
||||
|
||||
print(">>>> Output: %s" % payloadJson)
|
||||
|
||||
open(f2, "w").write(json.dumps(payloadJson) + "\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user