summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2022-11-03 23:26:59 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2022-11-03 23:26:59 +0100
commit76347f1c6f3aa41654fb989d1726d7ce4b56795e (patch)
treebecfd58880d00bb18fafcb30422fa1e2494184ce /src
parentMake the higlight ring a bit less in your face (diff)
downloadnheko-76347f1c6f3aa41654fb989d1726d7ce4b56795e.tar.xz
Continue fetching past messages when searching
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp98
-rw-r--r--src/timeline/EventStore.cpp11
-rw-r--r--src/timeline/TimelineFilter.cpp32
-rw-r--r--src/timeline/TimelineFilter.h4
-rw-r--r--src/timeline/TimelineModel.cpp1
-rw-r--r--src/timeline/TimelineModel.h2
6 files changed, 94 insertions, 54 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 3426ccfe..b577f201 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -1013,20 +1013,22 @@ Cache::getOlmSessions(const std::string &curve25519)
 {
     using namespace mtx::crypto;
 
-    auto txn = lmdb::txn::begin(env_);
-    auto db  = getOlmSessionsDb(txn, curve25519);
-
-    std::string_view session_id, unused;
-    std::vector<std::string> res;
+    try {
+        auto txn = ro_txn(env_);
+        auto db  = getOlmSessionsDb(txn, curve25519);
 
-    auto cursor = lmdb::cursor::open(txn, db);
-    while (cursor.get(session_id, unused, MDB_NEXT))
-        res.emplace_back(session_id);
-    cursor.close();
+        std::string_view session_id, unused;
+        std::vector<std::string> res;
 
-    txn.commit();
+        auto cursor = lmdb::cursor::open(txn, db);
+        while (cursor.get(session_id, unused, MDB_NEXT))
+            res.emplace_back(session_id);
+        cursor.close();
 
-    return res;
+        return res;
+    } catch (...) {
+        return {};
+    }
 }
 
 void
@@ -2173,18 +2175,22 @@ Cache::roomIds()
 std::string
 Cache::previousBatchToken(const std::string &room_id)
 {
-    auto txn     = lmdb::txn::begin(env_, nullptr);
-    auto orderDb = getEventOrderDb(txn, room_id);
+    auto txn = ro_txn(env_);
+    try {
+        auto orderDb = getEventOrderDb(txn, room_id);
 
-    auto cursor = lmdb::cursor::open(txn, orderDb);
-    std::string_view indexVal, val;
-    if (!cursor.get(indexVal, val, MDB_FIRST)) {
-        return "";
-    }
+        auto cursor = lmdb::cursor::open(txn, orderDb);
+        std::string_view indexVal, val;
+        if (!cursor.get(indexVal, val, MDB_FIRST)) {
+            return "";
+        }
 
-    auto j = nlohmann::json::parse(val);
+        auto j = nlohmann::json::parse(val);
 
-    return j.value("prev_batch", "");
+        return j.value("prev_batch", "");
+    } catch (...) {
+        return "";
+    }
 }
 
 Cache::Messages
@@ -3206,10 +3212,10 @@ Cache::pendingEvents(const std::string &room_id)
 std::optional<mtx::events::collections::TimelineEvent>
 Cache::firstPendingMessage(const std::string &room_id)
 {
-    auto txn     = lmdb::txn::begin(env_);
+    auto txn     = ro_txn(env_);
     auto pending = getPendingMessagesDb(txn, room_id);
 
-    {
+    try {
         auto pendingCursor = lmdb::cursor::open(txn, pending);
         std::string_view tsIgnored, pendingTxn;
         while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
@@ -3225,7 +3231,6 @@ Cache::firstPendingMessage(const std::string &room_id)
                 from_json(nlohmann::json::parse(event), te);
 
                 pendingCursor.close();
-                txn.commit();
                 return te;
             } catch (std::exception &e) {
                 nhlog::db()->error("Failed to parse message from cache {}", e.what());
@@ -3233,10 +3238,8 @@ Cache::firstPendingMessage(const std::string &room_id)
                 continue;
             }
         }
+    } catch (const lmdb::error &e) {
     }
-
-    txn.commit();
-
     return std::nullopt;
 }
 
@@ -3998,33 +4001,36 @@ Cache::hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes
     using namespace mtx::events;
     using namespace mtx::events::state;
 
-    auto txn = lmdb::txn::begin(env_);
-    auto db  = getStatesDb(txn, room_id);
+    auto txn = ro_txn(env_);
+    try {
+        auto db = getStatesDb(txn, room_id);
 
-    int64_t min_event_level = std::numeric_limits<int64_t>::max();
-    int64_t user_level      = std::numeric_limits<int64_t>::min();
+        int64_t min_event_level = std::numeric_limits<int64_t>::max();
+        int64_t user_level      = std::numeric_limits<int64_t>::min();
 
-    std::string_view event;
-    bool res = db.get(txn, to_string(EventType::RoomPowerLevels), event);
+        std::string_view event;
+        bool res = db.get(txn, to_string(EventType::RoomPowerLevels), event);
 
-    if (res) {
-        try {
-            StateEvent<PowerLevels> msg =
-              nlohmann::json::parse(std::string_view(event.data(), event.size()))
-                .get<StateEvent<PowerLevels>>();
+        if (res) {
+            try {
+                StateEvent<PowerLevels> msg =
+                  nlohmann::json::parse(std::string_view(event.data(), event.size()))
+                    .get<StateEvent<PowerLevels>>();
 
-            user_level = msg.content.user_level(user_id);
+                user_level = msg.content.user_level(user_id);
 
-            for (const auto &ty : eventTypes)
-                min_event_level = std::min(min_event_level, msg.content.state_level(to_string(ty)));
-        } catch (const nlohmann::json::exception &e) {
-            nhlog::db()->warn("failed to parse m.room.power_levels event: {}", e.what());
+                for (const auto &ty : eventTypes)
+                    min_event_level =
+                      std::min(min_event_level, msg.content.state_level(to_string(ty)));
+            } catch (const nlohmann::json::exception &e) {
+                nhlog::db()->warn("failed to parse m.room.power_levels event: {}", e.what());
+            }
         }
-    }
-
-    txn.commit();
 
-    return user_level >= min_event_level;
+        return user_level >= min_event_level;
+    } catch (...) {
+        return false;
+    }
 }
 
 std::vector<std::string>
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index de813196..65efc0b4 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -80,8 +80,8 @@ EventStore::EventStore(std::string room_id, QObject *)
                   emit beginInsertRows(toExternalIdx(newFirst), toExternalIdx(this->first - 1));
                   this->first = newFirst;
                   emit endInsertRows();
-                  emit fetchedMore();
                   emit dataChanged(toExternalIdx(oldFirst), toExternalIdx(oldFirst));
+                  emit fetchedMore();
               } else {
                   auto range = cache::client()->getTimelineRange(room_id_);
 
@@ -725,10 +725,11 @@ EventStore::decryptEvent(const IdIndex &idx,
         case olm::DecryptionErrorCode::ParsingFailed:
             break;
         case olm::DecryptionErrorCode::ReplayAttack:
-            nhlog::crypto()->critical("Reply attack while decryptiong event {} in room {} from {}!",
-                                      e.event_id,
-                                      room_id_,
-                                      e.sender);
+            nhlog::crypto()->critical(
+              "Replay attack while decryptiong event {} in room {} from {}!",
+              e.event_id,
+              room_id_,
+              e.sender);
             break;
         case olm::DecryptionErrorCode::NoError:
             // unreachable
diff --git a/src/timeline/TimelineFilter.cpp b/src/timeline/TimelineFilter.cpp
index 15d2590c..cd17a7f6 100644
--- a/src/timeline/TimelineFilter.cpp
+++ b/src/timeline/TimelineFilter.cpp
@@ -19,8 +19,10 @@ TimelineFilter::setThreadId(const QString &t)
     if (this->threadId != t) {
         this->threadId = t;
         invalidateFilter();
+
+        fetchMore({});
+        emit threadIdChanged();
     }
-    emit threadIdChanged();
 }
 
 void
@@ -30,21 +32,45 @@ TimelineFilter::setContentFilter(const QString &c)
     if (this->contentFilter != c) {
         this->contentFilter = c;
         invalidateFilter();
+
+        fetchMore({});
+        emit contentFilterChanged();
+    }
+}
+
+void
+TimelineFilter::fetchAgain()
+{
+    if (threadId.isEmpty() && contentFilter.isEmpty())
+        return;
+
+    if (auto s = source()) {
+        if (rowCount() == cachedCount && s->canFetchMore(QModelIndex()))
+            s->fetchMore(QModelIndex());
+        else
+            cachedCount = rowCount();
     }
-    emit contentFilterChanged();
 }
 
 void
 TimelineFilter::setSource(TimelineModel *s)
 {
     if (auto orig = this->source(); orig != s) {
-        if (orig)
+        cachedCount = 0;
+
+        if (orig) {
             disconnect(orig,
                        &TimelineModel::currentIndexChanged,
                        this,
                        &TimelineFilter::currentIndexChanged);
+            disconnect(orig, &TimelineModel::fetchedMore, this, &TimelineFilter::fetchAgain);
+        }
+
         this->setSourceModel(s);
+
         connect(s, &TimelineModel::currentIndexChanged, this, &TimelineFilter::currentIndexChanged);
+        connect(s, &TimelineModel::fetchedMore, this, &TimelineFilter::fetchAgain);
+
         emit sourceChanged();
         invalidateFilter();
     }
diff --git a/src/timeline/TimelineFilter.h b/src/timeline/TimelineFilter.h
index 3b04650e..a602f84f 100644
--- a/src/timeline/TimelineFilter.h
+++ b/src/timeline/TimelineFilter.h
@@ -45,9 +45,13 @@ signals:
     void sourceChanged();
     void currentIndexChanged();
 
+private slots:
+    void fetchAgain();
+
 protected:
     bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
 
 private:
     QString threadId, contentFilter;
+    int cachedCount = 0;
 };
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index b20e36bc..6b764081 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -449,6 +449,7 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
     connect(&events, &EventStore::fetchedMore, this, [this]() {
         setPaginationInProgress(false);
         updateLastMessage();
+        emit fetchedMore();
     });
     connect(&events, &EventStore::fetchedMore, this, &TimelineModel::checkAfterFetch);
     connect(&events,
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 9cd60e5d..9daeeb3a 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -465,6 +465,8 @@ signals:
 
     void scrollTargetChanged();
 
+    void fetchedMore();
+
 private:
     template<typename T>
     void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType);