summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Cache.h47
-rw-r--r--include/ChatPage.h6
-rw-r--r--include/RoomInfoListItem.h11
-rw-r--r--include/Utils.h31
-rw-r--r--include/timeline/TimelineView.h1
-rw-r--r--include/timeline/TimelineViewManager.h2
6 files changed, 75 insertions, 23 deletions
diff --git a/include/Cache.h b/include/Cache.h
index 3d906f02..5d65c80c 100644
--- a/include/Cache.h
+++ b/include/Cache.h
@@ -19,8 +19,10 @@
 
 #include <boost/optional.hpp>
 
+#include <QDateTime>
 #include <QDir>
 #include <QImage>
+#include <QString>
 
 #include <json.hpp>
 #include <lmdb++.h>
@@ -46,9 +48,24 @@ struct SearchResult
         QString display_name;
 };
 
+inline int
+numeric_key_comparison(const MDB_val *a, const MDB_val *b)
+{
+        auto lhs = std::stoul(std::string((char *)a->mv_data, a->mv_size));
+        auto rhs = std::stoul(std::string((char *)b->mv_data, b->mv_size));
+
+        if (lhs < rhs)
+                return 1;
+        else if (lhs == rhs)
+                return 0;
+
+        return -1;
+}
+
 Q_DECLARE_METATYPE(SearchResult)
 Q_DECLARE_METATYPE(QVector<SearchResult>)
 Q_DECLARE_METATYPE(RoomMember)
+Q_DECLARE_METATYPE(mtx::responses::Timeline)
 
 //! Used to uniquely identify a list of read receipts.
 struct ReadReceiptKey
@@ -70,6 +87,15 @@ from_json(const json &j, ReadReceiptKey &key)
         key.room_id  = j.at("room_id").get<std::string>();
 }
 
+struct DescInfo
+{
+        QString username;
+        QString userid;
+        QString body;
+        QString timestamp;
+        QDateTime datetime;
+};
+
 //! UI info associated with a room.
 struct RoomInfo
 {
@@ -86,6 +112,8 @@ struct RoomInfo
         //! Who can access to the room.
         JoinRule join_rule = JoinRule::Public;
         bool guest_access  = false;
+        //! Metadata describing the last message in the timeline.
+        DescInfo msgInfo;
 };
 
 inline void
@@ -289,6 +317,8 @@ public:
         bool isFormatValid();
         void setCurrentFormat();
 
+        std::map<QString, mtx::responses::Timeline> roomMessages();
+
         //! Retrieve all the user ids from a room.
         std::vector<std::string> roomMembers(const std::string &room_id);
 
@@ -402,6 +432,13 @@ private:
         QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
         QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
 
+        DescInfo getLastMessageInfo(lmdb::txn &txn, const std::string &room_id);
+        void saveTimelineMessages(lmdb::txn &txn,
+                                  const std::string &room_id,
+                                  const mtx::responses::Timeline &res);
+
+        mtx::responses::Timeline getTimelineMessages(lmdb::txn &txn, const std::string &room_id);
+
         //! Remove a room from the cache.
         // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id);
         template<class T>
@@ -500,6 +537,7 @@ private:
                        mpark::holds_alternative<StateEvent<HistoryVisibility>>(e) ||
                        mpark::holds_alternative<StateEvent<JoinRules>>(e) ||
                        mpark::holds_alternative<StateEvent<Name>>(e) ||
+                       mpark::holds_alternative<StateEvent<Member>>(e) ||
                        mpark::holds_alternative<StateEvent<PowerLevels>>(e) ||
                        mpark::holds_alternative<StateEvent<Topic>>(e);
         }
@@ -544,6 +582,15 @@ private:
                 }
         }
 
+        lmdb::dbi getMessagesDb(lmdb::txn &txn, const std::string &room_id)
+        {
+                auto db =
+                  lmdb::dbi::open(txn, std::string(room_id + "/messages").c_str(), MDB_CREATE);
+                lmdb::dbi_set_compare(txn, db, numeric_key_comparison);
+
+                return db;
+        }
+
         lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id)
         {
                 return lmdb::dbi::open(
diff --git a/include/ChatPage.h b/include/ChatPage.h
index ffea2914..a4c6ccc5 100644
--- a/include/ChatPage.h
+++ b/include/ChatPage.h
@@ -108,7 +108,6 @@ signals:
         void showLoginPage(const QString &msg);
         void showUserSettingsPage();
         void showOverlayProgressBar();
-        void startConsesusTimer();
 
         void removeTimelineEvent(const QString &room_id, const QString &event_id);
 
@@ -124,7 +123,7 @@ signals:
 
         void initializeRoomList(QMap<QString, RoomInfo>);
         void initializeViews(const mtx::responses::Rooms &rooms);
-        void initializeEmptyViews(const std::vector<std::string> &rooms);
+        void initializeEmptyViews(const std::map<QString, mtx::responses::Timeline> &msgs);
         void syncUI(const mtx::responses::Rooms &rooms);
         void syncRoomlist(const std::map<QString, RoomInfo> &updates);
         void syncTopBar(const std::map<QString, RoomInfo> &updates);
@@ -206,9 +205,6 @@ private:
         TextInputWidget *text_input_;
         TypingDisplay *typingDisplay_;
 
-        // Safety net if consensus is not possible or too slow.
-        QTimer *showContentTimer_;
-        QTimer *consensusTimer_;
         QTimer connectivityTimer_;
         std::atomic_bool isConnected_;
 
diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h
index aebc2216..95db1d75 100644
--- a/include/RoomInfoListItem.h
+++ b/include/RoomInfoListItem.h
@@ -22,20 +22,11 @@
 #include <QSharedPointer>
 #include <QWidget>
 
+#include "Cache.h"
 #include <mtx/responses.hpp>
 
 class Menu;
 class RippleOverlay;
-struct RoomInfo;
-
-struct DescInfo
-{
-        QString username;
-        QString userid;
-        QString body;
-        QString timestamp;
-        QDateTime datetime;
-};
 
 class RoomInfoListItem : public QWidget
 {
diff --git a/include/Utils.h b/include/Utils.h
index ad8e2073..7db405b1 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -41,14 +41,15 @@ template<class T>
 QString
 messageDescription(const QString &username = "", const QString &body = "")
 {
-        using Audio   = mtx::events::RoomEvent<mtx::events::msg::Audio>;
-        using Emote   = mtx::events::RoomEvent<mtx::events::msg::Emote>;
-        using File    = mtx::events::RoomEvent<mtx::events::msg::File>;
-        using Image   = mtx::events::RoomEvent<mtx::events::msg::Image>;
-        using Notice  = mtx::events::RoomEvent<mtx::events::msg::Notice>;
-        using Sticker = mtx::events::Sticker;
-        using Text    = mtx::events::RoomEvent<mtx::events::msg::Text>;
-        using Video   = mtx::events::RoomEvent<mtx::events::msg::Video>;
+        using Audio     = mtx::events::RoomEvent<mtx::events::msg::Audio>;
+        using Emote     = mtx::events::RoomEvent<mtx::events::msg::Emote>;
+        using File      = mtx::events::RoomEvent<mtx::events::msg::File>;
+        using Image     = mtx::events::RoomEvent<mtx::events::msg::Image>;
+        using Notice    = mtx::events::RoomEvent<mtx::events::msg::Notice>;
+        using Sticker   = mtx::events::Sticker;
+        using Text      = mtx::events::RoomEvent<mtx::events::msg::Text>;
+        using Video     = mtx::events::RoomEvent<mtx::events::msg::Video>;
+        using Encrypted = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
 
         if (std::is_same<T, AudioItem>::value || std::is_same<T, Audio>::value)
                 return QString("sent an audio clip");
@@ -66,6 +67,8 @@ messageDescription(const QString &username = "", const QString &body = "")
                 return QString(": %1").arg(body);
         else if (std::is_same<T, Emote>::value)
                 return QString("* %1 %2").arg(username).arg(body);
+        else if (std::is_same<T, Encrypted>::value)
+                return QString("sent an encrypted message");
 }
 
 template<class T, class Event>
@@ -135,6 +138,18 @@ erase_if(ContainerT &items, const PredicateT &predicate)
         }
 }
 
+inline uint64_t
+event_timestamp(const mtx::events::collections::TimelineEvents &event)
+{
+        return mpark::visit([](auto msg) { return msg.origin_server_ts; }, event);
+}
+
+inline nlohmann::json
+serialize_event(const mtx::events::collections::TimelineEvents &event)
+{
+        return mpark::visit([](auto msg) { return json(msg); }, event);
+}
+
 inline mtx::events::EventType
 event_type(const mtx::events::collections::TimelineEvents &event)
 {
diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h
index bbe1dcad..7f1912ea 100644
--- a/include/timeline/TimelineView.h
+++ b/include/timeline/TimelineView.h
@@ -158,6 +158,7 @@ public:
 
         //! Remove an item from the timeline with the given Event ID.
         void removeEvent(const QString &event_id);
+        void setPrevBatchToken(const QString &token) { prev_batch_token_ = token; }
 
 public slots:
         void sliderRangeChanged(int min, int max);
diff --git a/include/timeline/TimelineViewManager.h b/include/timeline/TimelineViewManager.h
index 9e31ecbf..590adb2b 100644
--- a/include/timeline/TimelineViewManager.h
+++ b/include/timeline/TimelineViewManager.h
@@ -27,6 +27,7 @@ class QFile;
 class RoomInfoListItem;
 class TimelineView;
 struct DescInfo;
+struct SavedMessages;
 
 class TimelineViewManager : public QStackedWidget
 {
@@ -57,6 +58,7 @@ signals:
 
 public slots:
         void removeTimelineEvent(const QString &room_id, const QString &event_id);
+        void initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs);
 
         void setHistoryView(const QString &room_id);
         void queueTextMessage(const QString &msg);