← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~mzanetti/reminders-app/fix-enable-push into lp:reminders-app

 

Michael Zanetti has proposed merging lp:~mzanetti/reminders-app/fix-enable-push into lp:reminders-app.

Commit message:
Fix the remaining issues in the push notification integration and enable it.

Requested reviews:
  Ubuntu Reminders app developers (reminders-app-dev)

For more details, see:
https://code.launchpad.net/~mzanetti/reminders-app/fix-enable-push/+merge/262541
-- 
Your team Ubuntu Reminders app developers is requested to review the proposed merge of lp:~mzanetti/reminders-app/fix-enable-push into lp:reminders-app.
=== modified file 'src/account-plugin/qml/evernote/Main.qml.in'
--- src/account-plugin/qml/evernote/Main.qml.in	2015-02-20 21:18:01 +0000
+++ src/account-plugin/qml/evernote/Main.qml.in	2015-06-21 16:30:06 +0000
@@ -24,7 +24,7 @@
     creationComponent: OAuth {
         Connections {
             target: UserStore
-            onUsernameChanged: saveUsername()
+            onUserChanged: saveUsername()
         }
 
         function completeCreation(reply) {
@@ -37,7 +37,7 @@
         }
 
         function saveUsername() {
-            account.updateDisplayName(UserStore.username)
+            account.updateDisplayName(UserStore.userName)
             account.synced.connect(finished)
             account.sync()
         }

=== modified file 'src/app/preferences.cpp'
--- src/app/preferences.cpp	2015-02-23 18:00:46 +0000
+++ src/app/preferences.cpp	2015-06-21 16:30:06 +0000
@@ -80,3 +80,19 @@
     m_settings.endGroup();
     return colorName;
 }
+
+QString Preferences::tokenForUser(const QString &user)
+{
+    QString token;
+    m_settings.beginGroup("accounts");
+    token = m_settings.value(user).toString();
+    m_settings.endGroup();
+    return token;
+}
+
+void Preferences::setTokenForUser(const QString &user, const QString &token)
+{
+    m_settings.beginGroup("accounts");
+    m_settings.setValue(user, token);
+    m_settings.endGroup();
+}

=== modified file 'src/app/preferences.h'
--- src/app/preferences.h	2015-03-06 00:47:45 +0000
+++ src/app/preferences.h	2015-06-21 16:30:06 +0000
@@ -45,6 +45,9 @@
 
     Q_INVOKABLE QString colorForNotebook(const QString &notebookGuid);
 
+    Q_INVOKABLE QString tokenForUser(const QString &user);
+    Q_INVOKABLE void setTokenForUser(const QString &user, const QString &token);
+
 signals:
     void accountNameChanged();
     void haveLocalUserChanged();

=== modified file 'src/app/qml/reminders.qml'
--- src/app/qml/reminders.qml	2015-06-12 09:48:22 +0000
+++ src/app/qml/reminders.qml	2015-06-21 16:30:06 +0000
@@ -280,9 +280,13 @@
     }
 
     function registerPushClient() {
-        console.log("Registering push client");
+        console.log("Registering push client", JSON.stringify({
+                                                                  "userId" : "" +  UserStore.userId,
+                                                                  "appId": root.applicationName + "_reminders",
+                                                                  "token": pushClient.token
+                                                              }));
         var req = new XMLHttpRequest();
-        req.open("post", "http://162.213.35.108/register";, true);
+        req.open("post", "https://push.ubuntu.com/gateway/register";, true);
         req.setRequestHeader("content-type", "application/json");
         req.onreadystatechange = function() {//Call a function when the state changes.
             print("push client register response")
@@ -295,7 +299,7 @@
             }
         }
         req.send(JSON.stringify({
-            "userId" : UserStore.username,
+            "userId" : "" + UserStore.userId,
             "appId": root.applicationName + "_reminders",
             "token": pushClient.token
         }))
@@ -324,18 +328,30 @@
         onNotificationsChanged: {
             print("PushClient notification:", notifications)
             var notification = JSON.parse(notifications)["payload"];
-            print("user", notification["userId"])
-            if (notification["userId"] !== UserStore.username) {
-                console.warn("user mismatch:", notification["userId"], "!=", UserStore.username)
+
+            if (notification["userId"] != UserStore.userId) { // Yes, we want type coercion here.
+                console.warn("user mismatch:", notification["userId"], "!=", UserStore.userId)
                 return;
             }
 
-            if (notification["notebookGUID"] !== undefined) {
+            switch(notification["reason"]) {
+            case "update":
+                print("Note updated on server:", notification["guid"])
+                if (NotesStore.note(notification["guid"]) === null) {
+                    NotesStore.refreshNotes();
+                } else {
+                    NotesStore.refreshNoteContent(notification["guid"]);
+                }
+                break;
+            case "create":
+                print("New note appeared on server:", notification["guid"])
+                NotesStore.refreshNotes();
+                break;
+            case "notebook_update":
                 NotesStore.refreshNotebooks();
-                NotesStore.refreshNotes(notification["notebookGUID"]);
-            }
-            if (notification["noteGUID"] !== undefined) {
-                NotesStore.refreshNoteContent(notification["noteGUID"]);
+                break;
+            default:
+                console.warn("Unhandled push notification:", notification["reason"])
             }
         }
 
@@ -412,10 +428,10 @@
 
     Connections {
         target: UserStore
-        onUsernameChanged: {
-            print("Logged in as user:", UserStore.username);
-            // Disabling push notifications as we haven't had a chance to properly test that yet
-            //registerPushClient();
+        onUserChanged: {
+            print("Logged in as user:", UserStore.userId, UserStore.userName);
+            preferences.setTokenForUser(UserStore.userId, EvernoteConnection.token);
+            registerPushClient();
         }
     }
 

=== modified file 'src/libqtevernote/jobs/fetchusernamejob.cpp'
--- src/libqtevernote/jobs/fetchusernamejob.cpp	2014-09-19 21:31:39 +0000
+++ src/libqtevernote/jobs/fetchusernamejob.cpp	2015-06-21 16:30:06 +0000
@@ -42,12 +42,10 @@
 
 void FetchUsernameJob::startJob()
 {
-    evernote::edam::User user;
-    client()->getUser(user, token().toStdString());
-    m_result = QString::fromStdString(user.username);
+    client()->getUser(m_user, token().toStdString());
 }
 
 void FetchUsernameJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
 {
-    emit jobDone(errorCode, errorMessage, m_result);
+    emit jobDone(errorCode, errorMessage, m_user.id, QString::fromStdString(m_user.username));
 }

=== modified file 'src/libqtevernote/jobs/fetchusernamejob.h'
--- src/libqtevernote/jobs/fetchusernamejob.h	2014-09-19 21:31:39 +0000
+++ src/libqtevernote/jobs/fetchusernamejob.h	2015-06-21 16:30:06 +0000
@@ -33,14 +33,14 @@
     virtual void attachToDuplicate(const EvernoteJob *other) override;
 
 signals:
-    void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result);
+    void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const int userId, const QString &userName);
 
 protected:
     void startJob();
     void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
 
 private:
-    QString m_result;
+    evernote::edam::User m_user;
 };
 
 #endif // FETCHUSERNAMEJOB_H

=== modified file 'src/libqtevernote/notesstore.cpp'
--- src/libqtevernote/notesstore.cpp	2015-06-12 09:48:22 +0000
+++ src/libqtevernote/notesstore.cpp	2015-06-21 16:30:06 +0000
@@ -61,7 +61,7 @@
     m_tagsLoading(false)
 {
     qCDebug(dcNotesStore) << "Creating NotesStore instance.";
-    connect(UserStore::instance(), &UserStore::usernameChanged, this, &NotesStore::userStoreConnected);
+    connect(UserStore::instance(), &UserStore::userChanged, this, &NotesStore::userStoreConnected);
 
     qRegisterMetaType<evernote::edam::NotesMetadataList>("evernote::edam::NotesMetadataList");
     qRegisterMetaType<evernote::edam::Note>("evernote::edam::Note");
@@ -98,7 +98,7 @@
         // We don't accept an empty username.
         return;
     }
-    if (!UserStore::instance()->username().isEmpty() && username != UserStore::instance()->username()) {
+    if (!UserStore::instance()->userName().isEmpty() && username != UserStore::instance()->userName()) {
         qCWarning(dcNotesStore) << "Logged in to Evernote. Can't change account manually. User EvernoteConnection to log in to another account or log out and change this manually.";
         return;
     }
@@ -118,8 +118,9 @@
     return QStandardPaths::standardLocations(QStandardPaths::DataLocation).first() + "/" + m_username + "/";
 }
 
-void NotesStore::userStoreConnected(const QString &username)
+void NotesStore::userStoreConnected()
 {
+    QString username = UserStore::instance()->userName();
     qCDebug(dcNotesStore) << "User store connected! Using username:" << username;
     setUsername(username);
 
@@ -738,10 +739,12 @@
                 connect(job, &SaveNoteJob::jobDone, this, &NotesStore::saveNoteJobDone);
                 EvernoteConnection::instance()->enqueue(job);
             } else {
-                qCWarning(dcSync) << "CONFLICT: Note has been changed on server and locally!";
-                qCWarning(dcSync) << "local note sequence:" << note->updateSequenceNumber();
-                qCWarning(dcSync) << "last synced sequence:" << note->lastSyncedSequenceNumber();
-                qCWarning(dcSync) << "remote sequence:" << result.updateSequenceNum;
+                qCWarning(dcSync) << "********************************************************";
+                qCWarning(dcSync) << "* CONFLICT: Note has been changed on server and locally!";
+                qCWarning(dcSync) << "* local note sequence:" << note->updateSequenceNumber();
+                qCWarning(dcSync) << "* last synced sequence:" << note->lastSyncedSequenceNumber();
+                qCWarning(dcSync) << "* remote update sequence:" << result.updateSequenceNum;
+                qCWarning(dcSync) << "********************************************************";
                 note->setConflicting(true);
                 changedRoles << RoleConflicting;
 
@@ -826,19 +829,7 @@
 
                 if (note->synced()) {
                     qCDebug(dcSync) << "Note has been deleted from the server and not changed locally. Deleting local note:" << note->guid();
-                    beginRemoveRows(QModelIndex(), idx, idx);
-                    m_notes.removeAt(idx);
-                    m_notesHash.remove(note->guid());
-                    endRemoveRows();
-                    emit noteRemoved(note->guid(), note->notebookGuid());
-                    emit countChanged();
-
-                    QSettings settings(m_cacheFile, QSettings::IniFormat);
-                    settings.beginGroup("notes");
-                    settings.remove(note->guid());
-                    settings.endGroup();
-
-                    note->deleteLater();
+                    removeNote(note->guid());
                 } else {
                     qCDebug(dcSync) << "CONFLICT: Note has been deleted from the server but we have unsynced local changes for note:" << note->guid();
                     FetchNoteJob::LoadWhatFlags flags = 0x0;
@@ -902,6 +893,12 @@
         return;
     }
 
+    if (result.deleted > 0) {
+        qCDebug(dcSync) << "Note has been deleted on server. Deleting locally.";
+        removeNote(note->guid());
+        return;
+    }
+
     if (note->notebookGuid() != QString::fromStdString(result.notebookGuid)) {
         note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
         roles << RoleGuid;
@@ -914,6 +911,18 @@
         note->setUpdated(QDateTime::fromMSecsSinceEpoch(result.updated));
         roles << RoleUpdated << RoleUpdatedString;
     }
+    QStringList tagGuids;
+    for (quint32 i = 0; i < result.tagGuids.size(); i++) {
+        QString tag = QString::fromStdString(result.tagGuids.at(i));
+        if (m_tagsHash.contains(tag)) {
+            refreshTags();
+        }
+        tagGuids << tag;
+    }
+    if (note->tagGuids() != tagGuids) {
+        note->setTagGuids(tagGuids);
+        roles << RoleTagGuids;
+    }
 
     // Notes are fetched without resources by default. if we discover one or more resources where we don't have
     // data in the cache, let's refresh the note again with resource data.
@@ -948,11 +957,14 @@
     if (what == FetchNoteJob::LoadContent) {
         note->setEnmlContent(QString::fromStdString(result.content));
         note->setUpdateSequenceNumber(result.updateSequenceNum);
+        note->setLastSyncedSequenceNumber(result.updateSequenceNum);
         roles << RoleHtmlContent << RoleEnmlContent << RoleTagline << RolePlaintextContent;
     }
+    bool syncReminders = false;
     if (note->reminderOrder() != result.attributes.reminderOrder) {
         note->setReminderOrder(result.attributes.reminderOrder);
         roles << RoleReminder;
+        syncReminders = true;
     }
     QDateTime reminderTime;
     if (result.attributes.reminderTime > 0) {
@@ -961,6 +973,7 @@
     if (note->reminderTime() != reminderTime) {
         note->setReminderTime(reminderTime);
         roles << RoleReminderTime << RoleReminderTimeString;
+        syncReminders = true;
     }
     QDateTime reminderDoneTime;
     if (result.attributes.reminderDoneTime > 0) {
@@ -969,6 +982,10 @@
     if (note->reminderDoneTime() != reminderDoneTime) {
         note->setReminderDoneTime(reminderDoneTime);
         roles << RoleReminderDone << RoleReminderDoneTime;
+        syncReminders = true;
+    }
+    if (syncReminders) {
+        m_organizerAdapter->startSync();
     }
 
     note->setLoading(false);
@@ -1456,14 +1473,7 @@
     int idx = m_notes.indexOf(note);
 
     if (note->lastSyncedSequenceNumber() == 0) {
-        emit noteRemoved(note->guid(), note->notebookGuid());
-        beginRemoveRows(QModelIndex(), idx, idx);
-        m_notes.takeAt(idx);
-        m_notesHash.take(guid);
-        endRemoveRows();
-        emit countChanged();
-        deleteFromCacheFile(note);
-        note->deleteLater();
+        removeNote(guid);
     } else {
 
         qCDebug(dcNotesStore) << "Setting note to deleted:" << note->guid();
@@ -1516,18 +1526,7 @@
         qCWarning(dcSync) << "Cannot delete note from server:" << errorMessage;
         return;
     }
-    Note *note = m_notesHash.value(guid);
-    int noteIndex = m_notes.indexOf(note);
-
-    emit noteRemoved(guid, note->notebookGuid());
-
-    beginRemoveRows(QModelIndex(), noteIndex, noteIndex);
-    m_notes.takeAt(noteIndex);
-    m_notesHash.take(guid);
-    endRemoveRows();
-    emit countChanged();
-    deleteFromCacheFile(note);
-    note->deleteLater();
+    removeNote(guid);
 }
 
 void NotesStore::expungeNotebookJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid)
@@ -1786,6 +1785,26 @@
     return true;
 }
 
+void NotesStore::removeNote(const QString &guid)
+{
+    Note *note = m_notesHash.value(guid);
+    int idx = m_notes.indexOf(note);
+
+    emit noteRemoved(note->guid(), note->notebookGuid());
+
+    beginRemoveRows(QModelIndex(), idx, idx);
+    m_notes.removeAt(idx);
+    m_notesHash.remove(note->guid());
+    endRemoveRows();
+    emit countChanged();
+
+    QSettings settings(m_cacheFile, QSettings::IniFormat);
+    settings.beginGroup("notes");
+    settings.remove(note->guid());
+    settings.endGroup();
+
+    note->deleteLater();
+}
 
 void NotesStore::expungeTag(const QString &guid)
 {

=== modified file 'src/libqtevernote/notesstore.h'
--- src/libqtevernote/notesstore.h	2015-06-11 18:55:24 +0000
+++ src/libqtevernote/notesstore.h	2015-06-21 16:30:06 +0000
@@ -205,7 +205,7 @@
     void syncToCacheFile(Tag *tag);
     void loadFromCacheFile();
 
-    void userStoreConnected(const QString &username);
+    void userStoreConnected();
     void emitDataChanged();
     void clear();
 
@@ -215,6 +215,8 @@
 
     bool handleUserError(EvernoteConnection::ErrorCode errorCode);
 
+    void removeNote(const QString &guid);
+
 private:
     explicit NotesStore(QObject *parent = 0);
     static NotesStore *s_instance;

=== modified file 'src/libqtevernote/userstore.cpp'
--- src/libqtevernote/userstore.cpp	2015-03-06 00:47:45 +0000
+++ src/libqtevernote/userstore.cpp	2015-06-21 16:30:06 +0000
@@ -57,9 +57,13 @@
     return s_instance;
 }
 
-QString UserStore::username() const
-{
-    return m_username;
+qint32 UserStore::userId() const
+{
+    return m_userId;
+}
+QString UserStore::userName() const
+{
+    return m_userName;
 }
 
 void UserStore::fetchUsername()
@@ -69,18 +73,21 @@
         connect(job, &FetchUsernameJob::jobDone, this, &UserStore::fetchUsernameJobDone);
         EvernoteConnection::instance()->enqueue(job);
     } else {
-        m_username.clear();
-        emit usernameChanged(m_username);
+        m_userId = -1;
+        m_userName.clear();
+        emit userChanged();
     }
 }
 
-void UserStore::fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result)
+void UserStore::fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const int userId, const QString &userName)
 {
     if (errorCode != EvernoteConnection::ErrorCodeNoError) {
         qCWarning(dcConnection) << "Error fetching username:" << errorMessage;
         return;
     }
 
-    m_username = result;
-    emit usernameChanged(m_username);
+    qCDebug(dcConnection) << "FetchUsername done. User ID:" << userId << "User name:" << userName;
+    m_userId = userId;
+    m_userName = userName;
+    emit userChanged();
 }

=== modified file 'src/libqtevernote/userstore.h'
--- src/libqtevernote/userstore.h	2014-12-08 10:25:48 +0000
+++ src/libqtevernote/userstore.h	2015-06-21 16:30:06 +0000
@@ -33,26 +33,29 @@
     Q_OBJECT
 
     // TODO: Once we need more than just the username, turn this into a class User
-    Q_PROPERTY(QString username READ username NOTIFY usernameChanged)
+    Q_PROPERTY(qint32 userId READ userId NOTIFY userChanged)
+    Q_PROPERTY(QString userName READ userName NOTIFY userChanged)
 
 public:
     static UserStore* instance();
 
-    QString username() const;
+    qint32 userId() const;
+    QString userName() const;
 
 signals:
-    void usernameChanged(const QString &username);
+    void userChanged();
 
 private slots:
     void fetchUsername();
 
-    void fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result);
+    void fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const int userId, const QString &userName);
 
 private:
     static UserStore* s_instance;
     explicit UserStore(QObject *parent = 0);
 
-    QString m_username;
+    qint32 m_userId;
+    QString m_userName;
 };
 
 #endif // USERSTORE_H

=== modified file 'src/push-helper/core.cpp'
--- src/push-helper/core.cpp	2014-12-08 10:25:48 +0000
+++ src/push-helper/core.cpp	2015-06-21 16:30:06 +0000
@@ -4,35 +4,48 @@
 #include "notesstore.h"
 #include "note.h"
 
+#include <Accounts/Manager>
+#include <Accounts/AccountService>
+
 #include <QDebug>
 #include <QOrganizerEvent>
+#include <QStandardPaths>
+#include <QJsonDocument>
 
 Core::Core(QObject *parent):
     QObject(parent)
 {
-    qDebug() << "Core starting up";
     connect(EvernoteConnection::instance(), &EvernoteConnection::isConnectedChanged, this, &Core::connectedChanged);
-    qDebug() << "EvernoteConnection created";
     connect(NotesStore::instance(), &NotesStore::loadingChanged, this, &Core::notesLoaded);
-    qDebug() << "notestore created";
-//    connect(&m_oaSetup, &OnlineAccountsClient::Setup::finished, this, &Core::oaRequestFinished);
-
-
-//    m_oaSetup.setApplicationId("com.ubuntu.reminders_reminders");
-//    m_oaSetup.setServiceTypeId("evernote");
-//    m_oaSetup.exec();
-//    qDebug() << "OA request started";
-
-    EvernoteConnection::instance()->setToken("S=s358:U=39eb980:E=1516e9a3575:C=14a16e90690:P=185:A=canonicalis:V=2:H=737f36850d4943e61ff2fcf7b4c809e2");
+}
+
+bool Core::process(const QByteArray &pushNotification)
+{
+    qDebug() << "should process:" << pushNotification;
+
+    QJsonParseError error;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(pushNotification, &error);
+    if (error.error != QJsonParseError::NoError) {
+        qDebug() << "Error parsing notification json:" << error.errorString();
+        return false;
+    }
+    QVariantMap notification = jsonDoc.toVariant().toMap().value("payload").toMap();
+
+    QSettings settings(QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/com.ubuntu.reminders/reminders.conf", QSettings::IniFormat);
+    settings.beginGroup("accounts");
+    QString token = settings.value(notification.value("userId").toString()).toString();
+    settings.endGroup();
+
+    if (token.isEmpty()) {
+        qDebug() << "No token found for this userId in " + settings.fileName() + ". Discarding push notification...";
+        return false;
+    }
+
+    EvernoteConnection::instance()->setToken(token);
     EvernoteConnection::instance()->setHostname("www.evernote.com");
     EvernoteConnection::instance()->connectToEvernote();
 
-    qDebug() << "Core created";
-}
-
-void Core::process(const QByteArray &pushNotification)
-{
-    qDebug() << "should process:" << pushNotification;
+    return true;
 }
 
 void Core::connectedChanged()
@@ -48,13 +61,5 @@
 void Core::notesLoaded()
 {
     qDebug() << "notes loading changed:" << NotesStore::instance()->loading();
-    foreach (Note *note, NotesStore::instance()->notes()) {
-        qDebug() << "have note" << note->title();
-        qDebug() << "content:" << note->plaintextContent();
-    }
 }
 
-void Core::oaRequestFinished(const QVariantMap &reply)
-{
-    qDebug() << "OA reply" << reply;
-}

=== modified file 'src/push-helper/core.h'
--- src/push-helper/core.h	2014-12-14 02:40:47 +0000
+++ src/push-helper/core.h	2015-06-21 16:30:06 +0000
@@ -9,7 +9,7 @@
 public:
     Core(QObject *parent = 0);
 
-    void process(const QByteArray &pushNotification);
+    bool process(const QByteArray &pushNotification);
 
 
 signals:

=== modified file 'src/push-helper/main.cpp'
--- src/push-helper/main.cpp	2014-12-06 22:35:01 +0000
+++ src/push-helper/main.cpp	2015-06-21 16:30:06 +0000
@@ -23,6 +23,7 @@
 
     Core core;
     QObject::connect(&core, &Core::finished, &a, &QCoreApplication::exit);
+
     core.process(data);
 
     a.exec();


Follow ups