mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor(core): strong type message receipt and row ID
Avoid implicit casting and invalid arithmetic.
This commit is contained in:
parent
8422c09f6a
commit
edf6b67313
|
@ -28,6 +28,7 @@
|
||||||
#include "src/model/groupinvite.h"
|
#include "src/model/groupinvite.h"
|
||||||
#include "src/nexus.h"
|
#include "src/nexus.h"
|
||||||
#include "src/persistence/profile.h"
|
#include "src/persistence/profile.h"
|
||||||
|
#include "src/util/strongtype.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
@ -579,7 +580,7 @@ void Core::onGroupTitleChange(Tox*, uint32_t groupId, uint32_t peerId, const uin
|
||||||
|
|
||||||
void Core::onReadReceiptCallback(Tox*, uint32_t friendId, uint32_t receipt, void* core)
|
void Core::onReadReceiptCallback(Tox*, uint32_t friendId, uint32_t receipt, void* core)
|
||||||
{
|
{
|
||||||
emit static_cast<Core*>(core)->receiptRecieved(friendId, receipt);
|
emit static_cast<Core*>(core)->receiptRecieved(friendId, ReceiptNum{receipt});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::acceptFriendRequest(const ToxPk& friendPk)
|
void Core::acceptFriendRequest(const ToxPk& friendPk)
|
||||||
|
@ -652,33 +653,35 @@ void Core::requestFriendship(const ToxId& friendId, const QString& message)
|
||||||
emit saveRequest();
|
emit saveRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Core::sendMessageWithType(uint32_t friendId, const QString& message, Tox_Message_Type type)
|
bool Core::sendMessageWithType(uint32_t friendId, const QString& message, Tox_Message_Type type, ReceiptNum& receipt)
|
||||||
{
|
{
|
||||||
int size = message.toUtf8().size();
|
int size = message.toUtf8().size();
|
||||||
auto maxSize = tox_max_message_length();
|
auto maxSize = tox_max_message_length();
|
||||||
if (size > maxSize) {
|
if (size > maxSize) {
|
||||||
qCritical() << "Core::sendMessageWithType called with message of size:" << size << "when max is:" << maxSize <<". Ignoring.";
|
qCritical() << "Core::sendMessageWithType called with message of size:" << size << "when max is:" << maxSize <<". Ignoring.";
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxString cMessage(message);
|
ToxString cMessage(message);
|
||||||
Tox_Err_Friend_Send_Message error;
|
Tox_Err_Friend_Send_Message error;
|
||||||
int receipt = tox_friend_send_message(tox.get(), friendId, type,
|
receipt = ReceiptNum{tox_friend_send_message(tox.get(), friendId, type,
|
||||||
cMessage.data(), cMessage.size(), &error);
|
cMessage.data(), cMessage.size(), &error)};
|
||||||
parseFriendSendMessageError(error);
|
if (parseFriendSendMessageError(error)) {
|
||||||
return receipt;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Core::sendMessage(uint32_t friendId, const QString& message)
|
bool Core::sendMessage(uint32_t friendId, const QString& message, ReceiptNum& receipt)
|
||||||
{
|
{
|
||||||
QMutexLocker ml(coreLoopLock.get());
|
QMutexLocker ml(coreLoopLock.get());
|
||||||
return sendMessageWithType(friendId, message, TOX_MESSAGE_TYPE_NORMAL);
|
return sendMessageWithType(friendId, message, TOX_MESSAGE_TYPE_NORMAL, receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Core::sendAction(uint32_t friendId, const QString& action)
|
bool Core::sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt)
|
||||||
{
|
{
|
||||||
QMutexLocker ml(coreLoopLock.get());
|
QMutexLocker ml(coreLoopLock.get());
|
||||||
return sendMessageWithType(friendId, action, TOX_MESSAGE_TYPE_ACTION);
|
return sendMessageWithType(friendId, action, TOX_MESSAGE_TYPE_ACTION, receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::sendTyping(uint32_t friendId, bool typing)
|
void Core::sendTyping(uint32_t friendId, bool typing)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "toxid.h"
|
#include "toxid.h"
|
||||||
|
|
||||||
#include "src/core/dhtserver.h"
|
#include "src/core/dhtserver.h"
|
||||||
|
#include "src/util/strongtype.h"
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
@ -51,6 +52,8 @@ enum class Status
|
||||||
class Core;
|
class Core;
|
||||||
|
|
||||||
using ToxCorePtr = std::unique_ptr<Core>;
|
using ToxCorePtr = std::unique_ptr<Core>;
|
||||||
|
using ReceiptNum = NamedType<uint32_t, struct ReceiptNumTag>;
|
||||||
|
Q_DECLARE_METATYPE(ReceiptNum);
|
||||||
|
|
||||||
class Core : public QObject
|
class Core : public QObject
|
||||||
{
|
{
|
||||||
|
@ -118,11 +121,11 @@ public slots:
|
||||||
void setUsername(const QString& username);
|
void setUsername(const QString& username);
|
||||||
void setStatusMessage(const QString& message);
|
void setStatusMessage(const QString& message);
|
||||||
|
|
||||||
int sendMessage(uint32_t friendId, const QString& message);
|
bool sendMessage(uint32_t friendId, const QString& message, ReceiptNum& receipt);
|
||||||
void sendGroupMessage(int groupId, const QString& message);
|
void sendGroupMessage(int groupId, const QString& message);
|
||||||
void sendGroupAction(int groupId, const QString& message);
|
void sendGroupAction(int groupId, const QString& message);
|
||||||
void changeGroupTitle(int groupId, const QString& title);
|
void changeGroupTitle(int groupId, const QString& title);
|
||||||
int sendAction(uint32_t friendId, const QString& action);
|
bool sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt);
|
||||||
void sendTyping(uint32_t friendId, bool typing);
|
void sendTyping(uint32_t friendId, bool typing);
|
||||||
|
|
||||||
void sendAvatarFile(uint32_t friendId, const QByteArray& data);
|
void sendAvatarFile(uint32_t friendId, const QByteArray& data);
|
||||||
|
@ -200,7 +203,7 @@ signals:
|
||||||
void groupSentFailed(int groupId);
|
void groupSentFailed(int groupId);
|
||||||
void actionSentResult(uint32_t friendId, const QString& action, int success);
|
void actionSentResult(uint32_t friendId, const QString& action, int success);
|
||||||
|
|
||||||
void receiptRecieved(int friedId, int receipt);
|
void receiptRecieved(int friedId, ReceiptNum receipt);
|
||||||
|
|
||||||
void failedToRemoveFriend(uint32_t friendId);
|
void failedToRemoveFriend(uint32_t friendId);
|
||||||
|
|
||||||
|
@ -234,7 +237,7 @@ private:
|
||||||
static void onReadReceiptCallback(Tox* tox, uint32_t friendId, uint32_t receipt, void* core);
|
static void onReadReceiptCallback(Tox* tox, uint32_t friendId, uint32_t receipt, void* core);
|
||||||
|
|
||||||
void sendGroupMessageWithType(int groupId, const QString& message, Tox_Message_Type type);
|
void sendGroupMessageWithType(int groupId, const QString& message, Tox_Message_Type type);
|
||||||
int sendMessageWithType(uint32_t friendId, const QString& message, Tox_Message_Type type);
|
bool sendMessageWithType(uint32_t friendId, const QString& message, Tox_Message_Type type, ReceiptNum& receipt);
|
||||||
bool parsePeerQueryError(Tox_Err_Conference_Peer_Query error) const;
|
bool parsePeerQueryError(Tox_Err_Conference_Peer_Query error) const;
|
||||||
bool parseConferenceJoinError(Tox_Err_Conference_Join error) const;
|
bool parseConferenceJoinError(Tox_Err_Conference_Join error) const;
|
||||||
bool checkConnection();
|
bool checkConnection();
|
||||||
|
|
|
@ -365,6 +365,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
QObject::connect(a.get(), &QApplication::aboutToQuit, cleanup);
|
QObject::connect(a.get(), &QApplication::aboutToQuit, cleanup);
|
||||||
|
|
||||||
|
qRegisterMetaType<ReceiptNum>();
|
||||||
// Run
|
// Run
|
||||||
int errorcode = a->exec();
|
int errorcode = a->exec();
|
||||||
|
|
||||||
|
|
|
@ -645,7 +645,7 @@ void RawDatabase::process()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.insertCallback)
|
if (query.insertCallback)
|
||||||
query.insertCallback(sqlite3_last_insert_rowid(sqlite));
|
query.insertCallback(RowId{sqlite3_last_insert_rowid(sqlite)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trans.success != nullptr)
|
if (trans.success != nullptr)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "src/util/strongtype.h"
|
||||||
|
|
||||||
/// The two following defines are required to use SQLCipher
|
/// The two following defines are required to use SQLCipher
|
||||||
/// They are used by the sqlite3.h header
|
/// They are used by the sqlite3.h header
|
||||||
|
@ -21,6 +22,8 @@
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
using RowId = NamedType<int64_t, struct RowIdTag>;
|
||||||
|
Q_DECLARE_METATYPE(RowId);
|
||||||
|
|
||||||
class RawDatabase : QObject
|
class RawDatabase : QObject
|
||||||
{
|
{
|
||||||
|
@ -31,13 +34,13 @@ public:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Query(QString query, QVector<QByteArray> blobs = {},
|
Query(QString query, QVector<QByteArray> blobs = {},
|
||||||
const std::function<void(int64_t)>& insertCallback = {})
|
const std::function<void(RowId)>& insertCallback = {})
|
||||||
: query{query.toUtf8()}
|
: query{query.toUtf8()}
|
||||||
, blobs{blobs}
|
, blobs{blobs}
|
||||||
, insertCallback{insertCallback}
|
, insertCallback{insertCallback}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Query(QString query, const std::function<void(int64_t)>& insertCallback)
|
Query(QString query, const std::function<void(RowId)>& insertCallback)
|
||||||
: query{query.toUtf8()}
|
: query{query.toUtf8()}
|
||||||
, insertCallback{insertCallback}
|
, insertCallback{insertCallback}
|
||||||
{
|
{
|
||||||
|
@ -52,7 +55,7 @@ public:
|
||||||
private:
|
private:
|
||||||
QByteArray query;
|
QByteArray query;
|
||||||
QVector<QByteArray> blobs;
|
QVector<QByteArray> blobs;
|
||||||
std::function<void(int64_t)> insertCallback;
|
std::function<void(RowId)> insertCallback;
|
||||||
std::function<void(const QVector<QVariant>&)> rowCallback;
|
std::function<void(const QVector<QVariant>&)> rowCallback;
|
||||||
QVector<sqlite3_stmt*> statements;
|
QVector<sqlite3_stmt*> statements;
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ void History::removeFriendHistory(const QString& friendPk)
|
||||||
QVector<RawDatabase::Query>
|
QVector<RawDatabase::Query>
|
||||||
History::generateNewMessageQueries(const QString& friendPk, const QString& message,
|
History::generateNewMessageQueries(const QString& friendPk, const QString& message,
|
||||||
const QString& sender, const QDateTime& time, bool isSent,
|
const QString& sender, const QDateTime& time, bool isSent,
|
||||||
QString dispName, std::function<void(int64_t)> insertIdCallback)
|
QString dispName, std::function<void(RowId)> insertIdCallback)
|
||||||
{
|
{
|
||||||
QVector<RawDatabase::Query> queries;
|
QVector<RawDatabase::Query> queries;
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ void History::onFileInsertionReady(FileDbInsertionData data)
|
||||||
.arg(static_cast<int>(data.direction))
|
.arg(static_cast<int>(data.direction))
|
||||||
.arg(ToxFile::CANCELED),
|
.arg(ToxFile::CANCELED),
|
||||||
{data.fileId.toUtf8(), data.filePath.toUtf8(), data.fileName.toUtf8(), QByteArray()},
|
{data.fileId.toUtf8(), data.filePath.toUtf8(), data.fileName.toUtf8(), QByteArray()},
|
||||||
[weakThis, fileId](int64_t id) {
|
[weakThis, fileId](RowId id) {
|
||||||
auto pThis = weakThis.lock();
|
auto pThis = weakThis.lock();
|
||||||
if (pThis) {
|
if (pThis) {
|
||||||
emit pThis->fileInserted(id, fileId);
|
emit pThis->fileInserted(id, fileId);
|
||||||
|
@ -299,12 +299,12 @@ void History::onFileInsertionReady(FileDbInsertionData data)
|
||||||
queries += RawDatabase::Query(QStringLiteral("UPDATE history "
|
queries += RawDatabase::Query(QStringLiteral("UPDATE history "
|
||||||
"SET file_id = (last_insert_rowid()) "
|
"SET file_id = (last_insert_rowid()) "
|
||||||
"WHERE id = %1")
|
"WHERE id = %1")
|
||||||
.arg(data.historyId));
|
.arg(data.historyId.get()));
|
||||||
|
|
||||||
db->execLater(queries);
|
db->execLater(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::onFileInserted(int64_t dbId, QString fileId)
|
void History::onFileInserted(RowId dbId, QString fileId)
|
||||||
{
|
{
|
||||||
auto& fileInfo = fileInfos[fileId];
|
auto& fileInfo = fileInfos[fileId];
|
||||||
if (fileInfo.finished) {
|
if (fileInfo.finished) {
|
||||||
|
@ -317,7 +317,7 @@ void History::onFileInserted(int64_t dbId, QString fileId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RawDatabase::Query History::generateFileFinished(int64_t id, bool success, const QString& filePath,
|
RawDatabase::Query History::generateFileFinished(RowId id, bool success, const QString& filePath,
|
||||||
const QByteArray& fileHash)
|
const QByteArray& fileHash)
|
||||||
{
|
{
|
||||||
auto file_state = success ? ToxFile::FINISHED : ToxFile::CANCELED;
|
auto file_state = success ? ToxFile::FINISHED : ToxFile::CANCELED;
|
||||||
|
@ -326,14 +326,14 @@ RawDatabase::Query History::generateFileFinished(int64_t id, bool success, const
|
||||||
"SET file_state = %1, file_path = ?, file_hash = ?"
|
"SET file_state = %1, file_path = ?, file_hash = ?"
|
||||||
"WHERE id = %2")
|
"WHERE id = %2")
|
||||||
.arg(file_state)
|
.arg(file_state)
|
||||||
.arg(id),
|
.arg(id.get()),
|
||||||
{filePath.toUtf8(), fileHash});
|
{filePath.toUtf8(), fileHash});
|
||||||
} else {
|
} else {
|
||||||
return RawDatabase::Query(QStringLiteral("UPDATE file_transfers "
|
return RawDatabase::Query(QStringLiteral("UPDATE file_transfers "
|
||||||
"SET finished = %1 "
|
"SET finished = %1 "
|
||||||
"WHERE id = %2")
|
"WHERE id = %2")
|
||||||
.arg(file_state)
|
.arg(file_state)
|
||||||
.arg(id));
|
.arg(id.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ void History::addNewFileMessage(const QString& friendPk, const QString& fileId,
|
||||||
insertionData.size = size;
|
insertionData.size = size;
|
||||||
insertionData.direction = direction;
|
insertionData.direction = direction;
|
||||||
|
|
||||||
auto insertFileTransferFn = [weakThis, insertionData](int64_t messageId) {
|
auto insertFileTransferFn = [weakThis, insertionData](RowId messageId) {
|
||||||
auto insertionDataRw = std::move(insertionData);
|
auto insertionDataRw = std::move(insertionData);
|
||||||
|
|
||||||
insertionDataRw.historyId = messageId;
|
insertionDataRw.historyId = messageId;
|
||||||
|
@ -395,7 +395,7 @@ void History::addNewFileMessage(const QString& friendPk, const QString& fileId,
|
||||||
*/
|
*/
|
||||||
void History::addNewMessage(const QString& friendPk, const QString& message, const QString& sender,
|
void History::addNewMessage(const QString& friendPk, const QString& message, const QString& sender,
|
||||||
const QDateTime& time, bool isSent, QString dispName,
|
const QDateTime& time, bool isSent, QString dispName,
|
||||||
const std::function<void(int64_t)>& insertIdCallback)
|
const std::function<void(RowId)>& insertIdCallback)
|
||||||
{
|
{
|
||||||
if (!Settings::getInstance().getEnableLogging()) {
|
if (!Settings::getInstance().getEnableLogging()) {
|
||||||
qWarning() << "Blocked a message from being added to database while history is disabled";
|
qWarning() << "Blocked a message from being added to database while history is disabled";
|
||||||
|
@ -413,7 +413,7 @@ void History::setFileFinished(const QString& fileId, bool success, const QString
|
||||||
const QByteArray& fileHash)
|
const QByteArray& fileHash)
|
||||||
{
|
{
|
||||||
auto& fileInfo = fileInfos[fileId];
|
auto& fileInfo = fileInfos[fileId];
|
||||||
if (fileInfo.fileId == -1) {
|
if (fileInfo.fileId.get() == -1) {
|
||||||
fileInfo.finished = true;
|
fileInfo.finished = true;
|
||||||
fileInfo.success = success;
|
fileInfo.success = success;
|
||||||
fileInfo.filePath = filePath;
|
fileInfo.filePath = filePath;
|
||||||
|
@ -616,13 +616,13 @@ QDateTime History::getStartDateChatHistory(const QString& friendPk)
|
||||||
*
|
*
|
||||||
* @param id Message ID.
|
* @param id Message ID.
|
||||||
*/
|
*/
|
||||||
void History::markAsSent(qint64 messageId)
|
void History::markAsSent(RowId messageId)
|
||||||
{
|
{
|
||||||
if (!isValid()) {
|
if (!isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db->execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(messageId));
|
db->execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(messageId.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -642,7 +642,7 @@ QList<History::HistMessage> History::getChatHistory(const QString& friendPk, con
|
||||||
auto rowCallback = [&messages](const QVector<QVariant>& row) {
|
auto rowCallback = [&messages](const QVector<QVariant>& row) {
|
||||||
// dispName and message could have null bytes, QString::fromUtf8
|
// dispName and message could have null bytes, QString::fromUtf8
|
||||||
// truncates on null bytes so we strip them
|
// truncates on null bytes so we strip them
|
||||||
auto id = row[0].toLongLong();
|
auto id = RowId{row[0].toLongLong()};
|
||||||
auto isOfflineMessage = row[1].isNull();
|
auto isOfflineMessage = row[1].isNull();
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(row[2].toLongLong());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(row[2].toLongLong());
|
||||||
auto friend_key = row[3].toString();
|
auto friend_key = row[3].toString();
|
||||||
|
|
|
@ -95,7 +95,7 @@ struct FileDbInsertionData
|
||||||
{
|
{
|
||||||
FileDbInsertionData();
|
FileDbInsertionData();
|
||||||
|
|
||||||
int64_t historyId;
|
RowId historyId;
|
||||||
QString friendPk;
|
QString friendPk;
|
||||||
QString fileId;
|
QString fileId;
|
||||||
QString fileName;
|
QString fileName;
|
||||||
|
@ -111,7 +111,7 @@ class History : public QObject, public std::enable_shared_from_this<History>
|
||||||
public:
|
public:
|
||||||
struct HistMessage
|
struct HistMessage
|
||||||
{
|
{
|
||||||
HistMessage(qint64 id, bool isSent, QDateTime timestamp, QString chat, QString dispName,
|
HistMessage(RowId id, bool isSent, QDateTime timestamp, QString chat, QString dispName,
|
||||||
QString sender, QString message)
|
QString sender, QString message)
|
||||||
: chat{chat}
|
: chat{chat}
|
||||||
, sender{sender}
|
, sender{sender}
|
||||||
|
@ -122,7 +122,7 @@ public:
|
||||||
, content(std::move(message))
|
, content(std::move(message))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
HistMessage(qint64 id, bool isSent, QDateTime timestamp, QString chat, QString dispName,
|
HistMessage(RowId id, bool isSent, QDateTime timestamp, QString chat, QString dispName,
|
||||||
QString sender, ToxFile file)
|
QString sender, ToxFile file)
|
||||||
: chat{chat}
|
: chat{chat}
|
||||||
, sender{sender}
|
, sender{sender}
|
||||||
|
@ -138,7 +138,7 @@ public:
|
||||||
QString sender;
|
QString sender;
|
||||||
QString dispName;
|
QString dispName;
|
||||||
QDateTime timestamp;
|
QDateTime timestamp;
|
||||||
qint64 id;
|
RowId id;
|
||||||
bool isSent;
|
bool isSent;
|
||||||
HistMessageContent content;
|
HistMessageContent content;
|
||||||
};
|
};
|
||||||
|
@ -161,7 +161,7 @@ public:
|
||||||
void removeFriendHistory(const QString& friendPk);
|
void removeFriendHistory(const QString& friendPk);
|
||||||
void addNewMessage(const QString& friendPk, const QString& message, const QString& sender,
|
void addNewMessage(const QString& friendPk, const QString& message, const QString& sender,
|
||||||
const QDateTime& time, bool isSent, QString dispName,
|
const QDateTime& time, bool isSent, QString dispName,
|
||||||
const std::function<void(int64_t)>& insertIdCallback = {});
|
const std::function<void(RowId)>& insertIdCallback = {});
|
||||||
|
|
||||||
void addNewFileMessage(const QString& friendPk, const QString& fileId,
|
void addNewFileMessage(const QString& friendPk, const QString& fileId,
|
||||||
const QString& fileName, const QString& filePath, int64_t size,
|
const QString& fileName, const QString& filePath, int64_t size,
|
||||||
|
@ -177,27 +177,27 @@ public:
|
||||||
const ParameterSearch& parameter);
|
const ParameterSearch& parameter);
|
||||||
QDateTime getStartDateChatHistory(const QString& friendPk);
|
QDateTime getStartDateChatHistory(const QString& friendPk);
|
||||||
|
|
||||||
void markAsSent(qint64 messageId);
|
void markAsSent(RowId messageId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QVector<RawDatabase::Query>
|
QVector<RawDatabase::Query>
|
||||||
generateNewMessageQueries(const QString& friendPk, const QString& message,
|
generateNewMessageQueries(const QString& friendPk, const QString& message,
|
||||||
const QString& sender, const QDateTime& time, bool isSent,
|
const QString& sender, const QDateTime& time, bool isSent,
|
||||||
QString dispName, std::function<void(int64_t)> insertIdCallback = {});
|
QString dispName, std::function<void(RowId)> insertIdCallback = {});
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fileInsertionReady(FileDbInsertionData data);
|
void fileInsertionReady(FileDbInsertionData data);
|
||||||
void fileInserted(int64_t dbId, QString fileId);
|
void fileInserted(RowId dbId, QString fileId);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onFileInsertionReady(FileDbInsertionData data);
|
void onFileInsertionReady(FileDbInsertionData data);
|
||||||
void onFileInserted(int64_t dbId, QString fileId);
|
void onFileInserted(RowId dbId, QString fileId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<HistMessage> getChatHistory(const QString& friendPk, const QDateTime& from,
|
QList<HistMessage> getChatHistory(const QString& friendPk, const QDateTime& from,
|
||||||
const QDateTime& to, int numMessages);
|
const QDateTime& to, int numMessages);
|
||||||
|
|
||||||
static RawDatabase::Query generateFileFinished(int64_t fileId, bool success,
|
static RawDatabase::Query generateFileFinished(RowId fileId, bool success,
|
||||||
const QString& filePath, const QByteArray& fileHash);
|
const QString& filePath, const QByteArray& fileHash);
|
||||||
void dbSchemaUpgrade();
|
void dbSchemaUpgrade();
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ private:
|
||||||
bool success = false;
|
bool success = false;
|
||||||
QString filePath;
|
QString filePath;
|
||||||
QByteArray fileHash;
|
QByteArray fileHash;
|
||||||
int64_t fileId = -1;
|
RowId fileId{-1};
|
||||||
};
|
};
|
||||||
|
|
||||||
// This needs to be a shared pointer to avoid callback lifetime issues
|
// This needs to be a shared pointer to avoid callback lifetime issues
|
||||||
|
|
|
@ -33,7 +33,7 @@ OfflineMsgEngine::OfflineMsgEngine(Friend* frnd)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void OfflineMsgEngine::dischargeReceipt(int receipt)
|
void OfflineMsgEngine::dischargeReceipt(ReceiptNum receipt)
|
||||||
{
|
{
|
||||||
QMutexLocker ml(&mutex);
|
QMutexLocker ml(&mutex);
|
||||||
|
|
||||||
|
@ -47,14 +47,14 @@ void OfflineMsgEngine::dischargeReceipt(int receipt)
|
||||||
processReceipt(receipt);
|
processReceipt(receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OfflineMsgEngine::registerReceipt(int receipt, int64_t messageID, ChatMessage::Ptr msg)
|
void OfflineMsgEngine::registerReceipt(ReceiptNum receipt, RowId messageID, ChatMessage::Ptr msg)
|
||||||
{
|
{
|
||||||
QMutexLocker ml(&mutex);
|
QMutexLocker ml(&mutex);
|
||||||
|
|
||||||
auto it = receipts.find(receipt);
|
auto it = receipts.find(receipt);
|
||||||
if (it == receipts.end()) {
|
if (it == receipts.end()) {
|
||||||
it = receipts.insert(receipt, Receipt());
|
it = receipts.insert(receipt, Receipt());
|
||||||
} else if (it->bRowValid && receipt != 0 /* offline receipt */) {
|
} else if (it->bRowValid && receipt.get() != 0 /* offline receipt */) {
|
||||||
qWarning() << "Received duplicate registration of receipt";
|
qWarning() << "Received duplicate registration of receipt";
|
||||||
}
|
}
|
||||||
it->rowId = messageID;
|
it->rowId = messageID;
|
||||||
|
@ -76,7 +76,7 @@ void OfflineMsgEngine::deliverOfflineMsgs()
|
||||||
if (undeliveredMsgs.size() == 0)
|
if (undeliveredMsgs.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QMap<int64_t, MsgPtr> msgs = undeliveredMsgs;
|
QMap<RowId, MsgPtr> msgs = undeliveredMsgs;
|
||||||
removeAllReceipts();
|
removeAllReceipts();
|
||||||
undeliveredMsgs.clear();
|
undeliveredMsgs.clear();
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ void OfflineMsgEngine::deliverOfflineMsgs()
|
||||||
auto val = iter.value();
|
auto val = iter.value();
|
||||||
auto key = iter.key();
|
auto key = iter.key();
|
||||||
QString messageText = val.msg->toString();
|
QString messageText = val.msg->toString();
|
||||||
int rec;
|
ReceiptNum rec;
|
||||||
if (val.msg->isAction()) {
|
if (val.msg->isAction()) {
|
||||||
rec = Core::getInstance()->sendAction(f->getId(), messageText);
|
Core::getInstance()->sendAction(f->getId(), messageText, rec);
|
||||||
} else {
|
} else {
|
||||||
rec = Core::getInstance()->sendMessage(f->getId(), messageText);
|
Core::getInstance()->sendMessage(f->getId(), messageText, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerReceipt(rec, key, val.msg);
|
registerReceipt(rec, key, val.msg);
|
||||||
|
@ -102,7 +102,7 @@ void OfflineMsgEngine::removeAllReceipts()
|
||||||
receipts.clear();
|
receipts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OfflineMsgEngine::updateTimestamp(int receiptId)
|
void OfflineMsgEngine::updateTimestamp(ReceiptNum receiptId)
|
||||||
{
|
{
|
||||||
QMutexLocker ml(&mutex);
|
QMutexLocker ml(&mutex);
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ void OfflineMsgEngine::updateTimestamp(int receiptId)
|
||||||
receipts.erase(receipt);
|
receipts.erase(receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OfflineMsgEngine::processReceipt(int receiptId)
|
void OfflineMsgEngine::processReceipt(ReceiptNum receiptId)
|
||||||
{
|
{
|
||||||
const auto receipt = receipts.constFind(receiptId);
|
const auto receipt = receipts.constFind(receiptId);
|
||||||
if (receipt == receipts.end()) {
|
if (receipt == receipts.end()) {
|
||||||
|
@ -138,6 +138,6 @@ void OfflineMsgEngine::processReceipt(int receiptId)
|
||||||
if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
|
if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
|
||||||
updateTimestamp(receiptId);
|
updateTimestamp(receiptId);
|
||||||
} else {
|
} else {
|
||||||
QMetaObject::invokeMethod(this, "updateTimestamp", Qt::QueuedConnection, Q_ARG(int, receiptId));
|
QMetaObject::invokeMethod(this, "updateTimestamp", Qt::QueuedConnection, Q_ARG(ReceiptNum, receiptId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define OFFLINEMSGENGINE_H
|
#define OFFLINEMSGENGINE_H
|
||||||
|
|
||||||
#include "src/chatlog/chatmessage.h"
|
#include "src/chatlog/chatmessage.h"
|
||||||
|
#include "src/core/core.h"
|
||||||
|
#include "src/persistence/db/rawdatabase.h"
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
@ -36,32 +38,32 @@ public:
|
||||||
explicit OfflineMsgEngine(Friend*);
|
explicit OfflineMsgEngine(Friend*);
|
||||||
virtual ~OfflineMsgEngine() = default;
|
virtual ~OfflineMsgEngine() = default;
|
||||||
|
|
||||||
void dischargeReceipt(int receipt);
|
void dischargeReceipt(ReceiptNum receipt);
|
||||||
void registerReceipt(int receipt, int64_t messageID, ChatMessage::Ptr msg);
|
void registerReceipt(ReceiptNum receipt, RowId messageID, ChatMessage::Ptr msg);
|
||||||
void deliverOfflineMsgs();
|
void deliverOfflineMsgs();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void removeAllReceipts();
|
void removeAllReceipts();
|
||||||
void updateTimestamp(int receiptId);
|
void updateTimestamp(ReceiptNum receiptId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processReceipt(int receiptId);
|
void processReceipt(ReceiptNum receiptId);
|
||||||
struct Receipt
|
struct Receipt
|
||||||
{
|
{
|
||||||
bool bRowValid{false};
|
bool bRowValid{false};
|
||||||
int64_t rowId{0};
|
RowId rowId{0};
|
||||||
bool bRecepitReceived{false};
|
bool bRecepitReceived{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MsgPtr
|
struct MsgPtr
|
||||||
{
|
{
|
||||||
ChatMessage::Ptr msg;
|
ChatMessage::Ptr msg;
|
||||||
int receipt;
|
ReceiptNum receipt;
|
||||||
};
|
};
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
Friend* f;
|
Friend* f;
|
||||||
QHash<int, Receipt> receipts;
|
QHash<ReceiptNum, Receipt> receipts;
|
||||||
QMap<int64_t, MsgPtr> undeliveredMsgs;
|
QMap<RowId, MsgPtr> undeliveredMsgs;
|
||||||
|
|
||||||
static const int offlineTimeout;
|
static const int offlineTimeout;
|
||||||
};
|
};
|
||||||
|
|
55
src/util/strongtype.h
Normal file
55
src/util/strongtype.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2019 by The qTox Project Contributors
|
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STORNGTYPE_H
|
||||||
|
#define STORNGTYPE_H
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
/* This class facilitates creating a named class which wraps underlying POD,
|
||||||
|
* avoiding implict casts and arithmetic of the underlying data.
|
||||||
|
* Usage: Declare named type with arbitrary tag, then hook up Qt metatype for use
|
||||||
|
* in signals/slots. For queued connections, registering the metatype is also
|
||||||
|
* required before the type is used.
|
||||||
|
* using ReceiptNum = NamedType<uint32_t, struct ReceiptNumTag>;
|
||||||
|
* Q_DECLARE_METATYPE(ReceiptNum);
|
||||||
|
* qRegisterMetaType<ReceiptNum>();
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T, typename Parameter>
|
||||||
|
class NamedType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NamedType() {}
|
||||||
|
explicit NamedType(T const& value) : value_(value) {}
|
||||||
|
T& get() { return value_; }
|
||||||
|
T const& get() const {return value_; }
|
||||||
|
bool operator==(const NamedType& rhs) const { return value_ == rhs.value_; }
|
||||||
|
bool operator<(const NamedType& rhs) const { return value_ < rhs.value_; }
|
||||||
|
bool operator>(const NamedType& rhs) const { return value_ > rhs.value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Parameter>
|
||||||
|
inline uint qHash(const NamedType<T,Parameter> &key, uint seed = 0) {
|
||||||
|
return qHash(key.get(), seed);
|
||||||
|
}
|
||||||
|
#endif // STORNGTYPE_H
|
|
@ -686,7 +686,7 @@ void ChatForm::onStatusMessage(const QString& message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onReceiptReceived(quint32 friendId, int receipt)
|
void ChatForm::onReceiptReceived(quint32 friendId, ReceiptNum receipt)
|
||||||
{
|
{
|
||||||
if (friendId == f->getId()) {
|
if (friendId == f->getId()) {
|
||||||
offlineEngine->dischargeReceipt(receipt);
|
offlineEngine->dischargeReceipt(receipt);
|
||||||
|
@ -885,7 +885,7 @@ ChatForm::MessageMetadata ChatForm::getMessageMetadata(History::HistMessage cons
|
||||||
const bool isAction =
|
const bool isAction =
|
||||||
histMessage.content.getType() == HistMessageContentType::message
|
histMessage.content.getType() == HistMessageContentType::message
|
||||||
&& histMessage.content.asMessage().startsWith(ACTION_PREFIX, Qt::CaseInsensitive);
|
&& histMessage.content.asMessage().startsWith(ACTION_PREFIX, Qt::CaseInsensitive);
|
||||||
const qint64 id = histMessage.id;
|
const RowId id = histMessage.id;
|
||||||
return {isSelf, needSending, isAction, id, authorPk, msgDateTime};
|
return {isSelf, needSending, isAction, id, authorPk, msgDateTime};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,13 +931,13 @@ void ChatForm::sendLoadedMessage(ChatMessage::Ptr chatMsg, MessageMetadata const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int receipt = 0;
|
ReceiptNum receipt{0};
|
||||||
if (f->getStatus() != Status::Offline) {
|
if (f->getStatus() != Status::Offline) {
|
||||||
Core* core = Core::getInstance();
|
Core* core = Core::getInstance();
|
||||||
uint32_t friendId = f->getId();
|
uint32_t friendId = f->getId();
|
||||||
QString stringMsg = chatMsg->toString();
|
QString stringMsg = chatMsg->toString();
|
||||||
receipt = metadata.isAction ? core->sendAction(friendId, stringMsg)
|
metadata.isAction ? core->sendAction(friendId, stringMsg, receipt)
|
||||||
: core->sendMessage(friendId, stringMsg);
|
: core->sendMessage(friendId, stringMsg, receipt);
|
||||||
}
|
}
|
||||||
getOfflineMsgEngine()->registerReceipt(receipt, metadata.id, chatMsg);
|
getOfflineMsgEngine()->registerReceipt(receipt, metadata.id, chatMsg);
|
||||||
}
|
}
|
||||||
|
@ -1122,11 +1122,11 @@ void ChatForm::SendMessageStr(QString msg)
|
||||||
historyPart = ACTION_PREFIX + part;
|
historyPart = ACTION_PREFIX + part;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rec = 0;
|
ReceiptNum receipt{0};
|
||||||
if (f->getStatus() != Status::Offline) {
|
if (f->getStatus() != Status::Offline) {
|
||||||
Core* core = Core::getInstance();
|
Core* core = Core::getInstance();
|
||||||
uint32_t friendId = f->getId();
|
uint32_t friendId = f->getId();
|
||||||
rec = isAction ? core->sendAction(friendId, part) : core->sendMessage(friendId, part);
|
isAction ? core->sendAction(friendId, part, receipt) : core->sendMessage(friendId, part, receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessage::Ptr ma = createSelfMessage(part, timestamp, isAction, false);
|
ChatMessage::Ptr ma = createSelfMessage(part, timestamp, isAction, false);
|
||||||
|
@ -1138,8 +1138,8 @@ void ChatForm::SendMessageStr(QString msg)
|
||||||
QString name = Core::getInstance()->getUsername();
|
QString name = Core::getInstance()->getUsername();
|
||||||
bool isSent = !Settings::getInstance().getFauxOfflineMessaging();
|
bool isSent = !Settings::getInstance().getFauxOfflineMessaging();
|
||||||
history->addNewMessage(pk, historyPart, selfPk, timestamp, isSent, name,
|
history->addNewMessage(pk, historyPart, selfPk, timestamp, isSent, name,
|
||||||
[offMsgEngine, rec, ma](int64_t id) {
|
[offMsgEngine, receipt, ma](RowId id) {
|
||||||
offMsgEngine->registerReceipt(rec, id, ma);
|
offMsgEngine->registerReceipt(receipt, id, ma);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// TODO: Make faux-offline messaging work partially with the history disabled
|
// TODO: Make faux-offline messaging work partially with the history disabled
|
||||||
|
|
|
@ -103,7 +103,7 @@ private slots:
|
||||||
void onFriendNameChanged(const QString& name);
|
void onFriendNameChanged(const QString& name);
|
||||||
void onFriendMessageReceived(quint32 friendId, const QString& message, bool isAction);
|
void onFriendMessageReceived(quint32 friendId, const QString& message, bool isAction);
|
||||||
void onStatusMessage(const QString& message);
|
void onStatusMessage(const QString& message);
|
||||||
void onReceiptReceived(quint32 friendId, int receipt);
|
void onReceiptReceived(quint32 friendId, ReceiptNum receipt);
|
||||||
void onLoadHistory();
|
void onLoadHistory();
|
||||||
void onUpdateTime();
|
void onUpdateTime();
|
||||||
void sendImage(const QPixmap& pixmap);
|
void sendImage(const QPixmap& pixmap);
|
||||||
|
@ -117,10 +117,10 @@ private:
|
||||||
const bool isSelf;
|
const bool isSelf;
|
||||||
const bool needSending;
|
const bool needSending;
|
||||||
const bool isAction;
|
const bool isAction;
|
||||||
const qint64 id;
|
const RowId id;
|
||||||
const ToxPk authorPk;
|
const ToxPk authorPk;
|
||||||
const QDateTime msgDateTime;
|
const QDateTime msgDateTime;
|
||||||
MessageMetadata(bool isSelf, bool needSending, bool isAction, qint64 id, ToxPk authorPk,
|
MessageMetadata(bool isSelf, bool needSending, bool isAction, RowId id, ToxPk authorPk,
|
||||||
QDateTime msgDateTime)
|
QDateTime msgDateTime)
|
||||||
: isSelf{isSelf}
|
: isSelf{isSelf}
|
||||||
, needSending{needSending}
|
, needSending{needSending}
|
||||||
|
|
|
@ -240,7 +240,7 @@ void Widget::init()
|
||||||
connect(updateCheck.get(), &UpdateCheck::updateAvailable, this, &Widget::onUpdateAvailable);
|
connect(updateCheck.get(), &UpdateCheck::updateAvailable, this, &Widget::onUpdateAvailable);
|
||||||
#endif
|
#endif
|
||||||
settingsWidget = new SettingsWidget(updateCheck.get(), this);
|
settingsWidget = new SettingsWidget(updateCheck.get(), this);
|
||||||
#if UPDATE_CHECK_ENABLED
|
#if UPDATE_CHECK_ENABLED
|
||||||
updateCheck->checkForUpdate();
|
updateCheck->checkForUpdate();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1013,7 +1013,7 @@ void Widget::addFriend(uint32_t friendId, const ToxPk& friendPk)
|
||||||
connect(widget, &FriendWidget::copyFriendIdToClipboard, this, &Widget::copyFriendIdToClipboard);
|
connect(widget, &FriendWidget::copyFriendIdToClipboard, this, &Widget::copyFriendIdToClipboard);
|
||||||
connect(widget, &FriendWidget::contextMenuCalled, widget, &FriendWidget::onContextMenuCalled);
|
connect(widget, &FriendWidget::contextMenuCalled, widget, &FriendWidget::onContextMenuCalled);
|
||||||
connect(widget, SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int)));
|
connect(widget, SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int)));
|
||||||
|
|
||||||
Profile* profile = Nexus::getProfile();
|
Profile* profile = Nexus::getProfile();
|
||||||
connect(profile, &Profile::friendAvatarSet, widget, &FriendWidget::onAvatarSet);
|
connect(profile, &Profile::friendAvatarSet, widget, &FriendWidget::onAvatarSet);
|
||||||
connect(profile, &Profile::friendAvatarRemoved, widget, &FriendWidget::onAvatarRemoved);
|
connect(profile, &Profile::friendAvatarRemoved, widget, &FriendWidget::onAvatarRemoved);
|
||||||
|
@ -1218,7 +1218,7 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool
|
||||||
newFriendMessageAlert(friendId);
|
newFriendMessageAlert(friendId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::onReceiptRecieved(int friendId, int receipt)
|
void Widget::onReceiptRecieved(int friendId, ReceiptNum receipt)
|
||||||
{
|
{
|
||||||
Friend* f = FriendList::findFriend(friendId);
|
Friend* f = FriendList::findFriend(friendId);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
|
|
@ -167,7 +167,7 @@ public slots:
|
||||||
void onFriendMessageReceived(int friendId, const QString& message, bool isAction);
|
void onFriendMessageReceived(int friendId, const QString& message, bool isAction);
|
||||||
void onFriendRequestReceived(const ToxPk& friendPk, const QString& message);
|
void onFriendRequestReceived(const ToxPk& friendPk, const QString& message);
|
||||||
void updateFriendActivity(const Friend* frnd);
|
void updateFriendActivity(const Friend* frnd);
|
||||||
void onReceiptRecieved(int friendId, int receipt);
|
void onReceiptRecieved(int friendId, ReceiptNum receipt);
|
||||||
void onEmptyGroupCreated(int groupId, const QString& title);
|
void onEmptyGroupCreated(int groupId, const QString& title);
|
||||||
void onGroupInviteReceived(const GroupInvite& inviteInfo);
|
void onGroupInviteReceived(const GroupInvite& inviteInfo);
|
||||||
void onGroupInviteAccepted(const GroupInvite& inviteInfo);
|
void onGroupInviteAccepted(const GroupInvite& inviteInfo);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user