mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
feat(history): Save/load system messages to history
This commit is contained in:
parent
916834fb9c
commit
18109b2f7f
|
@ -214,7 +214,10 @@ std::vector<IChatLog::DateChatLogIdxPair> ChatHistory::getDateIdxs(const QDate&
|
||||||
|
|
||||||
void ChatHistory::addSystemMessage(const SystemMessage& message)
|
void ChatHistory::addSystemMessage(const SystemMessage& message)
|
||||||
{
|
{
|
||||||
// FIXME: #6221 Insert into history
|
if (canUseHistory()) {
|
||||||
|
history->addNewSystemMessage(f.getPublicKey(), message);
|
||||||
|
}
|
||||||
|
|
||||||
sessionChatLog.addSystemMessage(message);
|
sessionChatLog.addSystemMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +413,11 @@ void ChatHistory::loadHistoryIntoSessionChatLog(ChatLogIdx start) const
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case HistMessageContentType::system: {
|
||||||
|
const auto& systemMessage = message.content.asSystemMessage();
|
||||||
|
sessionChatLog.insertSystemMessageAtIdx(currentIdx, systemMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ public slots:
|
||||||
void onFileTransferRemotePausedUnpaused(const ToxPk& sender, const ToxFile& file, bool paused);
|
void onFileTransferRemotePausedUnpaused(const ToxPk& sender, const ToxFile& file, bool paused);
|
||||||
void onFileTransferBrokenUnbroken(const ToxPk& sender, const ToxFile& file, bool broken);
|
void onFileTransferBrokenUnbroken(const ToxPk& sender, const ToxFile& file, bool broken);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString resolveSenderNameFromSender(const ToxPk &sender);
|
QString resolveSenderNameFromSender(const ToxPk &sender);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "src/core/toxpk.h"
|
#include "src/core/toxpk.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static constexpr int SCHEMA_VERSION = 7;
|
static constexpr int SCHEMA_VERSION = 8;
|
||||||
|
|
||||||
bool createCurrentSchema(RawDatabase& db)
|
bool createCurrentSchema(RawDatabase& db)
|
||||||
{
|
{
|
||||||
|
@ -395,6 +395,19 @@ bool dbSchema6to7(RawDatabase& db)
|
||||||
return db.execNow(upgradeQueries);
|
return db.execNow(upgradeQueries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dbSchema7to8(RawDatabase& db)
|
||||||
|
{
|
||||||
|
// Dummy upgrade. This upgrade does not change the schema, however on
|
||||||
|
// version 7 if qtox saw a system message it would assert and crash. This
|
||||||
|
// upgrade ensures that old versions of qtox do not try to load the new
|
||||||
|
// database
|
||||||
|
|
||||||
|
QVector<RawDatabase::Query> upgradeQueries;
|
||||||
|
upgradeQueries += RawDatabase::Query(QStringLiteral("PRAGMA user_version = 8;"));
|
||||||
|
|
||||||
|
return db.execNow(upgradeQueries);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Upgrade the db schema
|
* @brief Upgrade the db schema
|
||||||
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION
|
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION
|
||||||
|
@ -444,7 +457,7 @@ bool dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
||||||
using DbSchemaUpgradeFn = bool (*)(RawDatabase&);
|
using DbSchemaUpgradeFn = bool (*)(RawDatabase&);
|
||||||
std::vector<DbSchemaUpgradeFn> upgradeFns = {dbSchema0to1, dbSchema1to2, dbSchema2to3,
|
std::vector<DbSchemaUpgradeFn> upgradeFns = {dbSchema0to1, dbSchema1to2, dbSchema2to3,
|
||||||
dbSchema3to4, dbSchema4to5, dbSchema5to6,
|
dbSchema3to4, dbSchema4to5, dbSchema5to6,
|
||||||
dbSchema6to7};
|
dbSchema6to7, dbSchema7to8};
|
||||||
|
|
||||||
assert(databaseSchemaVersion < static_cast<int>(upgradeFns.size()));
|
assert(databaseSchemaVersion < static_cast<int>(upgradeFns.size()));
|
||||||
assert(upgradeFns.size() == SCHEMA_VERSION);
|
assert(upgradeFns.size() == SCHEMA_VERSION);
|
||||||
|
@ -550,7 +563,26 @@ generateNewTextMessageQueries(const ToxPk& friendPk, const QString& message, con
|
||||||
return queries;
|
return queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<RawDatabase::Query> generateNewSystemMessageQueries(const ToxPk& friendPk,
|
||||||
|
const SystemMessage& systemMessage)
|
||||||
|
{
|
||||||
|
QVector<RawDatabase::Query> queries;
|
||||||
|
|
||||||
|
queries += generateEnsurePkInPeers(friendPk);
|
||||||
|
queries += generateHistoryTableInsertion('S', systemMessage.timestamp, friendPk);
|
||||||
|
|
||||||
|
QVector<QByteArray> blobs;
|
||||||
|
std::transform(systemMessage.args.begin(), systemMessage.args.end(), std::back_inserter(blobs),
|
||||||
|
[](const QString& s) { return s.toUtf8(); });
|
||||||
|
|
||||||
|
queries += RawDatabase::Query(QString("INSERT INTO system_messages (id, message_type, "
|
||||||
|
"system_message_type, arg1, arg2, arg3, arg4)"
|
||||||
|
"VALUES (last_insert_rowid(), 'S', %1, ?, ?, ?, ?)")
|
||||||
|
.arg(static_cast<int>(systemMessage.messageType)),
|
||||||
|
blobs);
|
||||||
|
|
||||||
|
return queries;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -756,6 +788,7 @@ History::generateNewFileTransferQueries(const ToxPk& friendPk, const ToxPk& send
|
||||||
|
|
||||||
return queries;
|
return queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawDatabase::Query History::generateFileFinished(RowId id, bool success, const QString& filePath,
|
RawDatabase::Query History::generateFileFinished(RowId id, bool success, const QString& filePath,
|
||||||
const QByteArray& fileHash)
|
const QByteArray& fileHash)
|
||||||
{
|
{
|
||||||
|
@ -818,6 +851,16 @@ void History::addNewFileMessage(const ToxPk& friendPk, const QString& fileId,
|
||||||
db->execLater(queries);
|
db->execLater(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void History::addNewSystemMessage(const ToxPk& friendPk, const SystemMessage& systemMessage)
|
||||||
|
{
|
||||||
|
if (historyAccessBlocked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto queries = generateNewSystemMessageQueries(friendPk, systemMessage);
|
||||||
|
|
||||||
|
db->execLater(queries);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Saves a chat message in the database.
|
* @brief Saves a chat message in the database.
|
||||||
* @param friendPk Friend publick key to save.
|
* @param friendPk Friend publick key to save.
|
||||||
|
@ -983,8 +1026,18 @@ QList<History::HistMessage> History::getMessagesForFriend(const ToxPk& friendPk,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
case 'S':
|
case 'S':
|
||||||
// System messages not yet supported
|
it = std::next(row.begin(), systemOffset);
|
||||||
assert(false);
|
assert(!it->isNull());
|
||||||
|
SystemMessage systemMessage;
|
||||||
|
systemMessage.messageType = static_cast<SystemMessageType>((*it++).toLongLong());
|
||||||
|
|
||||||
|
auto argEnd = std::next(it, systemMessage.args.size());
|
||||||
|
std::transform(it, argEnd, systemMessage.args.begin(), [](const QVariant& arg) {
|
||||||
|
return QString::fromUtf8(arg.toByteArray().replace('\0', ""));
|
||||||
|
});
|
||||||
|
it = argEnd;
|
||||||
|
|
||||||
|
messages += HistMessage(id, timestamp, friendPk.toString(), systemMessage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,10 +28,11 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <tox/toxencryptsave.h>
|
#include <tox/toxencryptsave.h>
|
||||||
|
|
||||||
|
#include "src/core/extension.h"
|
||||||
#include "src/core/toxfile.h"
|
#include "src/core/toxfile.h"
|
||||||
#include "src/core/toxpk.h"
|
#include "src/core/toxpk.h"
|
||||||
#include "src/core/extension.h"
|
|
||||||
#include "src/model/brokenmessagereason.h"
|
#include "src/model/brokenmessagereason.h"
|
||||||
|
#include "src/model/systemmessage.h"
|
||||||
#include "src/persistence/db/rawdatabase.h"
|
#include "src/persistence/db/rawdatabase.h"
|
||||||
#include "src/widget/searchtypes.h"
|
#include "src/widget/searchtypes.h"
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ class HistoryKeeper;
|
||||||
enum class HistMessageContentType
|
enum class HistMessageContentType
|
||||||
{
|
{
|
||||||
message,
|
message,
|
||||||
file
|
file,
|
||||||
|
system,
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistMessageContent
|
class HistMessageContent
|
||||||
|
@ -57,6 +59,11 @@ public:
|
||||||
, type(HistMessageContentType::file)
|
, type(HistMessageContentType::file)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
HistMessageContent(SystemMessage systemMessage)
|
||||||
|
: data(std::make_shared<SystemMessage>(std::move(systemMessage)))
|
||||||
|
, type(HistMessageContentType::system)
|
||||||
|
{}
|
||||||
|
|
||||||
HistMessageContentType getType() const
|
HistMessageContentType getType() const
|
||||||
{
|
{
|
||||||
return type;
|
return type;
|
||||||
|
@ -74,6 +81,12 @@ public:
|
||||||
return *static_cast<ToxFile*>(data.get());
|
return *static_cast<ToxFile*>(data.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemMessage& asSystemMessage()
|
||||||
|
{
|
||||||
|
assert(type == HistMessageContentType::system);
|
||||||
|
return *static_cast<SystemMessage*>(data.get());
|
||||||
|
}
|
||||||
|
|
||||||
const QString& asMessage() const
|
const QString& asMessage() const
|
||||||
{
|
{
|
||||||
assert(type == HistMessageContentType::message);
|
assert(type == HistMessageContentType::message);
|
||||||
|
@ -86,6 +99,12 @@ public:
|
||||||
return *static_cast<ToxFile*>(data.get());
|
return *static_cast<ToxFile*>(data.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SystemMessage& asSystemMessage() const
|
||||||
|
{
|
||||||
|
assert(type == HistMessageContentType::system);
|
||||||
|
return *static_cast<SystemMessage*>(data.get());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Not really shared but shared_ptr has support for shared_ptr<void>
|
// Not really shared but shared_ptr has support for shared_ptr<void>
|
||||||
std::shared_ptr<void> data;
|
std::shared_ptr<void> data;
|
||||||
|
@ -142,6 +161,13 @@ public:
|
||||||
, content(std::move(file))
|
, content(std::move(file))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
HistMessage(RowId id, QDateTime timestamp, QString chat, SystemMessage systemMessage)
|
||||||
|
: chat{chat}
|
||||||
|
, timestamp{timestamp}
|
||||||
|
, id{id}
|
||||||
|
, state(MessageState::complete)
|
||||||
|
, content(std::move(systemMessage))
|
||||||
|
{}
|
||||||
|
|
||||||
QString chat;
|
QString chat;
|
||||||
QString sender;
|
QString sender;
|
||||||
|
@ -177,6 +203,8 @@ public:
|
||||||
const QString& fileName, const QString& filePath, int64_t size,
|
const QString& fileName, const QString& filePath, int64_t size,
|
||||||
const ToxPk& sender, const QDateTime& time, QString const& dispName);
|
const ToxPk& sender, const QDateTime& time, QString const& dispName);
|
||||||
|
|
||||||
|
void addNewSystemMessage(const ToxPk& friendPk, const SystemMessage& systemMessage);
|
||||||
|
|
||||||
void setFileFinished(const QString& fileId, bool success, const QString& filePath, const QByteArray& fileHash);
|
void setFileFinished(const QString& fileId, bool success, const QString& filePath, const QByteArray& fileHash);
|
||||||
size_t getNumMessagesForFriend(const ToxPk& friendPk);
|
size_t getNumMessagesForFriend(const ToxPk& friendPk);
|
||||||
size_t getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const QDateTime& date);
|
size_t getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const QDateTime& date);
|
||||||
|
|
|
@ -53,6 +53,8 @@ private slots:
|
||||||
void test4to5();
|
void test4to5();
|
||||||
void test5to6();
|
void test5to6();
|
||||||
void test6to7();
|
void test6to7();
|
||||||
|
// test7to8 omitted, version only upgrade, versions are not verified in this
|
||||||
|
// test suite
|
||||||
void cleanupTestCase() const;
|
void cleanupTestCase() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user