diff --git a/src/core.cpp b/src/core.cpp index 43f2251b1..2f8211519 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -745,23 +745,22 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag saveConfiguration(); } -void Core::sendMessage(int friendId, const QString& message) +int Core::sendMessage(int friendId, const QString& message) { - QList cMessages = splitMessage(message); - - for (auto &cMsg :cMessages) - { - int messageId = tox_send_message(tox, friendId, cMsg.data(), cMsg.size()); - if (messageId == 0) - emit messageSentResult(friendId, message, messageId); - } + QMutexLocker ml(&messageSendMutex); + CString cMessage(message); + int receipt = tox_send_message(tox, friendId, cMessage.data(), cMessage.size()); + emit messageSentResult(friendId, message, receipt); + return receipt; } -void Core::sendAction(int friendId, const QString &action) +int Core::sendAction(int friendId, const QString &action) { + QMutexLocker ml(&messageSendMutex); CString cMessage(action); - int ret = tox_send_action(tox, friendId, cMessage.data(), cMessage.size()); - emit actionSentResult(friendId, action, ret); + int receipt = tox_send_action(tox, friendId, cMessage.data(), cMessage.size()); + emit messageSentResult(friendId, action, receipt); + return receipt; } void Core::sendTyping(int friendId, bool typing) diff --git a/src/core.h b/src/core.h index 14bd02060..8fe15de03 100644 --- a/src/core.h +++ b/src/core.h @@ -45,6 +45,7 @@ public: static const QString TOX_EXT; static const QString CONFIG_FILE_NAME; static QString sanitize(QString name); + static QList splitMessage(const QString &message); QString getPeerName(const ToxID& id) const; @@ -92,10 +93,10 @@ public slots: void setStatusMessage(const QString& message); void setAvatar(uint8_t format, const QByteArray& data); - void sendMessage(int friendId, const QString& message); + int sendMessage(int friendId, const QString& message); void sendGroupMessage(int groupId, const QString& message); void sendGroupAction(int groupId, const QString& message); - void sendAction(int friendId, const QString& action); + int sendAction(int friendId, const QString& action); void sendTyping(int friendId, bool typing); void sendFile(int32_t friendId, QString Filename, QString FilePath, long long filesize); @@ -154,7 +155,6 @@ signals: void messageSentResult(int friendId, const QString& message, int messageId); void groupSentResult(int groupId, const QString& message, int result); - void actionSentResult(int friendId, const QString& action, int success); void receiptRecieved(int friedId, int receipt); @@ -250,8 +250,6 @@ private: void checkLastOnline(int friendId); - QList splitMessage(const QString &message); - private slots: void onFileTransferFinished(ToxFile file); @@ -265,7 +263,7 @@ private: int dhtServerId; static QList fileSendQueue, fileRecvQueue; static ToxCall calls[]; - QMutex fileSendMutex; + QMutex fileSendMutex, messageSendMutex; bool ready; uint8_t* pwsaltedkeys[PasswordType::ptCounter]; // use the pw's hash as the "pw" diff --git a/src/historykeeper.cpp b/src/historykeeper.cpp index 4dc3335af..64e674974 100644 --- a/src/historykeeper.cpp +++ b/src/historykeeper.cpp @@ -37,7 +37,7 @@ HistoryKeeper *HistoryKeeper::getInstance() { QList initLst; initLst.push_back(QString("CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, ") + - QString("chat_id INTEGER NOT NULL, sender INTEGER NOT NULL, sent_ok BOOLEAN NOT NULL DEFAULT TRUE, message TEXT NOT NULL);")); + QString("chat_id INTEGER NOT NULL, sender INTEGER NOT NULL, sent_ok INTEGER NOT NULL DEFAULT 0, message TEXT NOT NULL);")); initLst.push_back(QString("CREATE TABLE IF NOT EXISTS aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT UNIQUE NOT NULL);")); initLst.push_back(QString("CREATE TABLE IF NOT EXISTS chats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, ctype INTEGER NOT NULL);")); @@ -109,6 +109,10 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) : updateChatsID(); updateAliases(); + + QSqlQuery sqlAnswer = db->exec("select seq from sqlite_sequence where name=\"history\";"); + sqlAnswer.first(); + messageID = sqlAnswer.value(0).toInt(); } HistoryKeeper::~HistoryKeeper() @@ -116,7 +120,7 @@ HistoryKeeper::~HistoryKeeper() delete db; } -void HistoryKeeper::addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt) +int HistoryKeeper::addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt) { int chat_id = getChatID(chat, ctSingle).first; int sender_id = getAliasID(sender); @@ -124,6 +128,9 @@ void HistoryKeeper::addChatEntry(const QString& chat, const QString& message, co db->exec(QString("INSERT INTO history (timestamp, chat_id, sender, message)") + QString("VALUES (%1, %2, %3, '%4');") .arg(dt.toMSecsSinceEpoch()).arg(chat_id).arg(sender_id).arg(wrapMessage(message))); + + messageID++; + return messageID; } QList HistoryKeeper::getChatHistory(HistoryKeeper::ChatType ct, const QString &chat, @@ -235,13 +242,15 @@ void HistoryKeeper::resetInstance() historyInstance = nullptr; } -void HistoryKeeper::addGroupChatEntry(const QString &chat, const QString &message, const QString &sender, const QDateTime &dt) +int HistoryKeeper::addGroupChatEntry(const QString &chat, const QString &message, const QString &sender, const QDateTime &dt) { Q_UNUSED(chat) Q_UNUSED(message) Q_UNUSED(sender) Q_UNUSED(dt) // no groupchats yet + + return -1; } HistoryKeeper::ChatType HistoryKeeper::convertToChatType(int ct) @@ -275,3 +284,8 @@ void HistoryKeeper::renameHistory(QString from, QString to) if (filePlain.exists()) filePlain.rename(QDir(Settings::getInstance().getSettingsDirPath()).filePath(to + ".qtox_history")); } + +void HistoryKeeper::markAsSent(int m_id) +{ + db->exec(QString("UPDATE history SET sent_ok = 1 WHERE id = %1;").arg(m_id)); +} diff --git a/src/historykeeper.h b/src/historykeeper.h index bfe3208c4..ad07d65c6 100644 --- a/src/historykeeper.h +++ b/src/historykeeper.h @@ -44,9 +44,10 @@ public: static bool checkPassword(); static void renameHistory(QString from, QString to); - void addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); - void addGroupChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); + int addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); + int addGroupChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); QList getChatHistory(ChatType ct, const QString &chat, const QDateTime &time_from, const QDateTime &time_to); + void markAsSent(int m_id); private: HistoryKeeper(GenericDdInterface *db_); @@ -66,6 +67,7 @@ private: QMap aliases; QMap> chats; bool isEncrypted; + int messageID; }; #endif // HISTORYKEEPER_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 6d0ab0be3..0f224a2e3 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -39,6 +39,7 @@ #include "src/widget/croppinglabel.h" #include "src/misc/style.h" #include "src/misc/settings.h" +#include "src/misc/cstring.h" ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) @@ -100,20 +101,36 @@ void ChatForm::onSendTriggered() if (msg.isEmpty()) return; - QDateTime timestamp = QDateTime::currentDateTime(); - HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, msg, Core::getInstance()->getSelfId().publicKey, timestamp); + bool isAction = msg.startsWith("/me "); + if (isAction) + msg = msg = msg.right(msg.length() - 4); - if (msg.startsWith("/me ")) + QList splittedMsg = Core::splitMessage(msg); + QDateTime timestamp = QDateTime::currentDateTime(); + + for (CString& c_msg : splittedMsg) { - msg = msg.right(msg.length() - 4); - addSelfMessage(msg, true, timestamp); - emit sendAction(f->getFriendID(), msg); - } - else - { - addSelfMessage(msg, false, timestamp); - emit sendMessage(f->getFriendID(), msg); + QString qt_msg = CString::toString(c_msg.data(), c_msg.size()); + QString qt_msg_hist = qt_msg; + if (isAction) + qt_msg_hist = "/me " + qt_msg; + + int id = HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, qt_msg_hist, + Core::getInstance()->getSelfId().publicKey, timestamp); + + qDebug() << "db id:" << id; + + addSelfMessage(msg, isAction, timestamp); + int rec; + if (isAction) + rec = Core::getInstance()->sendAction(f->getFriendID(), msg); + else + rec = Core::getInstance()->sendMessage(f->getFriendID(), msg); + + qDebug() << "receipt:" << rec; + registerReceipt(rec, id); } + msgEdit->clear(); } @@ -787,7 +804,6 @@ void ChatForm::updateTime() callDuration->setText(secondsToDHMS(timeElapsed.elapsed()/1000)); } - QString ChatForm::secondsToDHMS(quint32 duration) { QString res; @@ -810,3 +826,28 @@ QString ChatForm::secondsToDHMS(quint32 duration) //I assume no one will ever have call longer than ~30days return cD + res.sprintf("%dd%02dh %02dm %02ds", days, hours, minutes, seconds); } + +void ChatForm::registerReceipt(int receipt, int messageID) +{ + receipts[receipt] = messageID; + undeliveredMsgs.insert(messageID); + qDebug() << "linking: rec" << receipt << "with" << messageID; +} + +void ChatForm::dischargeReceipt(int receipt) +{ + auto it = receipts.find(receipt); + if (it != receipts.end()) + { + if (undeliveredMsgs.remove(it.value())) + HistoryKeeper::getInstance()->markAsSent(it.value()); + receipts.erase(it); + qDebug() << "receipt" << receipt << "delivered"; + } +} + +void ChatForm::clearReciepts() +{ + receipts.clear(); + undeliveredMsgs.clear(); +} diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 14b6739e1..4f2d847d7 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -22,6 +22,7 @@ #include #include #include +#include struct Friend; class FileTransferInstance; @@ -35,6 +36,9 @@ public: ChatForm(Friend* chatFriend); ~ChatForm(); void setStatusMessage(QString newMessage); + void registerReceipt(int receipt, int messageID); + void dischargeReceipt(int receipt); + void clearReciepts(); signals: void sendFile(int32_t friendId, QString, QString, long long); @@ -100,6 +104,8 @@ private: void startCounter(); void stopCounter(); QString secondsToDHMS(quint32 duration); + QHash receipts; + QSet undeliveredMsgs; }; #endif // CHATFORM_H diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 085cde8fb..8980de450 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -769,6 +769,7 @@ void Widget::onReceiptRecieved(int friendId, int receipt) return; qDebug() << "Receipt Recieved" << friendId << "receipt" << receipt; + f->getChatForm()->dischargeReceipt(receipt); } void Widget::newMessageAlert(GenericChatroomWidget* chat)