summary refs log tree commit diff
path: root/src/Cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cache.cc')
-rw-r--r--src/Cache.cc121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/Cache.cc b/src/Cache.cc

index ed4194ec..a276f554 100644 --- a/src/Cache.cc +++ b/src/Cache.cc
@@ -21,8 +21,10 @@ #include <QByteArray> #include <QFile> #include <QHash> +#include <QSettings> #include <QStandardPaths> +#include <mtx/responses/common.hpp> #include <variant.hpp> #include "Cache.h" @@ -38,6 +40,8 @@ static const lmdb::val NEXT_BATCH_KEY("next_batch"); static const lmdb::val OLM_ACCOUNT_KEY("olm_account"); static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); +constexpr size_t MAX_RESTORED_MESSAGES = 30; + //! Cache databases and their format. //! //! Contains UI information for the joined rooms. (i.e name, topic, avatar url etc). @@ -85,6 +89,7 @@ init(const QString &user_id) qRegisterMetaType<RoomInfo>(); qRegisterMetaType<QMap<QString, RoomInfo>>(); qRegisterMetaType<std::map<QString, RoomInfo>>(); + qRegisterMetaType<std::map<QString, mtx::responses::Timeline>>(); instance_ = std::make_unique<Cache>(user_id); } @@ -744,6 +749,8 @@ Cache::saveState(const mtx::responses::Sync &res) saveStateEvents(txn, statesdb, membersdb, room.first, room.second.state.events); saveStateEvents(txn, statesdb, membersdb, room.first, room.second.timeline.events); + saveTimelineMessages(txn, room.first, room.second.timeline); + RoomInfo updatedInfo; updatedInfo.name = getRoomName(txn, statesdb, membersdb).toStdString(); updatedInfo.topic = getRoomTopic(txn, statesdb).toStdString(); @@ -944,6 +951,57 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms) return room_info; } +std::map<QString, mtx::responses::Timeline> +Cache::roomMessages() +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + + std::map<QString, mtx::responses::Timeline> msgs; + std::string room_id, unused; + + auto roomsCursor = lmdb::cursor::open(txn, roomsDb_); + while (roomsCursor.get(room_id, unused, MDB_NEXT)) + msgs.emplace(QString::fromStdString(room_id), getTimelineMessages(txn, room_id)); + + roomsCursor.close(); + txn.commit(); + + return msgs; +} + +mtx::responses::Timeline +Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id) +{ + auto db = getMessagesDb(txn, room_id); + + mtx::responses::Timeline timeline; + std::string timestamp, msg; + + auto cursor = lmdb::cursor::open(txn, db); + + size_t index = 0; + + while (cursor.get(timestamp, msg, MDB_NEXT) && index < MAX_RESTORED_MESSAGES) { + auto obj = json::parse(msg); + + if (obj.count("event") == 0 || obj.count("token") == 0) + continue; + + mtx::events::collections::TimelineEvents event; + mtx::events::collections::from_json(obj.at("event"), event); + + index += 1; + + timeline.events.push_back(event); + timeline.prev_batch = obj.at("token").get<std::string>(); + } + cursor.close(); + + std::reverse(timeline.events.begin(), timeline.events.end()); + + return timeline; +} + QMap<QString, RoomInfo> Cache::roomInfo(bool withInvites) { @@ -959,6 +1017,8 @@ Cache::roomInfo(bool withInvites) while (roomsCursor.get(room_id, room_data, MDB_NEXT)) { RoomInfo tmp = json::parse(std::move(room_data)); tmp.member_count = getMembersDb(txn, room_id).size(txn); + tmp.msgInfo = getLastMessageInfo(txn, room_id); + result.insert(QString::fromStdString(std::move(room_id)), std::move(tmp)); } roomsCursor.close(); @@ -979,6 +1039,38 @@ Cache::roomInfo(bool withInvites) return result; } +DescInfo +Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id) +{ + auto db = getMessagesDb(txn, room_id); + + if (db.size(txn) == 0) + return DescInfo{}; + + std::string timestamp, msg; + + QSettings settings; + auto local_user = settings.value("auth/user_id").toString(); + + auto cursor = lmdb::cursor::open(txn, db); + while (cursor.get(timestamp, msg, MDB_NEXT)) { + auto obj = json::parse(msg); + + if (obj.count("event") == 0) + continue; + + mtx::events::collections::TimelineEvents event; + mtx::events::collections::from_json(obj.at("event"), event); + + cursor.close(); + return utils::getMessageDescription( + event, local_user, QString::fromStdString(room_id)); + } + cursor.close(); + + return DescInfo{}; +} + std::map<QString, bool> Cache::invites() { @@ -1513,6 +1605,35 @@ Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_ } void +Cache::saveTimelineMessages(lmdb::txn &txn, + const std::string &room_id, + const mtx::responses::Timeline &res) +{ + auto db = getMessagesDb(txn, room_id); + + using namespace mtx::events; + using namespace mtx::events::state; + + for (const auto &e : res.events) { + if (isStateEvent(e)) + continue; + + if (mpark::holds_alternative<RedactionEvent<msg::Redaction>>(e)) + continue; + + json obj = json::object(); + + obj["event"] = utils::serialize_event(e); + obj["token"] = res.prev_batch; + + lmdb::dbi_put(txn, + db, + lmdb::val(std::to_string(utils::event_timestamp(e))), + lmdb::val(obj.dump())); + } +} + +void Cache::markSentNotification(const std::string &event_id) { auto txn = lmdb::txn::begin(env_);