mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Reduce overhead of Cache.h
This commit is contained in:
parent
7d6a015f36
commit
5fc1f3bd67
28 changed files with 1404 additions and 644 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -40,6 +40,7 @@ moc_*.cpp
|
||||||
qrc_*.cpp
|
qrc_*.cpp
|
||||||
ui_*.h
|
ui_*.h
|
||||||
*-build-*
|
*-build-*
|
||||||
|
/.clangd/
|
||||||
|
|
||||||
# QtCreator
|
# QtCreator
|
||||||
|
|
||||||
|
|
|
@ -357,7 +357,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/notifications/Manager.h
|
src/notifications/Manager.h
|
||||||
|
|
||||||
src/AvatarProvider.h
|
src/AvatarProvider.h
|
||||||
src/Cache.h
|
src/Cache_p.h
|
||||||
src/ChatPage.h
|
src/ChatPage.h
|
||||||
src/CommunitiesListItem.h
|
src/CommunitiesListItem.h
|
||||||
src/CommunitiesList.h
|
src/CommunitiesList.h
|
||||||
|
|
|
@ -35,9 +35,6 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca
|
||||||
|
|
||||||
const auto cacheKey = avatarUrl + "_size_" + size;
|
const auto cacheKey = avatarUrl + "_size_" + size;
|
||||||
|
|
||||||
if (!cache::client())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (avatarUrl.isEmpty())
|
if (avatarUrl.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -47,7 +44,7 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = cache::client()->image(avatarUrl);
|
auto data = cache::image(avatarUrl);
|
||||||
if (!data.isNull()) {
|
if (!data.isNull()) {
|
||||||
pixmap.loadFromData(data);
|
pixmap.loadFromData(data);
|
||||||
avatar_cache.insert(cacheKey, pixmap);
|
avatar_cache.insert(cacheKey, pixmap);
|
||||||
|
@ -82,7 +79,7 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache::client()->saveImage(opts.mxc_url, res);
|
cache::saveImage(opts.mxc_url, res);
|
||||||
|
|
||||||
emit proxy->avatarDownloaded(QByteArray(res.data(), res.size()));
|
emit proxy->avatarDownloaded(QByteArray(res.data(), res.size()));
|
||||||
});
|
});
|
||||||
|
@ -95,12 +92,7 @@ resolve(const QString &room_id,
|
||||||
QObject *receiver,
|
QObject *receiver,
|
||||||
AvatarCallback callback)
|
AvatarCallback callback)
|
||||||
{
|
{
|
||||||
const auto key = QString("%1 %2").arg(room_id).arg(user_id);
|
const auto avatarUrl = cache::avatarUrl(room_id, user_id);
|
||||||
const auto avatarUrl = Cache::avatarUrl(room_id, user_id);
|
|
||||||
const auto cacheKey = avatarUrl + "_size_" + size;
|
|
||||||
|
|
||||||
if (!Cache::AvatarUrls.contains(key) || !cache::client())
|
|
||||||
return;
|
|
||||||
|
|
||||||
resolve(avatarUrl, size, receiver, callback);
|
resolve(avatarUrl, size, receiver, callback);
|
||||||
}
|
}
|
||||||
|
|
561
src/Cache.cpp
561
src/Cache.cpp
|
@ -30,6 +30,7 @@
|
||||||
#include <mtx/responses/common.hpp>
|
#include <mtx/responses/common.hpp>
|
||||||
|
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
#include "Cache_p.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
//! Should be changed when a breaking change occurs in the cache format.
|
//! Should be changed when a breaking change occurs in the cache format.
|
||||||
|
@ -89,29 +90,20 @@ namespace {
|
||||||
std::unique_ptr<Cache> instance_ = nullptr;
|
std::unique_ptr<Cache> instance_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace cache {
|
int
|
||||||
void
|
numeric_key_comparison(const MDB_val *a, const MDB_val *b)
|
||||||
init(const QString &user_id)
|
|
||||||
{
|
{
|
||||||
qRegisterMetaType<SearchResult>();
|
auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size));
|
||||||
qRegisterMetaType<QVector<SearchResult>>();
|
auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size));
|
||||||
qRegisterMetaType<RoomMember>();
|
|
||||||
qRegisterMetaType<RoomSearchResult>();
|
|
||||||
qRegisterMetaType<RoomInfo>();
|
|
||||||
qRegisterMetaType<QMap<QString, RoomInfo>>();
|
|
||||||
qRegisterMetaType<QMap<QString, mtx::responses::Notifications>>();
|
|
||||||
qRegisterMetaType<std::map<QString, RoomInfo>>();
|
|
||||||
qRegisterMetaType<std::map<QString, mtx::responses::Timeline>>();
|
|
||||||
|
|
||||||
instance_ = std::make_unique<Cache>(user_id);
|
if (lhs < rhs)
|
||||||
|
return 1;
|
||||||
|
else if (lhs == rhs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache *
|
|
||||||
client()
|
|
||||||
{
|
|
||||||
return instance_.get();
|
|
||||||
}
|
|
||||||
} // namespace cache
|
|
||||||
|
|
||||||
Cache::Cache(const QString &userId, QObject *parent)
|
Cache::Cache(const QString &userId, QObject *parent)
|
||||||
: QObject{parent}
|
: QObject{parent}
|
||||||
|
@ -2321,20 +2313,6 @@ from_json(const json &j, RoomInfo &info)
|
||||||
info.tags = j.at("tags").get<std::vector<std::string>>();
|
info.tags = j.at("tags").get<std::vector<std::string>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
numeric_key_comparison(const MDB_val *a, const MDB_val *b)
|
|
||||||
{
|
|
||||||
auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size));
|
|
||||||
auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size));
|
|
||||||
|
|
||||||
if (lhs < rhs)
|
|
||||||
return 1;
|
|
||||||
else if (lhs == rhs)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
to_json(json &j, const ReadReceiptKey &key)
|
to_json(json &j, const ReadReceiptKey &key)
|
||||||
{
|
{
|
||||||
|
@ -2407,3 +2385,520 @@ from_json(const nlohmann::json &obj, MegolmSessionIndex &msg)
|
||||||
msg.session_id = obj.at("session_id");
|
msg.session_id = obj.at("session_id");
|
||||||
msg.sender_key = obj.at("sender_key");
|
msg.sender_key = obj.at("sender_key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace cache {
|
||||||
|
void
|
||||||
|
init(const QString &user_id)
|
||||||
|
{
|
||||||
|
qRegisterMetaType<SearchResult>();
|
||||||
|
qRegisterMetaType<QVector<SearchResult>>();
|
||||||
|
qRegisterMetaType<RoomMember>();
|
||||||
|
qRegisterMetaType<RoomSearchResult>();
|
||||||
|
qRegisterMetaType<RoomInfo>();
|
||||||
|
qRegisterMetaType<QMap<QString, RoomInfo>>();
|
||||||
|
qRegisterMetaType<QMap<QString, mtx::responses::Notifications>>();
|
||||||
|
qRegisterMetaType<std::map<QString, RoomInfo>>();
|
||||||
|
qRegisterMetaType<std::map<QString, mtx::responses::Timeline>>();
|
||||||
|
|
||||||
|
instance_ = std::make_unique<Cache>(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache *
|
||||||
|
client()
|
||||||
|
{
|
||||||
|
return instance_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
displayName(const std::string &room_id, const std::string &user_id)
|
||||||
|
{
|
||||||
|
return instance_->displayName(room_id, user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
displayName(const QString &room_id, const QString &user_id)
|
||||||
|
{
|
||||||
|
return instance_->displayName(room_id, user_id);
|
||||||
|
}
|
||||||
|
QString
|
||||||
|
avatarUrl(const QString &room_id, const QString &user_id)
|
||||||
|
{
|
||||||
|
return instance_->avatarUrl(room_id, user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
userColor(const QString &user_id)
|
||||||
|
{
|
||||||
|
return instance_->userColor(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removeDisplayName(const QString &room_id, const QString &user_id)
|
||||||
|
{
|
||||||
|
instance_->removeDisplayName(room_id, user_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeAvatarUrl(const QString &room_id, const QString &user_id)
|
||||||
|
{
|
||||||
|
instance_->removeAvatarUrl(room_id, user_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeUserColor(const QString &user_id)
|
||||||
|
{
|
||||||
|
instance_->removeUserColor(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
insertDisplayName(const QString &room_id, const QString &user_id, const QString &display_name)
|
||||||
|
{
|
||||||
|
instance_->insertDisplayName(room_id, user_id, display_name);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url)
|
||||||
|
{
|
||||||
|
instance_->insertAvatarUrl(room_id, user_id, avatar_url);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
insertUserColor(const QString &user_id, const QString &color_name)
|
||||||
|
{
|
||||||
|
instance_->insertUserColor(user_id, color_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clearUserColors()
|
||||||
|
{
|
||||||
|
instance_->clearUserColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Load saved data for the display names & avatars.
|
||||||
|
void
|
||||||
|
populateMembers()
|
||||||
|
{
|
||||||
|
instance_->populateMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
joinedRooms()
|
||||||
|
{
|
||||||
|
return instance_->joinedRooms();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, RoomInfo>
|
||||||
|
roomInfo(bool withInvites)
|
||||||
|
{
|
||||||
|
return instance_->roomInfo(withInvites);
|
||||||
|
}
|
||||||
|
std::map<QString, bool>
|
||||||
|
invites()
|
||||||
|
{
|
||||||
|
return instance_->invites();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
|
||||||
|
{
|
||||||
|
return instance_->getRoomName(txn, statesdb, membersdb);
|
||||||
|
}
|
||||||
|
mtx::events::state::JoinRule
|
||||||
|
getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
|
||||||
|
{
|
||||||
|
return instance_->getRoomJoinRule(txn, statesdb);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb)
|
||||||
|
{
|
||||||
|
return instance_->getRoomGuestAccess(txn, statesdb);
|
||||||
|
}
|
||||||
|
QString
|
||||||
|
getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb)
|
||||||
|
{
|
||||||
|
return instance_->getRoomTopic(txn, statesdb);
|
||||||
|
}
|
||||||
|
QString
|
||||||
|
getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb, const QString &room_id)
|
||||||
|
{
|
||||||
|
return instance_->getRoomAvatarUrl(txn, statesdb, membersdb, room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb)
|
||||||
|
{
|
||||||
|
return instance_->getRoomVersion(txn, statesdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<RoomMember>
|
||||||
|
getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
|
||||||
|
{
|
||||||
|
return instance_->getMembers(room_id, startIndex, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
saveState(const mtx::responses::Sync &res)
|
||||||
|
{
|
||||||
|
instance_->saveState(res);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
isInitialized()
|
||||||
|
{
|
||||||
|
return instance_->isInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
nextBatchToken()
|
||||||
|
{
|
||||||
|
return instance_->nextBatchToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
deleteData()
|
||||||
|
{
|
||||||
|
instance_->deleteData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removeInvite(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
instance_->removeInvite(txn, room_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeInvite(const std::string &room_id)
|
||||||
|
{
|
||||||
|
instance_->removeInvite(room_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeRoom(lmdb::txn &txn, const std::string &roomid)
|
||||||
|
{
|
||||||
|
instance_->removeRoom(txn, roomid);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeRoom(const std::string &roomid)
|
||||||
|
{
|
||||||
|
instance_->removeRoom(roomid);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removeRoom(const QString &roomid)
|
||||||
|
{
|
||||||
|
instance_->removeRoom(roomid.toStdString());
|
||||||
|
}
|
||||||
|
void
|
||||||
|
setup()
|
||||||
|
{
|
||||||
|
instance_->setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isFormatValid()
|
||||||
|
{
|
||||||
|
return instance_->isFormatValid();
|
||||||
|
}
|
||||||
|
void
|
||||||
|
setCurrentFormat()
|
||||||
|
{
|
||||||
|
instance_->setCurrentFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, mtx::responses::Timeline>
|
||||||
|
roomMessages()
|
||||||
|
{
|
||||||
|
return instance_->roomMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, mtx::responses::Notifications>
|
||||||
|
getTimelineMentions()
|
||||||
|
{
|
||||||
|
return instance_->getTimelineMentions();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Retrieve all the user ids from a room.
|
||||||
|
std::vector<std::string>
|
||||||
|
roomMembers(const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->roomMembers(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Check if the given user has power leve greater than than
|
||||||
|
//! lowest power level of the given events.
|
||||||
|
bool
|
||||||
|
hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
|
||||||
|
const std::string &room_id,
|
||||||
|
const std::string &user_id)
|
||||||
|
{
|
||||||
|
return instance_->hasEnoughPowerLevel(eventTypes, room_id, user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Retrieves the saved room avatar.
|
||||||
|
QImage
|
||||||
|
getRoomAvatar(const QString &id)
|
||||||
|
{
|
||||||
|
return instance_->getRoomAvatar(id);
|
||||||
|
}
|
||||||
|
QImage
|
||||||
|
getRoomAvatar(const std::string &id)
|
||||||
|
{
|
||||||
|
return instance_->getRoomAvatar(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts)
|
||||||
|
{
|
||||||
|
instance_->updateReadReceipt(txn, room_id, receipts);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserReceipts
|
||||||
|
readReceipts(const QString &event_id, const QString &room_id)
|
||||||
|
{
|
||||||
|
return instance_->readReceipts(event_id, room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Filter the events that have at least one read receipt.
|
||||||
|
std::vector<QString>
|
||||||
|
filterReadEvents(const QString &room_id,
|
||||||
|
const std::vector<QString> &event_ids,
|
||||||
|
const std::string &excluded_user)
|
||||||
|
{
|
||||||
|
return instance_->filterReadEvents(room_id, event_ids, excluded_user);
|
||||||
|
}
|
||||||
|
//! Add event for which we are expecting some read receipts.
|
||||||
|
void
|
||||||
|
addPendingReceipt(const QString &room_id, const QString &event_id)
|
||||||
|
{
|
||||||
|
instance_->addPendingReceipt(room_id, event_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
removePendingReceipt(lmdb::txn &txn, const std::string &room_id, const std::string &event_id)
|
||||||
|
{
|
||||||
|
instance_->removePendingReceipt(txn, room_id, event_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
notifyForReadReceipts(const std::string &room_id)
|
||||||
|
{
|
||||||
|
instance_->notifyForReadReceipts(room_id);
|
||||||
|
}
|
||||||
|
std::vector<QString>
|
||||||
|
pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->pendingReceiptsEvents(txn, room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray
|
||||||
|
image(const QString &url)
|
||||||
|
{
|
||||||
|
return instance_->image(url);
|
||||||
|
}
|
||||||
|
QByteArray
|
||||||
|
image(lmdb::txn &txn, const std::string &url)
|
||||||
|
{
|
||||||
|
return instance_->image(txn, url);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
saveImage(const std::string &url, const std::string &data)
|
||||||
|
{
|
||||||
|
instance_->saveImage(url, data);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
saveImage(const QString &url, const QByteArray &data)
|
||||||
|
{
|
||||||
|
instance_->saveImage(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomInfo
|
||||||
|
singleRoomInfo(const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->singleRoomInfo(room_id);
|
||||||
|
}
|
||||||
|
std::vector<std::string>
|
||||||
|
roomsWithStateUpdates(const mtx::responses::Sync &res)
|
||||||
|
{
|
||||||
|
return instance_->roomsWithStateUpdates(res);
|
||||||
|
}
|
||||||
|
std::vector<std::string>
|
||||||
|
roomsWithTagUpdates(const mtx::responses::Sync &res)
|
||||||
|
{
|
||||||
|
return instance_->roomsWithTagUpdates(res);
|
||||||
|
}
|
||||||
|
std::map<QString, RoomInfo>
|
||||||
|
getRoomInfo(const std::vector<std::string> &rooms)
|
||||||
|
{
|
||||||
|
return instance_->getRoomInfo(rooms);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Calculates which the read status of a room.
|
||||||
|
//! Whether all the events in the timeline have been read.
|
||||||
|
bool
|
||||||
|
calculateRoomReadStatus(const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->calculateRoomReadStatus(room_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
calculateRoomReadStatus()
|
||||||
|
{
|
||||||
|
instance_->calculateRoomReadStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<SearchResult>
|
||||||
|
searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items)
|
||||||
|
{
|
||||||
|
return instance_->searchUsers(room_id, query, max_items);
|
||||||
|
}
|
||||||
|
std::vector<RoomSearchResult>
|
||||||
|
searchRooms(const std::string &query, std::uint8_t max_items)
|
||||||
|
{
|
||||||
|
return instance_->searchRooms(query, max_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
markSentNotification(const std::string &event_id)
|
||||||
|
{
|
||||||
|
instance_->markSentNotification(event_id);
|
||||||
|
}
|
||||||
|
//! Removes an event from the sent notifications.
|
||||||
|
void
|
||||||
|
removeReadNotification(const std::string &event_id)
|
||||||
|
{
|
||||||
|
instance_->removeReadNotification(event_id);
|
||||||
|
}
|
||||||
|
//! Check if we have sent a desktop notification for the given event id.
|
||||||
|
bool
|
||||||
|
isNotificationSent(const std::string &event_id)
|
||||||
|
{
|
||||||
|
return instance_->isNotificationSent(event_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Add all notifications containing a user mention to the db.
|
||||||
|
void
|
||||||
|
saveTimelineMentions(const mtx::responses::Notifications &res)
|
||||||
|
{
|
||||||
|
instance_->saveTimelineMentions(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Remove old unused data.
|
||||||
|
void
|
||||||
|
deleteOldMessages()
|
||||||
|
{
|
||||||
|
instance_->deleteOldMessages();
|
||||||
|
}
|
||||||
|
void
|
||||||
|
deleteOldData() noexcept
|
||||||
|
{
|
||||||
|
instance_->deleteOldData();
|
||||||
|
}
|
||||||
|
//! Retrieve all saved room ids.
|
||||||
|
std::vector<std::string>
|
||||||
|
getRoomIds(lmdb::txn &txn)
|
||||||
|
{
|
||||||
|
return instance_->getRoomIds(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Mark a room that uses e2e encryption.
|
||||||
|
void
|
||||||
|
setEncryptedRoom(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
instance_->setEncryptedRoom(txn, room_id);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
isRoomEncrypted(const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->isRoomEncrypted(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Check if a user is a member of the room.
|
||||||
|
bool
|
||||||
|
isRoomMember(const std::string &user_id, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->isRoomMember(user_id, room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Outbound Megolm Sessions
|
||||||
|
//
|
||||||
|
void
|
||||||
|
saveOutboundMegolmSession(const std::string &room_id,
|
||||||
|
const OutboundGroupSessionData &data,
|
||||||
|
mtx::crypto::OutboundGroupSessionPtr session)
|
||||||
|
{
|
||||||
|
instance_->saveOutboundMegolmSession(room_id, data, std::move(session));
|
||||||
|
}
|
||||||
|
OutboundGroupSessionDataRef
|
||||||
|
getOutboundMegolmSession(const std::string &room_id)
|
||||||
|
{
|
||||||
|
return instance_->getOutboundMegolmSession(room_id);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
outboundMegolmSessionExists(const std::string &room_id) noexcept
|
||||||
|
{
|
||||||
|
return instance_->outboundMegolmSessionExists(room_id);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
updateOutboundMegolmSession(const std::string &room_id, int message_index)
|
||||||
|
{
|
||||||
|
instance_->updateOutboundMegolmSession(room_id, message_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys)
|
||||||
|
{
|
||||||
|
instance_->importSessionKeys(keys);
|
||||||
|
}
|
||||||
|
mtx::crypto::ExportedSessionKeys
|
||||||
|
exportSessionKeys()
|
||||||
|
{
|
||||||
|
return instance_->exportSessionKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inbound Megolm Sessions
|
||||||
|
//
|
||||||
|
void
|
||||||
|
saveInboundMegolmSession(const MegolmSessionIndex &index,
|
||||||
|
mtx::crypto::InboundGroupSessionPtr session)
|
||||||
|
{
|
||||||
|
instance_->saveInboundMegolmSession(index, std::move(session));
|
||||||
|
}
|
||||||
|
OlmInboundGroupSession *
|
||||||
|
getInboundMegolmSession(const MegolmSessionIndex &index)
|
||||||
|
{
|
||||||
|
return instance_->getInboundMegolmSession(index);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
inboundMegolmSessionExists(const MegolmSessionIndex &index)
|
||||||
|
{
|
||||||
|
return instance_->inboundMegolmSessionExists(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Olm Sessions
|
||||||
|
//
|
||||||
|
void
|
||||||
|
saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session)
|
||||||
|
{
|
||||||
|
instance_->saveOlmSession(curve25519, std::move(session));
|
||||||
|
}
|
||||||
|
std::vector<std::string>
|
||||||
|
getOlmSessions(const std::string &curve25519)
|
||||||
|
{
|
||||||
|
return instance_->getOlmSessions(curve25519);
|
||||||
|
}
|
||||||
|
std::optional<mtx::crypto::OlmSessionPtr>
|
||||||
|
getOlmSession(const std::string &curve25519, const std::string &session_id)
|
||||||
|
{
|
||||||
|
return instance_->getOlmSession(curve25519, session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
saveOlmAccount(const std::string &pickled)
|
||||||
|
{
|
||||||
|
instance_->saveOlmAccount(pickled);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
restoreOlmAccount()
|
||||||
|
{
|
||||||
|
return instance_->restoreOlmAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
restoreSessions()
|
||||||
|
{
|
||||||
|
return instance_->restoreSessions();
|
||||||
|
}
|
||||||
|
} // namespace cache
|
||||||
|
|
||||||
|
|
570
src/Cache.h
570
src/Cache.h
|
@ -17,501 +17,285 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <lmdb++.h>
|
#include <lmdb++.h>
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
#include <mtx/responses.hpp>
|
#include <mtx/responses.hpp>
|
||||||
#include <mtxclient/crypto/client.hpp>
|
|
||||||
|
|
||||||
#include "CacheCryptoStructs.h"
|
#include "CacheCryptoStructs.h"
|
||||||
#include "CacheStructs.h"
|
#include "CacheStructs.h"
|
||||||
#include "Logging.h"
|
|
||||||
#include "MatrixClient.h"
|
|
||||||
|
|
||||||
int
|
namespace cache {
|
||||||
numeric_key_comparison(const MDB_val *a, const MDB_val *b);
|
void
|
||||||
|
init(const QString &user_id);
|
||||||
|
|
||||||
class Cache : public QObject
|
std::string
|
||||||
{
|
displayName(const std::string &room_id, const std::string &user_id);
|
||||||
Q_OBJECT
|
QString
|
||||||
|
displayName(const QString &room_id, const QString &user_id);
|
||||||
|
QString
|
||||||
|
avatarUrl(const QString &room_id, const QString &user_id);
|
||||||
|
QString
|
||||||
|
userColor(const QString &user_id);
|
||||||
|
|
||||||
public:
|
void
|
||||||
Cache(const QString &userId, QObject *parent = nullptr);
|
removeDisplayName(const QString &room_id, const QString &user_id);
|
||||||
|
void
|
||||||
|
removeAvatarUrl(const QString &room_id, const QString &user_id);
|
||||||
|
void
|
||||||
|
removeUserColor(const QString &user_id);
|
||||||
|
|
||||||
static QHash<QString, QString> DisplayNames;
|
void
|
||||||
static QHash<QString, QString> AvatarUrls;
|
insertDisplayName(const QString &room_id, const QString &user_id, const QString &display_name);
|
||||||
static QHash<QString, QString> UserColors;
|
void
|
||||||
|
insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url);
|
||||||
|
void
|
||||||
|
insertUserColor(const QString &user_id, const QString &color_name);
|
||||||
|
|
||||||
static std::string displayName(const std::string &room_id, const std::string &user_id);
|
void
|
||||||
static QString displayName(const QString &room_id, const QString &user_id);
|
clearUserColors();
|
||||||
static QString avatarUrl(const QString &room_id, const QString &user_id);
|
|
||||||
static QString userColor(const QString &user_id);
|
|
||||||
|
|
||||||
static void removeDisplayName(const QString &room_id, const QString &user_id);
|
|
||||||
static void removeAvatarUrl(const QString &room_id, const QString &user_id);
|
|
||||||
static void removeUserColor(const QString &user_id);
|
|
||||||
|
|
||||||
static void insertDisplayName(const QString &room_id,
|
|
||||||
const QString &user_id,
|
|
||||||
const QString &display_name);
|
|
||||||
static void insertAvatarUrl(const QString &room_id,
|
|
||||||
const QString &user_id,
|
|
||||||
const QString &avatar_url);
|
|
||||||
static void insertUserColor(const QString &user_id, const QString &color_name);
|
|
||||||
|
|
||||||
static void clearUserColors();
|
|
||||||
|
|
||||||
//! Load saved data for the display names & avatars.
|
//! Load saved data for the display names & avatars.
|
||||||
void populateMembers();
|
void
|
||||||
std::vector<std::string> joinedRooms();
|
populateMembers();
|
||||||
|
std::vector<std::string>
|
||||||
|
joinedRooms();
|
||||||
|
|
||||||
QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
|
QMap<QString, RoomInfo>
|
||||||
std::map<QString, bool> invites();
|
roomInfo(bool withInvites = true);
|
||||||
|
std::map<QString, bool>
|
||||||
|
invites();
|
||||||
|
|
||||||
//! Calculate & return the name of the room.
|
//! Calculate & return the name of the room.
|
||||||
QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
QString
|
||||||
|
getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
||||||
//! Get room join rules
|
//! Get room join rules
|
||||||
mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
|
mtx::events::state::JoinRule
|
||||||
bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
|
getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
bool
|
||||||
|
getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
//! Retrieve the topic of the room if any.
|
//! Retrieve the topic of the room if any.
|
||||||
QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
|
QString
|
||||||
|
getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
//! Retrieve the room avatar's url if any.
|
//! Retrieve the room avatar's url if any.
|
||||||
QString getRoomAvatarUrl(lmdb::txn &txn,
|
QString
|
||||||
lmdb::dbi &statesdb,
|
getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb, const QString &room_id);
|
||||||
lmdb::dbi &membersdb,
|
|
||||||
const QString &room_id);
|
|
||||||
//! Retrieve the version of the room if any.
|
//! Retrieve the version of the room if any.
|
||||||
QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
|
QString
|
||||||
|
getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
|
||||||
//! Retrieve member info from a room.
|
//! Retrieve member info from a room.
|
||||||
std::vector<RoomMember> getMembers(const std::string &room_id,
|
std::vector<RoomMember>
|
||||||
std::size_t startIndex = 0,
|
getMembers(const std::string &room_id, std::size_t startIndex = 0, std::size_t len = 30);
|
||||||
std::size_t len = 30);
|
|
||||||
|
|
||||||
void saveState(const mtx::responses::Sync &res);
|
void
|
||||||
bool isInitialized() const;
|
saveState(const mtx::responses::Sync &res);
|
||||||
|
bool
|
||||||
|
isInitialized();
|
||||||
|
|
||||||
std::string nextBatchToken() const;
|
std::string
|
||||||
|
nextBatchToken();
|
||||||
|
|
||||||
void deleteData();
|
void
|
||||||
|
deleteData();
|
||||||
|
|
||||||
void removeInvite(lmdb::txn &txn, const std::string &room_id);
|
void
|
||||||
void removeInvite(const std::string &room_id);
|
removeInvite(lmdb::txn &txn, const std::string &room_id);
|
||||||
void removeRoom(lmdb::txn &txn, const std::string &roomid);
|
void
|
||||||
void removeRoom(const std::string &roomid);
|
removeInvite(const std::string &room_id);
|
||||||
void removeRoom(const QString &roomid) { removeRoom(roomid.toStdString()); };
|
void
|
||||||
void setup();
|
removeRoom(lmdb::txn &txn, const std::string &roomid);
|
||||||
|
void
|
||||||
|
removeRoom(const std::string &roomid);
|
||||||
|
void
|
||||||
|
removeRoom(const QString &roomid);
|
||||||
|
void
|
||||||
|
setup();
|
||||||
|
|
||||||
bool isFormatValid();
|
bool
|
||||||
void setCurrentFormat();
|
isFormatValid();
|
||||||
|
void
|
||||||
|
setCurrentFormat();
|
||||||
|
|
||||||
std::map<QString, mtx::responses::Timeline> roomMessages();
|
std::map<QString, mtx::responses::Timeline>
|
||||||
|
roomMessages();
|
||||||
|
|
||||||
QMap<QString, mtx::responses::Notifications> getTimelineMentions();
|
QMap<QString, mtx::responses::Notifications>
|
||||||
|
getTimelineMentions();
|
||||||
|
|
||||||
//! Retrieve all the user ids from a room.
|
//! Retrieve all the user ids from a room.
|
||||||
std::vector<std::string> roomMembers(const std::string &room_id);
|
std::vector<std::string>
|
||||||
|
roomMembers(const std::string &room_id);
|
||||||
|
|
||||||
//! Check if the given user has power leve greater than than
|
//! Check if the given user has power leve greater than than
|
||||||
//! lowest power level of the given events.
|
//! lowest power level of the given events.
|
||||||
bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
|
bool
|
||||||
|
hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
|
||||||
const std::string &room_id,
|
const std::string &room_id,
|
||||||
const std::string &user_id);
|
const std::string &user_id);
|
||||||
|
|
||||||
//! Retrieves the saved room avatar.
|
//! Retrieves the saved room avatar.
|
||||||
QImage getRoomAvatar(const QString &id);
|
QImage
|
||||||
QImage getRoomAvatar(const std::string &id);
|
getRoomAvatar(const QString &id);
|
||||||
|
QImage
|
||||||
|
getRoomAvatar(const std::string &id);
|
||||||
|
|
||||||
//! Adds a user to the read list for the given event.
|
//! Adds a user to the read list for the given event.
|
||||||
//!
|
//!
|
||||||
//! There should be only one user id present in a receipt list per room.
|
//! There should be only one user id present in a receipt list per room.
|
||||||
//! The user id should be removed from any other lists.
|
//! The user id should be removed from any other lists.
|
||||||
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
|
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
|
||||||
void updateReadReceipt(lmdb::txn &txn,
|
void
|
||||||
const std::string &room_id,
|
updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts);
|
||||||
const Receipts &receipts);
|
|
||||||
|
|
||||||
//! Retrieve all the read receipts for the given event id and room.
|
//! Retrieve all the read receipts for the given event id and room.
|
||||||
//!
|
//!
|
||||||
//! Returns a map of user ids and the time of the read receipt in milliseconds.
|
//! Returns a map of user ids and the time of the read receipt in milliseconds.
|
||||||
using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
|
using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
|
||||||
UserReceipts readReceipts(const QString &event_id, const QString &room_id);
|
UserReceipts
|
||||||
|
readReceipts(const QString &event_id, const QString &room_id);
|
||||||
|
|
||||||
//! Filter the events that have at least one read receipt.
|
//! Filter the events that have at least one read receipt.
|
||||||
std::vector<QString> filterReadEvents(const QString &room_id,
|
std::vector<QString>
|
||||||
|
filterReadEvents(const QString &room_id,
|
||||||
const std::vector<QString> &event_ids,
|
const std::vector<QString> &event_ids,
|
||||||
const std::string &excluded_user);
|
const std::string &excluded_user);
|
||||||
//! Add event for which we are expecting some read receipts.
|
//! Add event for which we are expecting some read receipts.
|
||||||
void addPendingReceipt(const QString &room_id, const QString &event_id);
|
void
|
||||||
void removePendingReceipt(lmdb::txn &txn,
|
addPendingReceipt(const QString &room_id, const QString &event_id);
|
||||||
const std::string &room_id,
|
void
|
||||||
const std::string &event_id);
|
removePendingReceipt(lmdb::txn &txn, const std::string &room_id, const std::string &event_id);
|
||||||
void notifyForReadReceipts(const std::string &room_id);
|
void
|
||||||
std::vector<QString> pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id);
|
notifyForReadReceipts(const std::string &room_id);
|
||||||
|
std::vector<QString>
|
||||||
|
pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id);
|
||||||
|
|
||||||
QByteArray image(const QString &url) const;
|
QByteArray
|
||||||
QByteArray image(lmdb::txn &txn, const std::string &url) const;
|
image(const QString &url);
|
||||||
QByteArray image(const std::string &url) const
|
QByteArray
|
||||||
|
image(lmdb::txn &txn, const std::string &url);
|
||||||
|
inline QByteArray
|
||||||
|
image(const std::string &url)
|
||||||
{
|
{
|
||||||
return image(QString::fromStdString(url));
|
return image(QString::fromStdString(url));
|
||||||
}
|
}
|
||||||
void saveImage(const std::string &url, const std::string &data);
|
void
|
||||||
void saveImage(const QString &url, const QByteArray &data);
|
saveImage(const std::string &url, const std::string &data);
|
||||||
|
void
|
||||||
|
saveImage(const QString &url, const QByteArray &data);
|
||||||
|
|
||||||
RoomInfo singleRoomInfo(const std::string &room_id);
|
RoomInfo
|
||||||
std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res);
|
singleRoomInfo(const std::string &room_id);
|
||||||
std::vector<std::string> roomsWithTagUpdates(const mtx::responses::Sync &res);
|
std::vector<std::string>
|
||||||
std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms);
|
roomsWithStateUpdates(const mtx::responses::Sync &res);
|
||||||
std::map<QString, RoomInfo> roomUpdates(const mtx::responses::Sync &sync)
|
std::vector<std::string>
|
||||||
|
roomsWithTagUpdates(const mtx::responses::Sync &res);
|
||||||
|
std::map<QString, RoomInfo>
|
||||||
|
getRoomInfo(const std::vector<std::string> &rooms);
|
||||||
|
inline std::map<QString, RoomInfo>
|
||||||
|
roomUpdates(const mtx::responses::Sync &sync)
|
||||||
{
|
{
|
||||||
return getRoomInfo(roomsWithStateUpdates(sync));
|
return getRoomInfo(roomsWithStateUpdates(sync));
|
||||||
}
|
}
|
||||||
std::map<QString, RoomInfo> roomTagUpdates(const mtx::responses::Sync &sync)
|
inline std::map<QString, RoomInfo>
|
||||||
|
roomTagUpdates(const mtx::responses::Sync &sync)
|
||||||
{
|
{
|
||||||
return getRoomInfo(roomsWithTagUpdates(sync));
|
return getRoomInfo(roomsWithTagUpdates(sync));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Calculates which the read status of a room.
|
//! Calculates which the read status of a room.
|
||||||
//! Whether all the events in the timeline have been read.
|
//! Whether all the events in the timeline have been read.
|
||||||
bool calculateRoomReadStatus(const std::string &room_id);
|
bool
|
||||||
void calculateRoomReadStatus();
|
calculateRoomReadStatus(const std::string &room_id);
|
||||||
|
void
|
||||||
|
calculateRoomReadStatus();
|
||||||
|
|
||||||
QVector<SearchResult> searchUsers(const std::string &room_id,
|
QVector<SearchResult>
|
||||||
const std::string &query,
|
searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items = 5);
|
||||||
std::uint8_t max_items = 5);
|
std::vector<RoomSearchResult>
|
||||||
std::vector<RoomSearchResult> searchRooms(const std::string &query,
|
searchRooms(const std::string &query, std::uint8_t max_items = 5);
|
||||||
std::uint8_t max_items = 5);
|
|
||||||
|
|
||||||
void markSentNotification(const std::string &event_id);
|
void
|
||||||
|
markSentNotification(const std::string &event_id);
|
||||||
//! Removes an event from the sent notifications.
|
//! Removes an event from the sent notifications.
|
||||||
void removeReadNotification(const std::string &event_id);
|
void
|
||||||
|
removeReadNotification(const std::string &event_id);
|
||||||
//! Check if we have sent a desktop notification for the given event id.
|
//! Check if we have sent a desktop notification for the given event id.
|
||||||
bool isNotificationSent(const std::string &event_id);
|
bool
|
||||||
|
isNotificationSent(const std::string &event_id);
|
||||||
|
|
||||||
//! Add all notifications containing a user mention to the db.
|
//! Add all notifications containing a user mention to the db.
|
||||||
void saveTimelineMentions(const mtx::responses::Notifications &res);
|
void
|
||||||
|
saveTimelineMentions(const mtx::responses::Notifications &res);
|
||||||
|
|
||||||
//! Remove old unused data.
|
//! Remove old unused data.
|
||||||
void deleteOldMessages();
|
void
|
||||||
void deleteOldData() noexcept;
|
deleteOldMessages();
|
||||||
|
void
|
||||||
|
deleteOldData() noexcept;
|
||||||
//! Retrieve all saved room ids.
|
//! Retrieve all saved room ids.
|
||||||
std::vector<std::string> getRoomIds(lmdb::txn &txn);
|
std::vector<std::string>
|
||||||
|
getRoomIds(lmdb::txn &txn);
|
||||||
|
|
||||||
//! Mark a room that uses e2e encryption.
|
//! Mark a room that uses e2e encryption.
|
||||||
void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
|
void
|
||||||
bool isRoomEncrypted(const std::string &room_id);
|
setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
|
||||||
|
bool
|
||||||
//! Save the public keys for a device.
|
isRoomEncrypted(const std::string &room_id);
|
||||||
void saveDeviceKeys(const std::string &device_id);
|
|
||||||
void getDeviceKeys(const std::string &device_id);
|
|
||||||
|
|
||||||
//! Save the device list for a user.
|
|
||||||
void setDeviceList(const std::string &user_id, const std::vector<std::string> &devices);
|
|
||||||
std::vector<std::string> getDeviceList(const std::string &user_id);
|
|
||||||
|
|
||||||
//! Check if a user is a member of the room.
|
//! Check if a user is a member of the room.
|
||||||
bool isRoomMember(const std::string &user_id, const std::string &room_id);
|
bool
|
||||||
|
isRoomMember(const std::string &user_id, const std::string &room_id);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Outbound Megolm Sessions
|
// Outbound Megolm Sessions
|
||||||
//
|
//
|
||||||
void saveOutboundMegolmSession(const std::string &room_id,
|
void
|
||||||
|
saveOutboundMegolmSession(const std::string &room_id,
|
||||||
const OutboundGroupSessionData &data,
|
const OutboundGroupSessionData &data,
|
||||||
mtx::crypto::OutboundGroupSessionPtr session);
|
mtx::crypto::OutboundGroupSessionPtr session);
|
||||||
OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id);
|
OutboundGroupSessionDataRef
|
||||||
bool outboundMegolmSessionExists(const std::string &room_id) noexcept;
|
getOutboundMegolmSession(const std::string &room_id);
|
||||||
void updateOutboundMegolmSession(const std::string &room_id, int message_index);
|
bool
|
||||||
|
outboundMegolmSessionExists(const std::string &room_id) noexcept;
|
||||||
|
void
|
||||||
|
updateOutboundMegolmSession(const std::string &room_id, int message_index);
|
||||||
|
|
||||||
void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
|
void
|
||||||
mtx::crypto::ExportedSessionKeys exportSessionKeys();
|
importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
|
||||||
|
mtx::crypto::ExportedSessionKeys
|
||||||
|
exportSessionKeys();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Inbound Megolm Sessions
|
// Inbound Megolm Sessions
|
||||||
//
|
//
|
||||||
void saveInboundMegolmSession(const MegolmSessionIndex &index,
|
void
|
||||||
|
saveInboundMegolmSession(const MegolmSessionIndex &index,
|
||||||
mtx::crypto::InboundGroupSessionPtr session);
|
mtx::crypto::InboundGroupSessionPtr session);
|
||||||
OlmInboundGroupSession *getInboundMegolmSession(const MegolmSessionIndex &index);
|
OlmInboundGroupSession *
|
||||||
bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
|
getInboundMegolmSession(const MegolmSessionIndex &index);
|
||||||
|
bool
|
||||||
|
inboundMegolmSessionExists(const MegolmSessionIndex &index);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Olm Sessions
|
// Olm Sessions
|
||||||
//
|
//
|
||||||
void saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session);
|
|
||||||
std::vector<std::string> getOlmSessions(const std::string &curve25519);
|
|
||||||
std::optional<mtx::crypto::OlmSessionPtr> getOlmSession(const std::string &curve25519,
|
|
||||||
const std::string &session_id);
|
|
||||||
|
|
||||||
void saveOlmAccount(const std::string &pickled);
|
|
||||||
std::string restoreOlmAccount();
|
|
||||||
|
|
||||||
void restoreSessions();
|
|
||||||
|
|
||||||
OlmSessionStorage session_storage;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
|
||||||
void roomReadStatus(const std::map<QString, bool> &status);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Save an invited room.
|
|
||||||
void saveInvite(lmdb::txn &txn,
|
|
||||||
lmdb::dbi &statesdb,
|
|
||||||
lmdb::dbi &membersdb,
|
|
||||||
const mtx::responses::InvitedRoom &room);
|
|
||||||
|
|
||||||
//! Add a notification containing a user mention to the db.
|
|
||||||
void saveTimelineMentions(lmdb::txn &txn,
|
|
||||||
const std::string &room_id,
|
|
||||||
const QList<mtx::responses::Notification> &res);
|
|
||||||
|
|
||||||
//! Get timeline items that a user was mentions in for a given room
|
|
||||||
mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn,
|
|
||||||
const std::string &room_id);
|
|
||||||
|
|
||||||
QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
|
||||||
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>
|
|
||||||
void saveStateEvents(lmdb::txn &txn,
|
|
||||||
const lmdb::dbi &statesdb,
|
|
||||||
const lmdb::dbi &membersdb,
|
|
||||||
const std::string &room_id,
|
|
||||||
const std::vector<T> &events)
|
|
||||||
{
|
|
||||||
for (const auto &e : events)
|
|
||||||
saveStateEvent(txn, statesdb, membersdb, room_id, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void saveStateEvent(lmdb::txn &txn,
|
|
||||||
const lmdb::dbi &statesdb,
|
|
||||||
const lmdb::dbi &membersdb,
|
|
||||||
const std::string &room_id,
|
|
||||||
const T &event)
|
|
||||||
{
|
|
||||||
using namespace mtx::events;
|
|
||||||
using namespace mtx::events::state;
|
|
||||||
|
|
||||||
if (auto e = std::get_if<StateEvent<Member>>(&event); e != nullptr) {
|
|
||||||
switch (e->content.membership) {
|
|
||||||
//
|
|
||||||
// We only keep users with invite or join membership.
|
|
||||||
//
|
|
||||||
case Membership::Invite:
|
|
||||||
case Membership::Join: {
|
|
||||||
auto display_name = e->content.display_name.empty()
|
|
||||||
? e->state_key
|
|
||||||
: e->content.display_name;
|
|
||||||
|
|
||||||
// Lightweight representation of a member.
|
|
||||||
MemberInfo tmp{display_name, e->content.avatar_url};
|
|
||||||
|
|
||||||
lmdb::dbi_put(txn,
|
|
||||||
membersdb,
|
|
||||||
lmdb::val(e->state_key),
|
|
||||||
lmdb::val(json(tmp).dump()));
|
|
||||||
|
|
||||||
insertDisplayName(QString::fromStdString(room_id),
|
|
||||||
QString::fromStdString(e->state_key),
|
|
||||||
QString::fromStdString(display_name));
|
|
||||||
|
|
||||||
insertAvatarUrl(QString::fromStdString(room_id),
|
|
||||||
QString::fromStdString(e->state_key),
|
|
||||||
QString::fromStdString(e->content.avatar_url));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
lmdb::dbi_del(
|
|
||||||
txn, membersdb, lmdb::val(e->state_key), lmdb::val(""));
|
|
||||||
|
|
||||||
removeDisplayName(QString::fromStdString(room_id),
|
|
||||||
QString::fromStdString(e->state_key));
|
|
||||||
removeAvatarUrl(QString::fromStdString(room_id),
|
|
||||||
QString::fromStdString(e->state_key));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else if (std::holds_alternative<StateEvent<Encryption>>(event)) {
|
|
||||||
setEncryptedRoom(txn, room_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isStateEvent(event))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::visit(
|
|
||||||
[&txn, &statesdb](auto e) {
|
|
||||||
lmdb::dbi_put(
|
|
||||||
txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump()));
|
|
||||||
},
|
|
||||||
event);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
bool isStateEvent(const T &e)
|
|
||||||
{
|
|
||||||
using namespace mtx::events;
|
|
||||||
using namespace mtx::events::state;
|
|
||||||
|
|
||||||
return std::holds_alternative<StateEvent<Aliases>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<state::Avatar>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<CanonicalAlias>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Create>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<GuestAccess>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<HistoryVisibility>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<JoinRules>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Name>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Member>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<PowerLevels>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Topic>>(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
bool containsStateUpdates(const T &e)
|
|
||||||
{
|
|
||||||
using namespace mtx::events;
|
|
||||||
using namespace mtx::events::state;
|
|
||||||
|
|
||||||
return std::holds_alternative<StateEvent<state::Avatar>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<CanonicalAlias>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Name>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Member>>(e) ||
|
|
||||||
std::holds_alternative<StateEvent<Topic>>(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e)
|
|
||||||
{
|
|
||||||
using namespace mtx::events;
|
|
||||||
using namespace mtx::events::state;
|
|
||||||
|
|
||||||
return std::holds_alternative<StrippedEvent<state::Avatar>>(e) ||
|
|
||||||
std::holds_alternative<StrippedEvent<CanonicalAlias>>(e) ||
|
|
||||||
std::holds_alternative<StrippedEvent<Name>>(e) ||
|
|
||||||
std::holds_alternative<StrippedEvent<Member>>(e) ||
|
|
||||||
std::holds_alternative<StrippedEvent<Topic>>(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveInvites(lmdb::txn &txn,
|
|
||||||
const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
|
||||||
|
|
||||||
//! Sends signals for the rooms that are removed.
|
|
||||||
void removeLeftRooms(lmdb::txn &txn,
|
|
||||||
const std::map<std::string, mtx::responses::LeftRoom> &rooms)
|
|
||||||
{
|
|
||||||
for (const auto &room : rooms) {
|
|
||||||
removeRoom(txn, room.first);
|
|
||||||
|
|
||||||
// Clean up leftover invites.
|
|
||||||
removeInvite(txn, room.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(
|
|
||||||
txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Retrieves or creates the database that stores the open OLM sessions between our device
|
|
||||||
//! and the given curve25519 key which represents another device.
|
|
||||||
//!
|
|
||||||
//! Each entry is a map from the session_id to the pickled representation of the session.
|
|
||||||
lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key)
|
|
||||||
{
|
|
||||||
return lmdb::dbi::open(
|
|
||||||
txn, std::string("olm_sessions/" + curve25519_key).c_str(), MDB_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &event)
|
|
||||||
{
|
|
||||||
if (!event.content.display_name.empty())
|
|
||||||
return QString::fromStdString(event.content.display_name);
|
|
||||||
|
|
||||||
return QString::fromStdString(event.state_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNextBatchToken(lmdb::txn &txn, const std::string &token);
|
|
||||||
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
|
||||||
|
|
||||||
lmdb::env env_;
|
|
||||||
lmdb::dbi syncStateDb_;
|
|
||||||
lmdb::dbi roomsDb_;
|
|
||||||
lmdb::dbi invitesDb_;
|
|
||||||
lmdb::dbi mediaDb_;
|
|
||||||
lmdb::dbi readReceiptsDb_;
|
|
||||||
lmdb::dbi notificationsDb_;
|
|
||||||
|
|
||||||
lmdb::dbi devicesDb_;
|
|
||||||
lmdb::dbi deviceKeysDb_;
|
|
||||||
|
|
||||||
lmdb::dbi inboundMegolmSessionDb_;
|
|
||||||
lmdb::dbi outboundMegolmSessionDb_;
|
|
||||||
|
|
||||||
QString localUserId_;
|
|
||||||
QString cacheDirectory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace cache {
|
|
||||||
void
|
void
|
||||||
init(const QString &user_id);
|
saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session);
|
||||||
|
std::vector<std::string>
|
||||||
|
getOlmSessions(const std::string &curve25519);
|
||||||
|
std::optional<mtx::crypto::OlmSessionPtr>
|
||||||
|
getOlmSession(const std::string &curve25519, const std::string &session_id);
|
||||||
|
|
||||||
Cache *
|
void
|
||||||
client();
|
saveOlmAccount(const std::string &pickled);
|
||||||
|
std::string
|
||||||
|
restoreOlmAccount();
|
||||||
|
|
||||||
|
void
|
||||||
|
restoreSessions();
|
||||||
}
|
}
|
||||||
|
|
494
src/Cache_p.h
Normal file
494
src/Cache_p.h
Normal file
|
@ -0,0 +1,494 @@
|
||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2019 The nheko authors
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <lmdb++.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <mtx/responses.hpp>
|
||||||
|
#include <mtxclient/crypto/client.hpp>
|
||||||
|
|
||||||
|
#include "CacheCryptoStructs.h"
|
||||||
|
#include "CacheStructs.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
#include "MatrixClient.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
numeric_key_comparison(const MDB_val *a, const MDB_val *b);
|
||||||
|
|
||||||
|
class Cache : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Cache(const QString &userId, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
static std::string displayName(const std::string &room_id, const std::string &user_id);
|
||||||
|
static QString displayName(const QString &room_id, const QString &user_id);
|
||||||
|
static QString avatarUrl(const QString &room_id, const QString &user_id);
|
||||||
|
static QString userColor(const QString &user_id);
|
||||||
|
|
||||||
|
static void removeDisplayName(const QString &room_id, const QString &user_id);
|
||||||
|
static void removeAvatarUrl(const QString &room_id, const QString &user_id);
|
||||||
|
static void removeUserColor(const QString &user_id);
|
||||||
|
|
||||||
|
static void insertDisplayName(const QString &room_id,
|
||||||
|
const QString &user_id,
|
||||||
|
const QString &display_name);
|
||||||
|
static void insertAvatarUrl(const QString &room_id,
|
||||||
|
const QString &user_id,
|
||||||
|
const QString &avatar_url);
|
||||||
|
static void insertUserColor(const QString &user_id, const QString &color_name);
|
||||||
|
|
||||||
|
static void clearUserColors();
|
||||||
|
|
||||||
|
//! Load saved data for the display names & avatars.
|
||||||
|
void populateMembers();
|
||||||
|
std::vector<std::string> joinedRooms();
|
||||||
|
|
||||||
|
QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
|
||||||
|
std::map<QString, bool> invites();
|
||||||
|
|
||||||
|
//! Calculate & return the name of the room.
|
||||||
|
QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
||||||
|
//! Get room join rules
|
||||||
|
mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
//! Retrieve the topic of the room if any.
|
||||||
|
QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
//! Retrieve the room avatar's url if any.
|
||||||
|
QString getRoomAvatarUrl(lmdb::txn &txn,
|
||||||
|
lmdb::dbi &statesdb,
|
||||||
|
lmdb::dbi &membersdb,
|
||||||
|
const QString &room_id);
|
||||||
|
//! Retrieve the version of the room if any.
|
||||||
|
QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
|
||||||
|
|
||||||
|
//! Retrieve member info from a room.
|
||||||
|
std::vector<RoomMember> getMembers(const std::string &room_id,
|
||||||
|
std::size_t startIndex = 0,
|
||||||
|
std::size_t len = 30);
|
||||||
|
|
||||||
|
void saveState(const mtx::responses::Sync &res);
|
||||||
|
bool isInitialized() const;
|
||||||
|
|
||||||
|
std::string nextBatchToken() const;
|
||||||
|
|
||||||
|
void deleteData();
|
||||||
|
|
||||||
|
void removeInvite(lmdb::txn &txn, const std::string &room_id);
|
||||||
|
void removeInvite(const std::string &room_id);
|
||||||
|
void removeRoom(lmdb::txn &txn, const std::string &roomid);
|
||||||
|
void removeRoom(const std::string &roomid);
|
||||||
|
void setup();
|
||||||
|
|
||||||
|
bool isFormatValid();
|
||||||
|
void setCurrentFormat();
|
||||||
|
|
||||||
|
std::map<QString, mtx::responses::Timeline> roomMessages();
|
||||||
|
|
||||||
|
QMap<QString, mtx::responses::Notifications> getTimelineMentions();
|
||||||
|
|
||||||
|
//! Retrieve all the user ids from a room.
|
||||||
|
std::vector<std::string> roomMembers(const std::string &room_id);
|
||||||
|
|
||||||
|
//! Check if the given user has power leve greater than than
|
||||||
|
//! lowest power level of the given events.
|
||||||
|
bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
|
||||||
|
const std::string &room_id,
|
||||||
|
const std::string &user_id);
|
||||||
|
|
||||||
|
//! Retrieves the saved room avatar.
|
||||||
|
QImage getRoomAvatar(const QString &id);
|
||||||
|
QImage getRoomAvatar(const std::string &id);
|
||||||
|
|
||||||
|
//! Adds a user to the read list for the given event.
|
||||||
|
//!
|
||||||
|
//! There should be only one user id present in a receipt list per room.
|
||||||
|
//! The user id should be removed from any other lists.
|
||||||
|
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
|
||||||
|
void updateReadReceipt(lmdb::txn &txn,
|
||||||
|
const std::string &room_id,
|
||||||
|
const Receipts &receipts);
|
||||||
|
|
||||||
|
//! Retrieve all the read receipts for the given event id and room.
|
||||||
|
//!
|
||||||
|
//! Returns a map of user ids and the time of the read receipt in milliseconds.
|
||||||
|
using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
|
||||||
|
UserReceipts readReceipts(const QString &event_id, const QString &room_id);
|
||||||
|
|
||||||
|
//! Filter the events that have at least one read receipt.
|
||||||
|
std::vector<QString> filterReadEvents(const QString &room_id,
|
||||||
|
const std::vector<QString> &event_ids,
|
||||||
|
const std::string &excluded_user);
|
||||||
|
//! Add event for which we are expecting some read receipts.
|
||||||
|
void addPendingReceipt(const QString &room_id, const QString &event_id);
|
||||||
|
void removePendingReceipt(lmdb::txn &txn,
|
||||||
|
const std::string &room_id,
|
||||||
|
const std::string &event_id);
|
||||||
|
void notifyForReadReceipts(const std::string &room_id);
|
||||||
|
std::vector<QString> pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id);
|
||||||
|
|
||||||
|
QByteArray image(const QString &url) const;
|
||||||
|
QByteArray image(lmdb::txn &txn, const std::string &url) const;
|
||||||
|
void saveImage(const std::string &url, const std::string &data);
|
||||||
|
void saveImage(const QString &url, const QByteArray &data);
|
||||||
|
|
||||||
|
RoomInfo singleRoomInfo(const std::string &room_id);
|
||||||
|
std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res);
|
||||||
|
std::vector<std::string> roomsWithTagUpdates(const mtx::responses::Sync &res);
|
||||||
|
std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms);
|
||||||
|
|
||||||
|
//! Calculates which the read status of a room.
|
||||||
|
//! Whether all the events in the timeline have been read.
|
||||||
|
bool calculateRoomReadStatus(const std::string &room_id);
|
||||||
|
void calculateRoomReadStatus();
|
||||||
|
|
||||||
|
QVector<SearchResult> searchUsers(const std::string &room_id,
|
||||||
|
const std::string &query,
|
||||||
|
std::uint8_t max_items = 5);
|
||||||
|
std::vector<RoomSearchResult> searchRooms(const std::string &query,
|
||||||
|
std::uint8_t max_items = 5);
|
||||||
|
|
||||||
|
void markSentNotification(const std::string &event_id);
|
||||||
|
//! Removes an event from the sent notifications.
|
||||||
|
void removeReadNotification(const std::string &event_id);
|
||||||
|
//! Check if we have sent a desktop notification for the given event id.
|
||||||
|
bool isNotificationSent(const std::string &event_id);
|
||||||
|
|
||||||
|
//! Add all notifications containing a user mention to the db.
|
||||||
|
void saveTimelineMentions(const mtx::responses::Notifications &res);
|
||||||
|
|
||||||
|
//! Remove old unused data.
|
||||||
|
void deleteOldMessages();
|
||||||
|
void deleteOldData() noexcept;
|
||||||
|
//! Retrieve all saved room ids.
|
||||||
|
std::vector<std::string> getRoomIds(lmdb::txn &txn);
|
||||||
|
|
||||||
|
//! Mark a room that uses e2e encryption.
|
||||||
|
void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
|
||||||
|
bool isRoomEncrypted(const std::string &room_id);
|
||||||
|
|
||||||
|
//! Check if a user is a member of the room.
|
||||||
|
bool isRoomMember(const std::string &user_id, const std::string &room_id);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Outbound Megolm Sessions
|
||||||
|
//
|
||||||
|
void saveOutboundMegolmSession(const std::string &room_id,
|
||||||
|
const OutboundGroupSessionData &data,
|
||||||
|
mtx::crypto::OutboundGroupSessionPtr session);
|
||||||
|
OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id);
|
||||||
|
bool outboundMegolmSessionExists(const std::string &room_id) noexcept;
|
||||||
|
void updateOutboundMegolmSession(const std::string &room_id, int message_index);
|
||||||
|
|
||||||
|
void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
|
||||||
|
mtx::crypto::ExportedSessionKeys exportSessionKeys();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inbound Megolm Sessions
|
||||||
|
//
|
||||||
|
void saveInboundMegolmSession(const MegolmSessionIndex &index,
|
||||||
|
mtx::crypto::InboundGroupSessionPtr session);
|
||||||
|
OlmInboundGroupSession *getInboundMegolmSession(const MegolmSessionIndex &index);
|
||||||
|
bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Olm Sessions
|
||||||
|
//
|
||||||
|
void saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session);
|
||||||
|
std::vector<std::string> getOlmSessions(const std::string &curve25519);
|
||||||
|
std::optional<mtx::crypto::OlmSessionPtr> getOlmSession(const std::string &curve25519,
|
||||||
|
const std::string &session_id);
|
||||||
|
|
||||||
|
void saveOlmAccount(const std::string &pickled);
|
||||||
|
std::string restoreOlmAccount();
|
||||||
|
|
||||||
|
void restoreSessions();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
||||||
|
void roomReadStatus(const std::map<QString, bool> &status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Save an invited room.
|
||||||
|
void saveInvite(lmdb::txn &txn,
|
||||||
|
lmdb::dbi &statesdb,
|
||||||
|
lmdb::dbi &membersdb,
|
||||||
|
const mtx::responses::InvitedRoom &room);
|
||||||
|
|
||||||
|
//! Add a notification containing a user mention to the db.
|
||||||
|
void saveTimelineMentions(lmdb::txn &txn,
|
||||||
|
const std::string &room_id,
|
||||||
|
const QList<mtx::responses::Notification> &res);
|
||||||
|
|
||||||
|
//! Get timeline items that a user was mentions in for a given room
|
||||||
|
mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn,
|
||||||
|
const std::string &room_id);
|
||||||
|
|
||||||
|
QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
||||||
|
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>
|
||||||
|
void saveStateEvents(lmdb::txn &txn,
|
||||||
|
const lmdb::dbi &statesdb,
|
||||||
|
const lmdb::dbi &membersdb,
|
||||||
|
const std::string &room_id,
|
||||||
|
const std::vector<T> &events)
|
||||||
|
{
|
||||||
|
for (const auto &e : events)
|
||||||
|
saveStateEvent(txn, statesdb, membersdb, room_id, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void saveStateEvent(lmdb::txn &txn,
|
||||||
|
const lmdb::dbi &statesdb,
|
||||||
|
const lmdb::dbi &membersdb,
|
||||||
|
const std::string &room_id,
|
||||||
|
const T &event)
|
||||||
|
{
|
||||||
|
using namespace mtx::events;
|
||||||
|
using namespace mtx::events::state;
|
||||||
|
|
||||||
|
if (auto e = std::get_if<StateEvent<Member>>(&event); e != nullptr) {
|
||||||
|
switch (e->content.membership) {
|
||||||
|
//
|
||||||
|
// We only keep users with invite or join membership.
|
||||||
|
//
|
||||||
|
case Membership::Invite:
|
||||||
|
case Membership::Join: {
|
||||||
|
auto display_name = e->content.display_name.empty()
|
||||||
|
? e->state_key
|
||||||
|
: e->content.display_name;
|
||||||
|
|
||||||
|
// Lightweight representation of a member.
|
||||||
|
MemberInfo tmp{display_name, e->content.avatar_url};
|
||||||
|
|
||||||
|
lmdb::dbi_put(txn,
|
||||||
|
membersdb,
|
||||||
|
lmdb::val(e->state_key),
|
||||||
|
lmdb::val(json(tmp).dump()));
|
||||||
|
|
||||||
|
insertDisplayName(QString::fromStdString(room_id),
|
||||||
|
QString::fromStdString(e->state_key),
|
||||||
|
QString::fromStdString(display_name));
|
||||||
|
|
||||||
|
insertAvatarUrl(QString::fromStdString(room_id),
|
||||||
|
QString::fromStdString(e->state_key),
|
||||||
|
QString::fromStdString(e->content.avatar_url));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
lmdb::dbi_del(
|
||||||
|
txn, membersdb, lmdb::val(e->state_key), lmdb::val(""));
|
||||||
|
|
||||||
|
removeDisplayName(QString::fromStdString(room_id),
|
||||||
|
QString::fromStdString(e->state_key));
|
||||||
|
removeAvatarUrl(QString::fromStdString(room_id),
|
||||||
|
QString::fromStdString(e->state_key));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (std::holds_alternative<StateEvent<Encryption>>(event)) {
|
||||||
|
setEncryptedRoom(txn, room_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isStateEvent(event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::visit(
|
||||||
|
[&txn, &statesdb](auto e) {
|
||||||
|
lmdb::dbi_put(
|
||||||
|
txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump()));
|
||||||
|
},
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool isStateEvent(const T &e)
|
||||||
|
{
|
||||||
|
using namespace mtx::events;
|
||||||
|
using namespace mtx::events::state;
|
||||||
|
|
||||||
|
return std::holds_alternative<StateEvent<Aliases>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<state::Avatar>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<CanonicalAlias>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Create>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<GuestAccess>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<HistoryVisibility>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<JoinRules>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Name>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Member>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<PowerLevels>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Topic>>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool containsStateUpdates(const T &e)
|
||||||
|
{
|
||||||
|
using namespace mtx::events;
|
||||||
|
using namespace mtx::events::state;
|
||||||
|
|
||||||
|
return std::holds_alternative<StateEvent<state::Avatar>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<CanonicalAlias>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Name>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Member>>(e) ||
|
||||||
|
std::holds_alternative<StateEvent<Topic>>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e)
|
||||||
|
{
|
||||||
|
using namespace mtx::events;
|
||||||
|
using namespace mtx::events::state;
|
||||||
|
|
||||||
|
return std::holds_alternative<StrippedEvent<state::Avatar>>(e) ||
|
||||||
|
std::holds_alternative<StrippedEvent<CanonicalAlias>>(e) ||
|
||||||
|
std::holds_alternative<StrippedEvent<Name>>(e) ||
|
||||||
|
std::holds_alternative<StrippedEvent<Member>>(e) ||
|
||||||
|
std::holds_alternative<StrippedEvent<Topic>>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveInvites(lmdb::txn &txn,
|
||||||
|
const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
||||||
|
|
||||||
|
//! Sends signals for the rooms that are removed.
|
||||||
|
void removeLeftRooms(lmdb::txn &txn,
|
||||||
|
const std::map<std::string, mtx::responses::LeftRoom> &rooms)
|
||||||
|
{
|
||||||
|
for (const auto &room : rooms) {
|
||||||
|
removeRoom(txn, room.first);
|
||||||
|
|
||||||
|
// Clean up leftover invites.
|
||||||
|
removeInvite(txn, room.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(
|
||||||
|
txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Retrieves or creates the database that stores the open OLM sessions between our device
|
||||||
|
//! and the given curve25519 key which represents another device.
|
||||||
|
//!
|
||||||
|
//! Each entry is a map from the session_id to the pickled representation of the session.
|
||||||
|
lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key)
|
||||||
|
{
|
||||||
|
return lmdb::dbi::open(
|
||||||
|
txn, std::string("olm_sessions/" + curve25519_key).c_str(), MDB_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &event)
|
||||||
|
{
|
||||||
|
if (!event.content.display_name.empty())
|
||||||
|
return QString::fromStdString(event.content.display_name);
|
||||||
|
|
||||||
|
return QString::fromStdString(event.state_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNextBatchToken(lmdb::txn &txn, const std::string &token);
|
||||||
|
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
||||||
|
|
||||||
|
lmdb::env env_;
|
||||||
|
lmdb::dbi syncStateDb_;
|
||||||
|
lmdb::dbi roomsDb_;
|
||||||
|
lmdb::dbi invitesDb_;
|
||||||
|
lmdb::dbi mediaDb_;
|
||||||
|
lmdb::dbi readReceiptsDb_;
|
||||||
|
lmdb::dbi notificationsDb_;
|
||||||
|
|
||||||
|
lmdb::dbi devicesDb_;
|
||||||
|
lmdb::dbi deviceKeysDb_;
|
||||||
|
|
||||||
|
lmdb::dbi inboundMegolmSessionDb_;
|
||||||
|
lmdb::dbi outboundMegolmSessionDb_;
|
||||||
|
|
||||||
|
QString localUserId_;
|
||||||
|
QString cacheDirectory_;
|
||||||
|
|
||||||
|
static QHash<QString, QString> DisplayNames;
|
||||||
|
static QHash<QString, QString> AvatarUrls;
|
||||||
|
static QHash<QString, QString> UserColors;
|
||||||
|
|
||||||
|
OlmSessionStorage session_storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace cache {
|
||||||
|
Cache *
|
||||||
|
client();
|
||||||
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "AvatarProvider.h"
|
#include "AvatarProvider.h"
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
#include "Cache_p.h"
|
||||||
#include "ChatPage.h"
|
#include "ChatPage.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
@ -319,7 +320,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
auto bin = dev->peek(dev->size());
|
auto bin = dev->peek(dev->size());
|
||||||
auto payload = std::string(bin.data(), bin.size());
|
auto payload = std::string(bin.data(), bin.size());
|
||||||
std::optional<mtx::crypto::EncryptedFile> encryptedFile;
|
std::optional<mtx::crypto::EncryptedFile> encryptedFile;
|
||||||
if (cache::client()->isRoomEncrypted(current_room_.toStdString())) {
|
if (cache::isRoomEncrypted(current_room_.toStdString())) {
|
||||||
mtx::crypto::BinaryBuf buf;
|
mtx::crypto::BinaryBuf buf;
|
||||||
std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload);
|
std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload);
|
||||||
payload = mtx::crypto::to_string(buf);
|
payload = mtx::crypto::to_string(buf);
|
||||||
|
@ -408,7 +409,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
this,
|
this,
|
||||||
[](const mtx::responses::Notifications ¬if) {
|
[](const mtx::responses::Notifications ¬if) {
|
||||||
try {
|
try {
|
||||||
cache::client()->saveTimelineMentions(notif);
|
cache::saveTimelineMentions(notif);
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->error("failed to save mentions: {}", e.what());
|
nhlog::db()->error("failed to save mentions: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -457,7 +458,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
&popups::UserMentions::initializeMentions);
|
&popups::UserMentions::initializeMentions);
|
||||||
connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
|
connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
|
||||||
try {
|
try {
|
||||||
room_list_->cleanupInvites(cache::client()->invites());
|
room_list_->cleanupInvites(cache::invites());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->error("failed to retrieve invites: {}", e.what());
|
nhlog::db()->error("failed to retrieve invites: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -575,7 +576,7 @@ ChatPage::deleteConfigs()
|
||||||
settings.remove("");
|
settings.remove("");
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
cache::client()->deleteData();
|
cache::deleteData();
|
||||||
http::client()->clear();
|
http::client()->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,18 +611,18 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
||||||
connect(
|
connect(
|
||||||
cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus);
|
cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus);
|
||||||
|
|
||||||
const bool isInitialized = cache::client()->isInitialized();
|
const bool isInitialized = cache::isInitialized();
|
||||||
const bool isValid = cache::client()->isFormatValid();
|
const bool isValid = cache::isFormatValid();
|
||||||
|
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
cache::client()->setCurrentFormat();
|
cache::setCurrentFormat();
|
||||||
} else if (isInitialized && !isValid) {
|
} else if (isInitialized && !isValid) {
|
||||||
// TODO: Deleting session data but keep using the
|
// TODO: Deleting session data but keep using the
|
||||||
// same device doesn't work.
|
// same device doesn't work.
|
||||||
cache::client()->deleteData();
|
cache::deleteData();
|
||||||
|
|
||||||
cache::init(userid);
|
cache::init(userid);
|
||||||
cache::client()->setCurrentFormat();
|
cache::setCurrentFormat();
|
||||||
} else if (isInitialized) {
|
} else if (isInitialized) {
|
||||||
loadStateFromCache();
|
loadStateFromCache();
|
||||||
return;
|
return;
|
||||||
|
@ -629,7 +630,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
||||||
|
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->critical("failure during boot: {}", e.what());
|
nhlog::db()->critical("failure during boot: {}", e.what());
|
||||||
cache::client()->deleteData();
|
cache::deleteData();
|
||||||
nhlog::net()->info("falling back to initial sync");
|
nhlog::net()->info("falling back to initial sync");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +639,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
||||||
// There isn't a saved olm account to restore.
|
// There isn't a saved olm account to restore.
|
||||||
nhlog::crypto()->info("creating new olm account");
|
nhlog::crypto()->info("creating new olm account");
|
||||||
olm::client()->create_new_account();
|
olm::client()->create_new_account();
|
||||||
cache::client()->saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY));
|
cache::saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::crypto()->critical("failed to save olm account {}", e.what());
|
nhlog::crypto()->critical("failed to save olm account {}", e.what());
|
||||||
emit dropToLoginPageCb(QString::fromStdString(e.what()));
|
emit dropToLoginPageCb(QString::fromStdString(e.what()));
|
||||||
|
@ -671,7 +672,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto room_info = cache::client()->getRoomInfo({room_id.toStdString()});
|
auto room_info = cache::getRoomInfo({room_id.toStdString()});
|
||||||
|
|
||||||
if (room_info.find(room_id) == room_info.end())
|
if (room_info.find(room_id) == room_info.end())
|
||||||
return;
|
return;
|
||||||
|
@ -682,7 +683,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id)
|
||||||
top_bar_->updateRoomName(name);
|
top_bar_->updateRoomName(name);
|
||||||
top_bar_->updateRoomTopic(QString::fromStdString(room_info[room_id].topic));
|
top_bar_->updateRoomTopic(QString::fromStdString(room_info[room_id].topic));
|
||||||
|
|
||||||
auto img = cache::client()->getRoomAvatar(room_id);
|
auto img = cache::getRoomAvatar(room_id);
|
||||||
|
|
||||||
if (img.isNull())
|
if (img.isNull())
|
||||||
top_bar_->updateRoomAvatarFromName(name);
|
top_bar_->updateRoomAvatarFromName(name);
|
||||||
|
@ -719,18 +720,17 @@ ChatPage::loadStateFromCache()
|
||||||
|
|
||||||
QtConcurrent::run([this]() {
|
QtConcurrent::run([this]() {
|
||||||
try {
|
try {
|
||||||
cache::client()->restoreSessions();
|
cache::restoreSessions();
|
||||||
olm::client()->load(cache::client()->restoreOlmAccount(),
|
olm::client()->load(cache::restoreOlmAccount(), STORAGE_SECRET_KEY);
|
||||||
STORAGE_SECRET_KEY);
|
|
||||||
|
|
||||||
cache::client()->populateMembers();
|
cache::populateMembers();
|
||||||
|
|
||||||
emit initializeEmptyViews(cache::client()->roomMessages());
|
emit initializeEmptyViews(cache::roomMessages());
|
||||||
emit initializeRoomList(cache::client()->roomInfo());
|
emit initializeRoomList(cache::roomInfo());
|
||||||
emit initializeMentions(cache::client()->getTimelineMentions());
|
emit initializeMentions(cache::getTimelineMentions());
|
||||||
emit syncTags(cache::client()->roomInfo().toStdMap());
|
emit syncTags(cache::roomInfo().toStdMap());
|
||||||
|
|
||||||
cache::client()->calculateRoomReadStatus();
|
cache::calculateRoomReadStatus();
|
||||||
|
|
||||||
} catch (const mtx::crypto::olm_exception &e) {
|
} catch (const mtx::crypto::olm_exception &e) {
|
||||||
nhlog::crypto()->critical("failed to restore olm account: {}", e.what());
|
nhlog::crypto()->critical("failed to restore olm account: {}", e.what());
|
||||||
|
@ -773,8 +773,8 @@ void
|
||||||
ChatPage::removeRoom(const QString &room_id)
|
ChatPage::removeRoom(const QString &room_id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
cache::client()->removeRoom(room_id);
|
cache::removeRoom(room_id);
|
||||||
cache::client()->removeInvite(room_id.toStdString());
|
cache::removeInvite(room_id.toStdString());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->critical("failure while removing room: {}", e.what());
|
nhlog::db()->critical("failure while removing room: {}", e.what());
|
||||||
// TODO: Notify the user.
|
// TODO: Notify the user.
|
||||||
|
@ -807,7 +807,7 @@ ChatPage::generateTypingUsers(const QString &room_id, const std::vector<std::str
|
||||||
if (remote_user == local_user)
|
if (remote_user == local_user)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
users.append(Cache::displayName(room_id, remote_user));
|
users.append(cache::displayName(room_id, remote_user));
|
||||||
}
|
}
|
||||||
|
|
||||||
users.sort();
|
users.sort();
|
||||||
|
@ -853,16 +853,16 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (item.read) {
|
if (item.read) {
|
||||||
cache::client()->removeReadNotification(event_id);
|
cache::removeReadNotification(event_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache::client()->isNotificationSent(event_id)) {
|
if (!cache::isNotificationSent(event_id)) {
|
||||||
const auto room_id = QString::fromStdString(item.room_id);
|
const auto room_id = QString::fromStdString(item.room_id);
|
||||||
const auto user_id = utils::event_sender(item.event);
|
const auto user_id = utils::event_sender(item.event);
|
||||||
|
|
||||||
// We should only sent one notification per event.
|
// We should only sent one notification per event.
|
||||||
cache::client()->markSentNotification(event_id);
|
cache::markSentNotification(event_id);
|
||||||
|
|
||||||
// Don't send a notification when the current room is opened.
|
// Don't send a notification when the current room is opened.
|
||||||
if (isRoomActive(room_id))
|
if (isRoomActive(room_id))
|
||||||
|
@ -871,11 +871,10 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res)
|
||||||
notificationsManager.postNotification(
|
notificationsManager.postNotification(
|
||||||
room_id,
|
room_id,
|
||||||
QString::fromStdString(event_id),
|
QString::fromStdString(event_id),
|
||||||
QString::fromStdString(
|
QString::fromStdString(cache::singleRoomInfo(item.room_id).name),
|
||||||
cache::client()->singleRoomInfo(item.room_id).name),
|
cache::displayName(room_id, user_id),
|
||||||
Cache::displayName(room_id, user_id),
|
|
||||||
utils::event_body(item.event),
|
utils::event_body(item.event),
|
||||||
cache::client()->getRoomAvatar(room_id));
|
cache::getRoomAvatar(room_id));
|
||||||
}
|
}
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("error while sending desktop notification: {}", e.what());
|
nhlog::db()->warn("error while sending desktop notification: {}", e.what());
|
||||||
|
@ -962,7 +961,7 @@ ChatPage::trySync()
|
||||||
connectivityTimer_.start();
|
connectivityTimer_.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
opts.since = cache::client()->nextBatchToken();
|
opts.since = cache::nextBatchToken();
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->error("failed to retrieve next batch token: {}", e.what());
|
nhlog::db()->error("failed to retrieve next batch token: {}", e.what());
|
||||||
return;
|
return;
|
||||||
|
@ -1015,22 +1014,22 @@ ChatPage::trySync()
|
||||||
|
|
||||||
// TODO: fine grained error handling
|
// TODO: fine grained error handling
|
||||||
try {
|
try {
|
||||||
cache::client()->saveState(res);
|
cache::saveState(res);
|
||||||
olm::handle_to_device_messages(res.to_device);
|
olm::handle_to_device_messages(res.to_device);
|
||||||
|
|
||||||
emit syncUI(res.rooms);
|
emit syncUI(res.rooms);
|
||||||
|
|
||||||
auto updates = cache::client()->roomUpdates(res);
|
auto updates = cache::roomUpdates(res);
|
||||||
|
|
||||||
emit syncTopBar(updates);
|
emit syncTopBar(updates);
|
||||||
emit syncRoomlist(updates);
|
emit syncRoomlist(updates);
|
||||||
|
|
||||||
emit syncTags(cache::client()->roomTagUpdates(res));
|
emit syncTags(cache::roomTagUpdates(res));
|
||||||
|
|
||||||
cache::client()->deleteOldData();
|
cache::deleteOldData();
|
||||||
} catch (const lmdb::map_full_error &e) {
|
} catch (const lmdb::map_full_error &e) {
|
||||||
nhlog::db()->error("lmdb is full: {}", e.what());
|
nhlog::db()->error("lmdb is full: {}", e.what());
|
||||||
cache::client()->deleteOldData();
|
cache::deleteOldData();
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->error("saving sync response: {}", e.what());
|
nhlog::db()->error("saving sync response: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -1058,7 +1057,7 @@ ChatPage::joinRoom(const QString &room)
|
||||||
|
|
||||||
// We remove any invites with the same room_id.
|
// We remove any invites with the same room_id.
|
||||||
try {
|
try {
|
||||||
cache::client()->removeInvite(room_id);
|
cache::removeInvite(room_id);
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
emit showNotification(
|
emit showNotification(
|
||||||
QString("Failed to remove invite: %1").arg(e.what()));
|
QString("Failed to remove invite: %1").arg(e.what()));
|
||||||
|
@ -1156,16 +1155,16 @@ ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::Request
|
||||||
nhlog::net()->info("initial sync completed");
|
nhlog::net()->info("initial sync completed");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cache::client()->saveState(res);
|
cache::saveState(res);
|
||||||
|
|
||||||
olm::handle_to_device_messages(res.to_device);
|
olm::handle_to_device_messages(res.to_device);
|
||||||
|
|
||||||
emit initializeViews(std::move(res.rooms));
|
emit initializeViews(std::move(res.rooms));
|
||||||
emit initializeRoomList(cache::client()->roomInfo());
|
emit initializeRoomList(cache::roomInfo());
|
||||||
emit initializeMentions(cache::client()->getTimelineMentions());
|
emit initializeMentions(cache::getTimelineMentions());
|
||||||
|
|
||||||
cache::client()->calculateRoomReadStatus();
|
cache::calculateRoomReadStatus();
|
||||||
emit syncTags(cache::client()->roomInfo().toStdMap());
|
emit syncTags(cache::roomInfo().toStdMap());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->error("failed to save state after initial sync: {}", e.what());
|
nhlog::db()->error("failed to save state after initial sync: {}", e.what());
|
||||||
startInitialSync();
|
startInitialSync();
|
||||||
|
|
|
@ -215,7 +215,7 @@ CommunitiesList::highlightSelectedCommunity(const QString &community_id)
|
||||||
void
|
void
|
||||||
CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUrl)
|
CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUrl)
|
||||||
{
|
{
|
||||||
auto savedImgData = cache::client()->image(avatarUrl);
|
auto savedImgData = cache::image(avatarUrl);
|
||||||
if (!savedImgData.isNull()) {
|
if (!savedImgData.isNull()) {
|
||||||
QPixmap pix;
|
QPixmap pix;
|
||||||
pix.loadFromData(savedImgData);
|
pix.loadFromData(savedImgData);
|
||||||
|
@ -238,7 +238,7 @@ CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache::client()->saveImage(opts.mxc_url, res);
|
cache::saveImage(opts.mxc_url, res);
|
||||||
|
|
||||||
auto data = QByteArray(res.data(), res.size());
|
auto data = QByteArray(res.data(), res.size());
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
connect(
|
connect(
|
||||||
userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
|
userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
|
||||||
connect(userSettingsPage_, &UserSettingsPage::themeChanged, this, []() {
|
connect(userSettingsPage_, &UserSettingsPage::themeChanged, this, []() {
|
||||||
Cache::clearUserColors();
|
cache::clearUserColors();
|
||||||
});
|
});
|
||||||
connect(
|
connect(
|
||||||
userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged);
|
userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged);
|
||||||
|
@ -444,7 +444,7 @@ MainWindow::openReadReceiptsDialog(const QString &event_id)
|
||||||
const auto room_id = chat_page_->currentRoom();
|
const auto room_id = chat_page_->currentRoom();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dialog->addUsers(cache::client()->readReceipts(event_id, room_id));
|
dialog->addUsers(cache::readReceipts(event_id, room_id));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("failed to retrieve read receipts for {} {}",
|
nhlog::db()->warn("failed to retrieve read receipts for {} {}",
|
||||||
event_id.toStdString(),
|
event_id.toStdString(),
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "MxcImageProvider.h"
|
#include "MxcImageProvider.h"
|
||||||
|
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
#include "MatrixClient.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
MxcImageResponse::run()
|
MxcImageResponse::run()
|
||||||
|
@ -11,7 +13,7 @@ MxcImageResponse::run()
|
||||||
.arg(m_requestedSize.width())
|
.arg(m_requestedSize.width())
|
||||||
.arg(m_requestedSize.height());
|
.arg(m_requestedSize.height());
|
||||||
|
|
||||||
auto data = cache::client()->image(fileName);
|
auto data = cache::image(fileName);
|
||||||
if (!data.isNull() && m_image.loadFromData(data)) {
|
if (!data.isNull() && m_image.loadFromData(data)) {
|
||||||
m_image = m_image.scaled(m_requestedSize, Qt::KeepAspectRatio);
|
m_image = m_image.scaled(m_requestedSize, Qt::KeepAspectRatio);
|
||||||
m_image.setText("mxc url", "mxc://" + m_id);
|
m_image.setText("mxc url", "mxc://" + m_id);
|
||||||
|
@ -36,14 +38,14 @@ MxcImageResponse::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = QByteArray(res.data(), res.size());
|
auto data = QByteArray(res.data(), res.size());
|
||||||
cache::client()->saveImage(fileName, data);
|
cache::saveImage(fileName, data);
|
||||||
m_image.loadFromData(data);
|
m_image.loadFromData(data);
|
||||||
m_image.setText("mxc url", "mxc://" + m_id);
|
m_image.setText("mxc url", "mxc://" + m_id);
|
||||||
|
|
||||||
emit finished();
|
emit finished();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
auto data = cache::client()->image(m_id);
|
auto data = cache::image(m_id);
|
||||||
if (!data.isNull() && m_image.loadFromData(data)) {
|
if (!data.isNull() && m_image.loadFromData(data)) {
|
||||||
m_image.setText("mxc url", "mxc://" + m_id);
|
m_image.setText("mxc url", "mxc://" + m_id);
|
||||||
emit finished();
|
emit finished();
|
||||||
|
@ -75,7 +77,7 @@ MxcImageResponse::run()
|
||||||
m_image.setText("original filename",
|
m_image.setText("original filename",
|
||||||
QString::fromStdString(originalFilename));
|
QString::fromStdString(originalFilename));
|
||||||
m_image.setText("mxc url", "mxc://" + m_id);
|
m_image.setText("mxc url", "mxc://" + m_id);
|
||||||
cache::client()->saveImage(m_id, data);
|
cache::saveImage(m_id, data);
|
||||||
|
|
||||||
emit finished();
|
emit finished();
|
||||||
});
|
});
|
||||||
|
|
27
src/Olm.cpp
27
src/Olm.cpp
|
@ -121,7 +121,7 @@ handle_pre_key_olm_message(const std::string &sender,
|
||||||
|
|
||||||
// We also remove the one time key used to establish that
|
// We also remove the one time key used to establish that
|
||||||
// session so we'll have to update our copy of the account object.
|
// session so we'll have to update our copy of the account object.
|
||||||
cache::client()->saveOlmAccount(olm::client()->save("secret"));
|
cache::saveOlmAccount(olm::client()->save("secret"));
|
||||||
} catch (const mtx::crypto::olm_exception &e) {
|
} catch (const mtx::crypto::olm_exception &e) {
|
||||||
nhlog::crypto()->critical(
|
nhlog::crypto()->critical(
|
||||||
"failed to create inbound session with {}: {}", sender, e.what());
|
"failed to create inbound session with {}: {}", sender, e.what());
|
||||||
|
@ -149,7 +149,7 @@ handle_pre_key_olm_message(const std::string &sender,
|
||||||
nhlog::crypto()->debug("decrypted message: \n {}", plaintext.dump(2));
|
nhlog::crypto()->debug("decrypted message: \n {}", plaintext.dump(2));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cache::client()->saveOlmSession(sender_key, std::move(inbound_session));
|
cache::saveOlmSession(sender_key, std::move(inbound_session));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn(
|
nhlog::db()->warn(
|
||||||
"failed to save inbound olm session from {}: {}", sender, e.what());
|
"failed to save inbound olm session from {}: {}", sender, e.what());
|
||||||
|
@ -166,7 +166,7 @@ encrypt_group_message(const std::string &room_id,
|
||||||
using namespace mtx::events;
|
using namespace mtx::events;
|
||||||
|
|
||||||
// Always chech before for existence.
|
// Always chech before for existence.
|
||||||
auto res = cache::client()->getOutboundMegolmSession(room_id);
|
auto res = cache::getOutboundMegolmSession(room_id);
|
||||||
auto payload = olm::client()->encrypt_group_message(res.session, body);
|
auto payload = olm::client()->encrypt_group_message(res.session, body);
|
||||||
|
|
||||||
// Prepare the m.room.encrypted event.
|
// Prepare the m.room.encrypted event.
|
||||||
|
@ -181,7 +181,7 @@ encrypt_group_message(const std::string &room_id,
|
||||||
nhlog::crypto()->info("next message_index {}", message_index);
|
nhlog::crypto()->info("next message_index {}", message_index);
|
||||||
|
|
||||||
// We need to re-pickle the session after we send a message to save the new message_index.
|
// We need to re-pickle the session after we send a message to save the new message_index.
|
||||||
cache::client()->updateOutboundMegolmSession(room_id, message_index);
|
cache::updateOutboundMegolmSession(room_id, message_index);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -189,13 +189,13 @@ encrypt_group_message(const std::string &room_id,
|
||||||
nlohmann::json
|
nlohmann::json
|
||||||
try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCipherContent &msg)
|
try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCipherContent &msg)
|
||||||
{
|
{
|
||||||
auto session_ids = cache::client()->getOlmSessions(sender_key);
|
auto session_ids = cache::getOlmSessions(sender_key);
|
||||||
|
|
||||||
nhlog::crypto()->info("attempt to decrypt message with {} known session_ids",
|
nhlog::crypto()->info("attempt to decrypt message with {} known session_ids",
|
||||||
session_ids.size());
|
session_ids.size());
|
||||||
|
|
||||||
for (const auto &id : session_ids) {
|
for (const auto &id : session_ids) {
|
||||||
auto session = cache::client()->getOlmSession(sender_key, id);
|
auto session = cache::getOlmSession(sender_key, id);
|
||||||
|
|
||||||
if (!session)
|
if (!session)
|
||||||
continue;
|
continue;
|
||||||
|
@ -204,7 +204,7 @@ try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCip
|
||||||
|
|
||||||
try {
|
try {
|
||||||
text = olm::client()->decrypt_message(session->get(), msg.type, msg.body);
|
text = olm::client()->decrypt_message(session->get(), msg.type, msg.body);
|
||||||
cache::client()->saveOlmSession(id, std::move(session.value()));
|
cache::saveOlmSession(id, std::move(session.value()));
|
||||||
} catch (const mtx::crypto::olm_exception &e) {
|
} catch (const mtx::crypto::olm_exception &e) {
|
||||||
nhlog::crypto()->debug("failed to decrypt olm message ({}, {}) with {}: {}",
|
nhlog::crypto()->debug("failed to decrypt olm message ({}, {}) with {}: {}",
|
||||||
msg.type,
|
msg.type,
|
||||||
|
@ -252,7 +252,7 @@ create_inbound_megolm_session(const std::string &sender,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto megolm_session = olm::client()->init_inbound_group_session(session_key);
|
auto megolm_session = olm::client()->init_inbound_group_session(session_key);
|
||||||
cache::client()->saveInboundMegolmSession(index, std::move(megolm_session));
|
cache::saveInboundMegolmSession(index, std::move(megolm_session));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
|
nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
|
||||||
return;
|
return;
|
||||||
|
@ -268,7 +268,7 @@ void
|
||||||
mark_keys_as_published()
|
mark_keys_as_published()
|
||||||
{
|
{
|
||||||
olm::client()->mark_keys_as_published();
|
olm::client()->mark_keys_as_published();
|
||||||
cache::client()->saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY));
|
cache::saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -355,13 +355,13 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have the keys for the requested session.
|
// Check if we have the keys for the requested session.
|
||||||
if (!cache::client()->outboundMegolmSessionExists(req.room_id)) {
|
if (!cache::outboundMegolmSessionExists(req.room_id)) {
|
||||||
nhlog::crypto()->warn("requested session not found in room: {}", req.room_id);
|
nhlog::crypto()->warn("requested session not found in room: {}", req.room_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the requested session_id and the one we have saved match.
|
// Check that the requested session_id and the one we have saved match.
|
||||||
const auto session = cache::client()->getOutboundMegolmSession(req.room_id);
|
const auto session = cache::getOutboundMegolmSession(req.room_id);
|
||||||
if (req.session_id != session.data.session_id) {
|
if (req.session_id != session.data.session_id) {
|
||||||
nhlog::crypto()->warn("session id of retrieved session doesn't match the request: "
|
nhlog::crypto()->warn("session id of retrieved session doesn't match the request: "
|
||||||
"requested({}), ours({})",
|
"requested({}), ours({})",
|
||||||
|
@ -370,7 +370,7 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache::client()->isRoomMember(req.sender, req.room_id)) {
|
if (!cache::isRoomMember(req.sender, req.room_id)) {
|
||||||
nhlog::crypto()->warn(
|
nhlog::crypto()->warn(
|
||||||
"user {} that requested the session key is not member of the room {}",
|
"user {} that requested the session key is not member of the room {}",
|
||||||
req.sender,
|
req.sender,
|
||||||
|
@ -509,8 +509,7 @@ send_megolm_key_to_device(const std::string &user_id,
|
||||||
device_msg = olm::client()->create_olm_encrypted_content(
|
device_msg = olm::client()->create_olm_encrypted_content(
|
||||||
olm_session.get(), room_key, pks.curve25519);
|
olm_session.get(), room_key, pks.curve25519);
|
||||||
|
|
||||||
cache::client()->saveOlmSession(pks.curve25519,
|
cache::saveOlmSession(pks.curve25519, std::move(olm_session));
|
||||||
std::move(olm_session));
|
|
||||||
} catch (const json::exception &e) {
|
} catch (const json::exception &e) {
|
||||||
nhlog::crypto()->warn("creating outbound session: {}",
|
nhlog::crypto()->warn("creating outbound session: {}",
|
||||||
e.what());
|
e.what());
|
||||||
|
|
|
@ -93,8 +93,7 @@ QuickSwitcher::QuickSwitcher(QWidget *parent)
|
||||||
|
|
||||||
QtConcurrent::run([this, query = query.toLower()]() {
|
QtConcurrent::run([this, query = query.toLower()]() {
|
||||||
try {
|
try {
|
||||||
emit queryResults(
|
emit queryResults(cache::searchRooms(query.toStdString()));
|
||||||
cache::client()->searchRooms(query.toStdString()));
|
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
qWarning() << "room search failed:" << e.what();
|
qWarning() << "room search failed:" << e.what();
|
||||||
}
|
}
|
||||||
|
|
|
@ -529,12 +529,12 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
||||||
emit heightChanged(widgetHeight);
|
emit heightChanged(widgetHeight);
|
||||||
});
|
});
|
||||||
connect(input_, &FilteredTextEdit::showSuggestions, this, [this](const QString &q) {
|
connect(input_, &FilteredTextEdit::showSuggestions, this, [this](const QString &q) {
|
||||||
if (q.isEmpty() || !cache::client())
|
if (q.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QtConcurrent::run([this, q = q.toLower().toStdString()]() {
|
QtConcurrent::run([this, q = q.toLower().toStdString()]() {
|
||||||
try {
|
try {
|
||||||
emit input_->resultsRetrieved(cache::client()->searchUsers(
|
emit input_->resultsRetrieved(cache::searchUsers(
|
||||||
ChatPage::instance()->currentRoom().toStdString(), q));
|
ChatPage::instance()->currentRoom().toStdString(), q));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
std::cout << e.what() << '\n';
|
std::cout << e.what() << '\n';
|
||||||
|
|
|
@ -555,7 +555,7 @@ UserSettingsPage::importSessionKeys()
|
||||||
try {
|
try {
|
||||||
auto sessions =
|
auto sessions =
|
||||||
mtx::crypto::decrypt_exported_sessions(payload, password.toStdString());
|
mtx::crypto::decrypt_exported_sessions(payload, password.toStdString());
|
||||||
cache::client()->importSessionKeys(std::move(sessions));
|
cache::importSessionKeys(std::move(sessions));
|
||||||
} catch (const mtx::crypto::sodium_exception &e) {
|
} catch (const mtx::crypto::sodium_exception &e) {
|
||||||
QMessageBox::warning(this, tr("Error"), e.what());
|
QMessageBox::warning(this, tr("Error"), e.what());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
|
@ -597,7 +597,7 @@ UserSettingsPage::exportSessionKeys()
|
||||||
// Export sessions & save to file.
|
// Export sessions & save to file.
|
||||||
try {
|
try {
|
||||||
auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(
|
auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(
|
||||||
cache::client()->exportSessionKeys(), password.toStdString());
|
cache::exportSessionKeys(), password.toStdString());
|
||||||
|
|
||||||
QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob));
|
QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob));
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ utils::getMessageDescription(const TimelineEvent &event,
|
||||||
} else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) {
|
} else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) {
|
||||||
const auto sender = QString::fromStdString(msg->sender);
|
const auto sender = QString::fromStdString(msg->sender);
|
||||||
|
|
||||||
const auto username = Cache::displayName(room_id, sender);
|
const auto username = cache::displayName(room_id, sender);
|
||||||
const auto ts = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts);
|
const auto ts = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts);
|
||||||
|
|
||||||
DescInfo info;
|
DescInfo info;
|
||||||
|
|
|
@ -168,7 +168,7 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin
|
||||||
const auto msg = std::get<T>(event);
|
const auto msg = std::get<T>(event);
|
||||||
const auto sender = QString::fromStdString(msg.sender);
|
const auto sender = QString::fromStdString(msg.sender);
|
||||||
|
|
||||||
const auto username = Cache::displayName(room_id, sender);
|
const auto username = cache::displayName(room_id, sender);
|
||||||
const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
|
const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
|
||||||
|
|
||||||
return DescInfo{QString::fromStdString(msg.event_id),
|
return DescInfo{QString::fromStdString(msg.event_id),
|
||||||
|
|
|
@ -110,11 +110,11 @@ MemberList::MemberList(const QString &room_id, QWidget *parent)
|
||||||
const size_t numMembers = list_->count() - 1;
|
const size_t numMembers = list_->count() - 1;
|
||||||
|
|
||||||
if (numMembers > 0)
|
if (numMembers > 0)
|
||||||
addUsers(cache::client()->getMembers(room_id_.toStdString(), numMembers));
|
addUsers(cache::getMembers(room_id_.toStdString(), numMembers));
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
addUsers(cache::client()->getMembers(room_id_.toStdString()));
|
addUsers(cache::getMembers(room_id_.toStdString()));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
qCritical() << e.what();
|
qCritical() << e.what();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ ReceiptItem::ReceiptItem(QWidget *parent,
|
||||||
QFont nameFont;
|
QFont nameFont;
|
||||||
nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1);
|
nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1);
|
||||||
|
|
||||||
auto displayName = Cache::displayName(room_id, user_id);
|
auto displayName = cache::displayName(room_id, user_id);
|
||||||
|
|
||||||
avatar_ = new Avatar(this, 44);
|
avatar_ = new Avatar(this, 44);
|
||||||
avatar_->setLetter(utils::firstChar(displayName));
|
avatar_->setLetter(utils::firstChar(displayName));
|
||||||
|
|
|
@ -485,8 +485,8 @@ void
|
||||||
RoomSettings::retrieveRoomInfo()
|
RoomSettings::retrieveRoomInfo()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
usesEncryption_ = cache::client()->isRoomEncrypted(room_id_.toStdString());
|
usesEncryption_ = cache::isRoomEncrypted(room_id_.toStdString());
|
||||||
info_ = cache::client()->singleRoomInfo(room_id_.toStdString());
|
info_ = cache::singleRoomInfo(room_id_.toStdString());
|
||||||
setAvatar();
|
setAvatar();
|
||||||
} catch (const lmdb::error &) {
|
} catch (const lmdb::error &) {
|
||||||
nhlog::db()->warn("failed to retrieve room info from cache: {}",
|
nhlog::db()->warn("failed to retrieve room info from cache: {}",
|
||||||
|
@ -529,8 +529,7 @@ bool
|
||||||
RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const
|
RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return cache::client()->hasEnoughPowerLevel(
|
return cache::hasEnoughPowerLevel({EventType::RoomJoinRules}, room_id, user_id);
|
||||||
{EventType::RoomJoinRules}, room_id, user_id);
|
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("lmdb error: {}", e.what());
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -542,7 +541,7 @@ bool
|
||||||
RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const
|
RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return cache::client()->hasEnoughPowerLevel(
|
return cache::hasEnoughPowerLevel(
|
||||||
{EventType::RoomName, EventType::RoomTopic}, room_id, user_id);
|
{EventType::RoomName, EventType::RoomTopic}, room_id, user_id);
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("lmdb error: {}", e.what());
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
|
@ -555,8 +554,7 @@ bool
|
||||||
RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &user_id) const
|
RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &user_id) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return cache::client()->hasEnoughPowerLevel(
|
return cache::hasEnoughPowerLevel({EventType::RoomAvatar}, room_id, user_id);
|
||||||
{EventType::RoomAvatar}, room_id, user_id);
|
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("lmdb error: {}", e.what());
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
#include "Cache.h"
|
#include <mtx/events/guest_access.hpp>
|
||||||
|
|
||||||
|
#include "CacheStructs.h"
|
||||||
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
class FlatButton;
|
class FlatButton;
|
||||||
|
|
|
@ -203,7 +203,7 @@ UserProfile::init(const QString &userId, const QString &roomId)
|
||||||
{
|
{
|
||||||
resetToDefaults();
|
resetToDefaults();
|
||||||
|
|
||||||
auto displayName = Cache::displayName(roomId, userId);
|
auto displayName = cache::displayName(roomId, userId);
|
||||||
|
|
||||||
userIdLabel_->setText(userId);
|
userIdLabel_->setText(userId);
|
||||||
displayNameLabel_->setText(displayName);
|
displayNameLabel_->setText(displayName);
|
||||||
|
@ -215,7 +215,7 @@ UserProfile::init(const QString &userId, const QString &roomId)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool hasMemberRights =
|
bool hasMemberRights =
|
||||||
cache::client()->hasEnoughPowerLevel({mtx::events::EventType::RoomMember},
|
cache::hasEnoughPowerLevel({mtx::events::EventType::RoomMember},
|
||||||
roomId.toStdString(),
|
roomId.toStdString(),
|
||||||
localUser.toStdString());
|
localUser.toStdString());
|
||||||
if (!hasMemberRights) {
|
if (!hasMemberRights) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ UserItem::UserItem(QWidget *parent, const QString &user_id)
|
||||||
: PopupItem(parent)
|
: PopupItem(parent)
|
||||||
, userId_{user_id}
|
, userId_{user_id}
|
||||||
{
|
{
|
||||||
auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_);
|
auto displayName = cache::displayName(ChatPage::instance()->currentRoom(), userId_);
|
||||||
|
|
||||||
avatar_->setLetter(utils::firstChar(displayName));
|
avatar_->setLetter(utils::firstChar(displayName));
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ UserItem::updateItem(const QString &user_id)
|
||||||
{
|
{
|
||||||
userId_ = user_id;
|
userId_ = user_id;
|
||||||
|
|
||||||
auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_);
|
auto displayName = cache::displayName(ChatPage::instance()->currentRoom(), userId_);
|
||||||
|
|
||||||
// If it's a matrix id we use the second letter.
|
// If it's a matrix id we use the second letter.
|
||||||
if (displayName.size() > 1 && displayName.at(0) == '@')
|
if (displayName.size() > 1 && displayName.at(0) == '@')
|
||||||
|
@ -93,7 +93,7 @@ UserItem::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->buttons() != Qt::RightButton)
|
if (event->buttons() != Qt::RightButton)
|
||||||
emit clicked(
|
emit clicked(
|
||||||
Cache::displayName(ChatPage::instance()->currentRoom(), selectedText()));
|
cache::displayName(ChatPage::instance()->currentRoom(), selectedText()));
|
||||||
|
|
||||||
QWidget::mousePressEvent(event);
|
QWidget::mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "../AvatarProvider.h"
|
#include "../AvatarProvider.h"
|
||||||
#include "../Cache.h"
|
|
||||||
#include "../ChatPage.h"
|
#include "../ChatPage.h"
|
||||||
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../ui/Avatar.h"
|
#include "../ui/Avatar.h"
|
||||||
#include "../ui/DropShadow.h"
|
#include "../ui/DropShadow.h"
|
||||||
#include "../ui/TextLabel.h"
|
#include "../ui/TextLabel.h"
|
||||||
|
#include "PopupItem.h"
|
||||||
#include "ReplyPopup.h"
|
#include "ReplyPopup.h"
|
||||||
|
|
||||||
ReplyPopup::ReplyPopup(QWidget *parent)
|
ReplyPopup::ReplyPopup(QWidget *parent)
|
||||||
|
|
|
@ -2,17 +2,14 @@
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPoint>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "../AvatarProvider.h"
|
|
||||||
#include "../Cache.h"
|
|
||||||
#include "../ChatPage.h"
|
|
||||||
#include "../Utils.h"
|
|
||||||
#include "../ui/FlatButton.h"
|
#include "../ui/FlatButton.h"
|
||||||
#include "../ui/TextLabel.h"
|
#include "../ui/TextLabel.h"
|
||||||
#include "PopupItem.h"
|
|
||||||
|
struct RelatedInfo;
|
||||||
|
class UserItem;
|
||||||
|
|
||||||
class ReplyPopup : public QWidget
|
class ReplyPopup : public QWidget
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "../AvatarProvider.h"
|
#include "CacheStructs.h"
|
||||||
#include "../Cache.h"
|
#include "ChatPage.h"
|
||||||
#include "../ChatPage.h"
|
|
||||||
#include "PopupItem.h"
|
#include "PopupItem.h"
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QVector<SearchResult>)
|
Q_DECLARE_METATYPE(QVector<SearchResult>)
|
||||||
|
@ -28,7 +27,7 @@ public:
|
||||||
|
|
||||||
const auto &widget = qobject_cast<Item *>(item->widget());
|
const auto &widget = qobject_cast<Item *>(item->widget());
|
||||||
emit itemSelected(
|
emit itemSelected(
|
||||||
Cache::displayName(ChatPage::instance()->currentRoom(), widget->selectedText()));
|
cache::displayName(ChatPage::instance()->currentRoom(), widget->selectedText()));
|
||||||
|
|
||||||
resetSelection();
|
resetSelection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ UserMentions::showPopup()
|
||||||
delete widget;
|
delete widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto notifs = cache::client()->getTimelineMentions();
|
auto notifs = cache::getTimelineMentions();
|
||||||
|
|
||||||
initializeMentions(notifs);
|
initializeMentions(notifs);
|
||||||
show();
|
show();
|
||||||
|
|
|
@ -422,7 +422,7 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
|
||||||
readEvent(event_id.toStdString());
|
readEvent(event_id.toStdString());
|
||||||
|
|
||||||
// ask to be notified for read receipts
|
// ask to be notified for read receipts
|
||||||
cache::client()->addPendingReceipt(room_id_, event_id);
|
cache::addPendingReceipt(room_id_, event_id);
|
||||||
|
|
||||||
isProcessingPending = false;
|
isProcessingPending = false;
|
||||||
emit dataChanged(index(idx, 0), index(idx, 0));
|
emit dataChanged(index(idx, 0), index(idx, 0));
|
||||||
|
@ -575,8 +575,7 @@ TimelineModel::data(const QModelIndex &index, int role) const
|
||||||
return qml_mtx_events::Failed;
|
return qml_mtx_events::Failed;
|
||||||
else if (pending.contains(id))
|
else if (pending.contains(id))
|
||||||
return qml_mtx_events::Sent;
|
return qml_mtx_events::Sent;
|
||||||
else if (read.contains(id) ||
|
else if (read.contains(id) || cache::readReceipts(id, room_id_).size() > 1)
|
||||||
cache::client()->readReceipts(id, room_id_).size() > 1)
|
|
||||||
return qml_mtx_events::Read;
|
return qml_mtx_events::Read;
|
||||||
else
|
else
|
||||||
return qml_mtx_events::Received;
|
return qml_mtx_events::Received;
|
||||||
|
@ -805,13 +804,13 @@ TimelineModel::userColor(QString id, QColor background)
|
||||||
QString
|
QString
|
||||||
TimelineModel::displayName(QString id) const
|
TimelineModel::displayName(QString id) const
|
||||||
{
|
{
|
||||||
return Cache::displayName(room_id_, id);
|
return cache::displayName(room_id_, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::avatarUrl(QString id) const
|
TimelineModel::avatarUrl(QString id) const
|
||||||
{
|
{
|
||||||
return Cache::avatarUrl(room_id_, id);
|
return cache::avatarUrl(room_id_, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
|
@ -868,7 +867,7 @@ TimelineModel::decryptEvent(const mtx::events::EncryptedEvent<mtx::events::msg::
|
||||||
.toStdString();
|
.toStdString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!cache::client()->inboundMegolmSessionExists(index)) {
|
if (!cache::inboundMegolmSessionExists(index)) {
|
||||||
nhlog::crypto()->info("Could not find inbound megolm session ({}, {}, {})",
|
nhlog::crypto()->info("Could not find inbound megolm session ({}, {}, {})",
|
||||||
index.room_id,
|
index.room_id,
|
||||||
index.session_id,
|
index.session_id,
|
||||||
|
@ -887,7 +886,7 @@ TimelineModel::decryptEvent(const mtx::events::EncryptedEvent<mtx::events::msg::
|
||||||
|
|
||||||
std::string msg_str;
|
std::string msg_str;
|
||||||
try {
|
try {
|
||||||
auto session = cache::client()->getInboundMegolmSession(index);
|
auto session = cache::getInboundMegolmSession(index);
|
||||||
auto res = olm::client()->decrypt_group_message(session, e.content.ciphertext);
|
auto res = olm::client()->decrypt_group_message(session, e.content.ciphertext);
|
||||||
msg_str = std::string((char *)res.data.data(), res.data.size());
|
msg_str = std::string((char *)res.data.data(), res.data.size());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
|
@ -1044,7 +1043,7 @@ TimelineModel::sendEncryptedMessage(const std::string &txn_id, nlohmann::json co
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if we have already an outbound megolm session then we can use.
|
// Check if we have already an outbound megolm session then we can use.
|
||||||
if (cache::client()->outboundMegolmSessionExists(room_id)) {
|
if (cache::outboundMegolmSessionExists(room_id)) {
|
||||||
auto data = olm::encrypt_group_message(
|
auto data = olm::encrypt_group_message(
|
||||||
room_id, http::client()->device_id(), doc.dump());
|
room_id, http::client()->device_id(), doc.dump());
|
||||||
|
|
||||||
|
@ -1089,10 +1088,10 @@ TimelineModel::sendEncryptedMessage(const std::string &txn_id, nlohmann::json co
|
||||||
session_data.session_id = session_id;
|
session_data.session_id = session_id;
|
||||||
session_data.session_key = session_key;
|
session_data.session_key = session_key;
|
||||||
session_data.message_index = 0; // TODO Update me
|
session_data.message_index = 0; // TODO Update me
|
||||||
cache::client()->saveOutboundMegolmSession(
|
cache::saveOutboundMegolmSession(
|
||||||
room_id, session_data, std::move(outbound_session));
|
room_id, session_data, std::move(outbound_session));
|
||||||
|
|
||||||
const auto members = cache::client()->roomMembers(room_id);
|
const auto members = cache::roomMembers(room_id);
|
||||||
nhlog::ui()->info("retrieved {} members for {}", members.size(), room_id);
|
nhlog::ui()->info("retrieved {} members for {}", members.size(), room_id);
|
||||||
|
|
||||||
auto keeper =
|
auto keeper =
|
||||||
|
@ -1311,7 +1310,7 @@ TimelineModel::handleClaimedKeys(std::shared_ptr<StateKeeper> keeper,
|
||||||
s.get(), room_keys.at(device_id), pks.at(device_id).curve25519);
|
s.get(), room_keys.at(device_id), pks.at(device_id).curve25519);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cache::client()->saveOlmSession(id_key, std::move(s));
|
cache::saveOlmSession(id_key, std::move(s));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->critical("failed to save outbound olm session: {}", e.what());
|
nhlog::db()->critical("failed to save outbound olm session: {}", e.what());
|
||||||
} catch (const mtx::crypto::olm_exception &e) {
|
} catch (const mtx::crypto::olm_exception &e) {
|
||||||
|
@ -1353,7 +1352,7 @@ struct SendMessageVisitor
|
||||||
void operator()(const mtx::events::RoomEvent<T> &msg)
|
void operator()(const mtx::events::RoomEvent<T> &msg)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (cache::client()->isRoomEncrypted(model_->room_id_.toStdString())) {
|
if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
|
||||||
model_->sendEncryptedMessage(txn_id_qstr_.toStdString(),
|
model_->sendEncryptedMessage(txn_id_qstr_.toStdString(),
|
||||||
nlohmann::json(msg.content));
|
nlohmann::json(msg.content));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue