corrected messages now are supposed to display correctly

This commit is contained in:
Blue 2020-03-28 17:05:49 +03:00
parent fe1ae8567a
commit ff2c9831cf
9 changed files with 202 additions and 63 deletions

View File

@ -716,7 +716,6 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
{
const QString& body(msg.body());
if (body.size() != 0) {
const QString& id(msg.id());
Shared::Message sMsg(Shared::Message::chat);
initializeMessage(sMsg, msg, outgoing, forwarded, guessing);
QString jid = sMsg.getPenPalJid();
@ -741,9 +740,18 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
} else {
sMsg.setState(Shared::Message::State::delivered);
}
cnt->appendMessageToArchive(sMsg);
emit message(sMsg);
QString oId = msg.replaceId();
if (oId.size() > 0) {
QMap<QString, QVariant> cData = {
{"body", sMsg.getBody()},
{"stamp", sMsg.getTime()}
};
cnt->correctMessageInArchive(oId, sMsg);
emit changeMessage(jid, oId, cData);
} else {
cnt->appendMessageToArchive(sMsg);
emit message(sMsg);
}
return true;
}
@ -773,12 +781,22 @@ bool Core::Account::handleGroupMessage(const QXmppMessage& msg, bool outgoing, b
pendingStateMessages.erase(pItr);
emit changeMessage(jid, id, cData);
} else {
cnt->appendMessageToArchive(sMsg);
QDateTime minAgo = QDateTime::currentDateTime().addSecs(-60);
if (sMsg.getTime() > minAgo) { //otherwise it's considered a delayed delivery, most probably MUC history receipt
emit message(sMsg);
QString oId = msg.replaceId();
if (oId.size() > 0) {
QMap<QString, QVariant> cData = {
{"body", sMsg.getBody()},
{"stamp", sMsg.getTime()}
};
cnt->correctMessageInArchive(oId, sMsg);
emit changeMessage(jid, oId, cData);
} else {
//qDebug() << "Delayed delivery: ";
cnt->appendMessageToArchive(sMsg);
QDateTime minAgo = QDateTime::currentDateTime().addSecs(-60);
if (sMsg.getTime() > minAgo) { //otherwise it's considered a delayed delivery, most probably MUC history receipt
emit message(sMsg);
} else {
//qDebug() << "Delayed delivery: ";
}
}
}
@ -824,10 +842,16 @@ void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMess
QString jid = itr->second;
RosterItem* item = getRosterItem(jid);
Shared::Message sMsg(Shared::Message::chat);
Shared::Message sMsg(static_cast<Shared::Message::Type>(msg.type()));
initializeMessage(sMsg, msg, false, true, true);
sMsg.setState(Shared::Message::State::sent);
item->addMessageToArchive(sMsg);
QString oId = msg.replaceId();
if (oId.size() > 0) {
item->correctMessageInArchive(oId, sMsg);
} else {
item->addMessageToArchive(sMsg);
}
}
//handleChatMessage(msg, false, true, true);

View File

@ -267,8 +267,7 @@ void Core::Archive::changeMessage(const QString& id, const QMap<QString, QVarian
Shared::Message Core::Archive::newest()
{
QString id = newestId();
return getElement(id);
return edge(true);
}
QString Core::Archive::newestId()
@ -276,25 +275,8 @@ QString Core::Archive::newestId()
if (!opened) {
throw Closed("newestId", jid.toStdString());
}
MDB_txn *txn;
int rc;
rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
MDB_cursor* cursor;
rc = mdb_cursor_open(txn, order, &cursor);
MDB_val lmdbKey, lmdbData;
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_LAST);
if (rc) {
qDebug() << "Error geting newestId " << mdb_strerror(rc);
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
throw Empty(jid.toStdString());
} else {
std::string sId((char*)lmdbData.mv_data, lmdbData.mv_size);
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
return sId.c_str();
}
Shared::Message msg = newest();
return msg.getId();
}
QString Core::Archive::oldestId()
@ -302,30 +284,79 @@ QString Core::Archive::oldestId()
if (!opened) {
throw Closed("oldestId", jid.toStdString());
}
Shared::Message msg = oldest();
return msg.getId();
}
Shared::Message Core::Archive::oldest()
{
return edge(false);
}
Shared::Message Core::Archive::edge(bool end)
{
QString name;
MDB_cursor_op begin;
MDB_cursor_op iteration;
if (end) {
name = "newest";
begin = MDB_LAST;
iteration = MDB_PREV;
} else {
name = "oldest";
begin = MDB_FIRST;
iteration = MDB_NEXT;
}
if (!opened) {
throw Closed(name.toStdString(), jid.toStdString());
}
MDB_txn *txn;
MDB_cursor* cursor;
MDB_val lmdbKey, lmdbData;
int rc;
rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
MDB_cursor* cursor;
rc = mdb_cursor_open(txn, order, &cursor);
MDB_val lmdbKey, lmdbData;
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, begin);
Shared::Message msg = getStoredMessage(txn, cursor, iteration, &lmdbKey, &lmdbData, rc);
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_FIRST);
if (rc) {
qDebug() << "Error geting oldestId " << mdb_strerror(rc);
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
qDebug() << "Error geting" << name << "message" << mdb_strerror(rc);
throw Empty(jid.toStdString());
} else {
std::string sId((char*)lmdbData.mv_data, lmdbData.mv_size);
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
return sId.c_str();
return msg;
}
}
Shared::Message Core::Archive::oldest()
Shared::Message Core::Archive::getStoredMessage(MDB_txn *txn, MDB_cursor* cursor, MDB_cursor_op op, MDB_val* key, MDB_val* value, int& rc)
{
return getElement(oldestId());
Shared::Message msg;
std::string sId;
while (true) {
if (rc) {
break;
}
sId = std::string((char*)value->mv_data, value->mv_size);
try {
msg = getMessage(sId, txn);
if (msg.serverStored()) {
break;
} else {
rc = mdb_cursor_get(cursor, key, value, op);
}
} catch (...) {
break;
}
}
return msg;
}
unsigned int Core::Archive::addElements(const std::list<Shared::Message>& messages)

View File

@ -183,6 +183,8 @@ private:
void printKeys();
bool dropAvatar(const std::string& resource);
Shared::Message getMessage(const std::string& id, MDB_txn* txn);
Shared::Message getStoredMessage(MDB_txn *txn, MDB_cursor* cursor, MDB_cursor_op op, MDB_val* key, MDB_val* value, int& rc);
Shared::Message edge(bool end);
};
}

View File

@ -35,6 +35,7 @@ Core::RosterItem::RosterItem(const QString& pJid, const QString& pAccount, QObje
appendCache(),
responseCache(),
requestCache(),
toCorrect(),
muc(false)
{
archive->open(account);
@ -75,6 +76,36 @@ void Core::RosterItem::addMessageToArchive(const Shared::Message& msg)
{
if (msg.storable()) {
hisoryCache.push_back(msg);
std::map<QString, Shared::Message>::iterator itr = toCorrect.find(msg.getId());
if (itr != toCorrect.end()) {
hisoryCache.back().change({
{"body", itr->second.getBody()},
{"stamp", itr->second.getTime()}
});
toCorrect.erase(itr);
}
}
}
void Core::RosterItem::correctMessageInArchive(const QString& originalId, const Shared::Message& msg)
{
if (msg.storable()) {
QDateTime thisTime = msg.getTime();
std::map<QString, Shared::Message>::iterator itr = toCorrect.find(originalId);
if (itr != toCorrect.end()) {
if (itr->second.getTime() < thisTime) {
itr->second = msg;
}
return;
}
bool found = changeMessage(originalId, {
{"body", msg.getBody()},
{"stamp", thisTime}
});
if (!found) {
toCorrect.insert(std::make_pair(originalId, msg));
}
}
}
@ -221,7 +252,7 @@ void Core::RosterItem::appendMessageToArchive(const Shared::Message& msg)
}
}
void Core::RosterItem::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
bool Core::RosterItem::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
bool found = false;
for (Shared::Message& msg : appendCache) {
@ -259,6 +290,8 @@ void Core::RosterItem::changeMessage(const QString& id, const QMap<QString, QVar
}
}
}
return found;
}
void Core::RosterItem::flushMessagesToArchive(bool finished, const QString& firstId, const QString& lastId)

View File

@ -61,6 +61,7 @@ public:
bool isMuc() const;
void addMessageToArchive(const Shared::Message& msg);
void correctMessageInArchive(const QString& originalId, const Shared::Message& msg);
void appendMessageToArchive(const Shared::Message& msg);
void flushMessagesToArchive(bool finished, const QString& firstId, const QString& lastId);
void requestHistory(int count, const QString& before);
@ -72,7 +73,7 @@ public:
virtual Shared::VCard handleResponseVCard(const QXmppVCardIq& card, const QString& resource);
virtual void handlePresence(const QXmppPresence& pres) = 0;
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
bool changeMessage(const QString& id, const QMap<QString, QVariant>& data);
signals:
void nameChanged(const QString& name);
@ -98,6 +99,7 @@ protected:
std::list<Shared::Message> appendCache;
std::list<Shared::Message> responseCache;
std::list<std::pair<int, QString>> requestCache;
std::map<QString, Shared::Message> toCorrect;
bool muc;
private:

View File

@ -53,7 +53,10 @@ Shared::Message::Message():
outgoing(false),
forwarded(false),
state(State::delivered),
edited(false)
edited(false),
errorText(),
originalMessage(),
lastModified()
{
}
@ -242,6 +245,16 @@ void Shared::Message::setThread(const QString& p_body)
thread = p_body;
}
QDateTime Shared::Message::getLastModified() const
{
return lastModified;
}
QString Shared::Message::getOriginalBody() const
{
return originalMessage;
}
Shared::Message::Type Shared::Message::getType() const
{
return type;
@ -261,6 +274,11 @@ void Shared::Message::setState(Shared::Message::State p_state)
}
}
bool Shared::Message::serverStored() const
{
return state == State::delivered || state == State::sent;
}
void Shared::Message::setEdited(bool p_edited)
{
edited = p_edited;
@ -285,6 +303,10 @@ void Shared::Message::serialize(QDataStream& data) const
if (state == State::error) {
data << errorText;
}
if (edited) {
data << originalMessage;
data << lastModified;
}
}
void Shared::Message::deserialize(QDataStream& data)
@ -310,6 +332,10 @@ void Shared::Message::deserialize(QDataStream& data)
if (state == State::error) {
data >> errorText;
}
if (edited) {
data >> originalMessage;
data >> lastModified;
}
}
bool Shared::Message::change(const QMap<QString, QVariant>& data)
@ -337,8 +363,19 @@ bool Shared::Message::change(const QMap<QString, QVariant>& data)
}
itr = data.find("body");
if (itr != data.end()) {
setBody(itr.value().toString());
setEdited(true);
QMap<QString, QVariant>::const_iterator dItr = data.find("stamp");
QDateTime correctionDate;
if (dItr != data.end()) {
correctionDate = dItr.value().toDateTime();
} else {
correctionDate = QDateTime::currentDateTime(); //in case there is no information about time of this correction it's applied
}
if (!edited || lastModified < correctionDate) {
originalMessage = body;
lastModified = correctionDate;
setBody(itr.value().toString());
setEdited(true);
}
}
return idChanged;

View File

@ -216,6 +216,9 @@ public:
QString getPenPalJid() const;
QString getPenPalResource() const;
void generateRandomId();
bool serverStored() const;
QDateTime getLastModified() const;
QString getOriginalBody() const;
void serialize(QDataStream& data) const;
void deserialize(QDataStream& data);
@ -236,6 +239,8 @@ private:
State state;
bool edited;
QString errorText;
QString originalMessage;
QDateTime lastModified;
};
class VCard {

View File

@ -121,6 +121,9 @@ Message::Message(const Shared::Message& source, bool p_outgoing, const QString&
layout->addStretch();
statusLay->addWidget(date);
}
if (msg.getEdited()) {
setEdited();
}
bodyLayout->addWidget(statusBar);
layout->setAlignment(avatar, Qt::AlignTop);
@ -315,20 +318,7 @@ bool Message::change(const QMap<QString, QVariant>& data)
text->hide();
}
if (msg.getEdited()) {
if (!hasEditedLabel) {
editedLabel = new QLabel();
QFont eFont = editedLabel->font();
eFont.setItalic(true);
eFont.setPointSize(eFont.pointSize() - 2);
editedLabel->setFont(eFont);
hasEditedLabel = true;
QHBoxLayout* statusLay = static_cast<QHBoxLayout*>(statusBar->layout());
if (hasStatusIcon) {
statusLay->insertWidget(1, editedLabel);
} else {
statusLay->insertWidget(0, editedLabel);
}
}
setEdited();
}
if (hasStatusIcon) {
setState();
@ -338,6 +328,20 @@ bool Message::change(const QMap<QString, QVariant>& data)
return idChanged;
}
void Message::setEdited()
{
if (!hasEditedLabel) {
editedLabel = new QLabel();
hasEditedLabel = true;
QIcon q(Shared::icon("edit-rename"));
editedLabel->setPixmap(q.pixmap(12, 12));
QHBoxLayout* statusLay = static_cast<QHBoxLayout*>(statusBar->layout());
statusLay->insertWidget(1, editedLabel);
}
editedLabel->setToolTip("Last time edited: " + msg.getLastModified().toLocalTime().toString()
+ "\nOriginal message: " + msg.getOriginalBody());
}
void Message::setState()
{
Shared::Message::State state = msg.getState();

View File

@ -94,6 +94,7 @@ private:
void hideProgress();
void hideFile();
void setState();
void setEdited();
};
#endif // MESSAGE_H