From 655f2e368466b1bbfbdfcf4d8a80b0c173a8090e Mon Sep 17 00:00:00 2001
From: Nicolas Jager <nicolas.jager@savoirfairelinux.com>
Date: Mon, 11 Dec 2017 15:13:15 -0500
Subject: [PATCH] get number of unread messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

add functions to get the number of unread messages. Clients get the
number of unread messages in a conversation when getting
ConversationInfo.

additional test coming with : testCount, count the number of
occurrences in the database matching a value.

Change-Id: Ie7db0b7f288bfe82b64518dd1e9790837c2a2087
Reviewed-by: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
---
 src/authority/databasehelper.cpp |  5 +++++
 src/authority/databasehelper.h   |  4 ++++
 src/conversationmodel.cpp        | 18 +++++++++++++++++-
 src/database.cpp                 | 17 +++++++++++++++++
 src/database.h                   |  8 ++++++++
 test/databasetester.cpp          |  8 ++++++++
 test/databasetester.h            |  5 +++++
 7 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/src/authority/databasehelper.cpp b/src/authority/databasehelper.cpp
index 7f5da0d6..79601e12 100644
--- a/src/authority/databasehelper.cpp
+++ b/src/authority/databasehelper.cpp
@@ -342,6 +342,11 @@ addContact(Database& db, const std::string& accountUri, const std::string& conta
     }
 }
 
+int
+countUnreadFromInteractions(Database& db, const std::string& conversationId)
+{
+    return db.count("status", "interactions", "status='UNREAD' AND conversation_id='" + conversationId + "'");
+}
 
 } // namespace database
 
diff --git a/src/authority/databasehelper.h b/src/authority/databasehelper.h
index 34d61250..b61d6167 100644
--- a/src/authority/databasehelper.h
+++ b/src/authority/databasehelper.h
@@ -210,6 +210,10 @@ void removeAccount(Database& db, const std::string& accountUri);
  */
 void addContact(Database& db, const std::string& accountUri, const std::string& contactUri);
 
+/**
+ * count number of 'UNREAD' from 'interactions' table.
+ */
+int countUnreadFromInteractions(Database& db, const std::string& conversationId);
 
 } // namespace database
 
diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index 5db7a818..f9614ff0 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -125,6 +125,11 @@ public:
      */
     void placeCall(const std::string& uid, bool isAudioOnly = false);
 
+    /**
+     * get number of unread messages
+     */
+    int getNumberOfUnreadMessagesFor(const std::string& uid);
+
     const ConversationModel& linked;
     Database& db;
     const CallbacksHandler& callbacksHandler;
@@ -276,7 +281,11 @@ ConversationModel::filteredConversation(const unsigned int row) const
     const auto& conversations = allFilteredConversations();
     if (row >= conversations.size())
         return conversation::Info();
-    return conversations.at(row);
+
+    auto conversationInfo = conversations.at(row);
+    conversationInfo.unreadMessages = pimpl_->getNumberOfUnreadMessagesFor(conversationInfo.uid);
+
+    return conversationInfo;
 }
 
 void
@@ -896,6 +905,7 @@ ConversationModelPimpl::addConversationWith(const std::string& convId,
         }
     }
 
+    conversation.unreadMessages = getNumberOfUnreadMessagesFor(convId);
     conversations.emplace_front(conversation);
     dirtyConversations = true;
 }
@@ -1163,6 +1173,12 @@ ConversationModelPimpl::slotConferenceRemoved(const std::string& confId)
     }
 }
 
+int
+ConversationModelPimpl::getNumberOfUnreadMessagesFor(const std::string& uid)
+{
+    database::countUnreadFromInteractions(db, uid);
+}
+
 } // namespace lrc
 
 #include "api/moc_conversationmodel.cpp"
diff --git a/src/database.cpp b/src/database.cpp
index 46fb2c0d..78a2973e 100644
--- a/src/database.cpp
+++ b/src/database.cpp
@@ -250,6 +250,23 @@ Database::select(const std::string& select,                            // "id",
     return std::move(result);
 }
 
+int
+Database::count(const std::string& count, // "id", "body", ...
+                const std::string& table, // "tests"
+                const std::string& where) // "contact=:name AND id=:id"
+{
+    QSqlQuery query;
+    std::string columnsSelect;
+    auto prepareStr = std::string("SELECT count(" + count + ") FROM " + table + " WHERE " + where);
+    query.prepare(prepareStr.c_str());
+
+    if (not query.exec())
+        throw QueryError(query);
+
+    query.next();
+    return query.value(0).toInt();
+}
+
 void
 Database::deleteFrom(const std::string& table,                             // "tests"
                      const std::string& where,                             // "contact=:name AND id=:id
diff --git a/src/database.h b/src/database.h
index 3d67ac2c..4b9cf698 100644
--- a/src/database.h
+++ b/src/database.h
@@ -208,6 +208,14 @@ public:
                             const std::string& where,
                             const std::map<std::string, std::string>& bindsWhere);
 
+    /**
+     * Returns the count of an expression.
+     * @param count is the column to count.
+     * @param table where to perfom the action on.
+     * @param where defines the conditional to select.
+     */
+    int count(const std::string& count, const std::string& table, const std::string& where);
+
 private:
     void createTables();
     void storeVersion(const std::string& version);
diff --git a/test/databasetester.cpp b/test/databasetester.cpp
index 8ee0013b..35222a5d 100644
--- a/test/databasetester.cpp
+++ b/test/databasetester.cpp
@@ -220,5 +220,13 @@ DatabaseTester::testDeleteInexistantValue()
     // Should not throw anything if fails
 }
 
+void
+DatabaseTester::testCountUnreadMessages()
+{
+    auto table = "profiles";
+    auto count = database_->count("uri", table, "status='0'");
+    CPPUNIT_ASSERT(count == 1);
+}
+
 } // namespace test
 } // namespace ring
diff --git a/test/databasetester.h b/test/databasetester.h
index dc0ff629..291a3539 100644
--- a/test/databasetester.h
+++ b/test/databasetester.h
@@ -39,6 +39,7 @@ class DatabaseTester : public CppUnit::TestFixture {
 
     CPPUNIT_TEST_SUITE(DatabaseTester);
     CPPUNIT_TEST(testInsertAndSelectCorrectValue);
+    CPPUNIT_TEST(testCountUnreadMessages);
     CPPUNIT_TEST(testInsertIncorrectFail);
     CPPUNIT_TEST(testSelectInexistantValue);
     CPPUNIT_TEST(testUpdateCorrectValue);
@@ -84,6 +85,10 @@ public:
      * Delete inexistant value in the database
      */
     void testDeleteInexistantValue();
+    /**
+     * Count the number of unread messages.
+     */
+    void testCountUnreadMessages();
 
 protected:
     std::unique_ptr<lrc::Database> database_;
-- 
GitLab