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()); const QString& body(msg.body());
if (body.size() != 0) { if (body.size() != 0) {
const QString& id(msg.id());
Shared::Message sMsg(Shared::Message::chat); Shared::Message sMsg(Shared::Message::chat);
initializeMessage(sMsg, msg, outgoing, forwarded, guessing); initializeMessage(sMsg, msg, outgoing, forwarded, guessing);
QString jid = sMsg.getPenPalJid(); QString jid = sMsg.getPenPalJid();
@ -741,9 +740,18 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
} else { } else {
sMsg.setState(Shared::Message::State::delivered); sMsg.setState(Shared::Message::State::delivered);
} }
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); cnt->appendMessageToArchive(sMsg);
emit message(sMsg); emit message(sMsg);
}
return true; return true;
} }
@ -772,6 +780,15 @@ bool Core::Account::handleGroupMessage(const QXmppMessage& msg, bool outgoing, b
cnt->changeMessage(id, cData); cnt->changeMessage(id, cData);
pendingStateMessages.erase(pItr); pendingStateMessages.erase(pItr);
emit changeMessage(jid, id, cData); emit changeMessage(jid, id, cData);
} else {
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 { } else {
cnt->appendMessageToArchive(sMsg); cnt->appendMessageToArchive(sMsg);
QDateTime minAgo = QDateTime::currentDateTime().addSecs(-60); QDateTime minAgo = QDateTime::currentDateTime().addSecs(-60);
@ -781,6 +798,7 @@ bool Core::Account::handleGroupMessage(const QXmppMessage& msg, bool outgoing, b
//qDebug() << "Delayed delivery: "; //qDebug() << "Delayed delivery: ";
} }
} }
}
return true; return true;
} }
@ -824,11 +842,17 @@ void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMess
QString jid = itr->second; QString jid = itr->second;
RosterItem* item = getRosterItem(jid); 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); initializeMessage(sMsg, msg, false, true, true);
sMsg.setState(Shared::Message::State::sent);
QString oId = msg.replaceId();
if (oId.size() > 0) {
item->correctMessageInArchive(oId, sMsg);
} else {
item->addMessageToArchive(sMsg); item->addMessageToArchive(sMsg);
} }
}
//handleChatMessage(msg, false, true, true); //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() Shared::Message Core::Archive::newest()
{ {
QString id = newestId(); return edge(true);
return getElement(id);
} }
QString Core::Archive::newestId() QString Core::Archive::newestId()
@ -276,25 +275,8 @@ QString Core::Archive::newestId()
if (!opened) { if (!opened) {
throw Closed("newestId", jid.toStdString()); throw Closed("newestId", jid.toStdString());
} }
MDB_txn *txn; Shared::Message msg = newest();
int rc; return msg.getId();
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();
}
} }
QString Core::Archive::oldestId() QString Core::Archive::oldestId()
@ -302,30 +284,79 @@ QString Core::Archive::oldestId()
if (!opened) { if (!opened) {
throw Closed("oldestId", jid.toStdString()); throw Closed("oldestId", jid.toStdString());
} }
MDB_txn *txn; Shared::Message msg = oldest();
int rc; return msg.getId();
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_FIRST);
if (rc) {
qDebug() << "Error geting oldestId " << 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 Core::Archive::oldest() Shared::Message Core::Archive::oldest()
{ {
return getElement(oldestId()); 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);
rc = mdb_cursor_open(txn, order, &cursor);
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);
if (rc) {
qDebug() << "Error geting" << name << "message" << mdb_strerror(rc);
throw Empty(jid.toStdString());
} else {
return msg;
}
}
Shared::Message Core::Archive::getStoredMessage(MDB_txn *txn, MDB_cursor* cursor, MDB_cursor_op op, MDB_val* key, MDB_val* value, int& rc)
{
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) unsigned int Core::Archive::addElements(const std::list<Shared::Message>& messages)

View File

@ -183,6 +183,8 @@ private:
void printKeys(); void printKeys();
bool dropAvatar(const std::string& resource); bool dropAvatar(const std::string& resource);
Shared::Message getMessage(const std::string& id, MDB_txn* txn); 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(), appendCache(),
responseCache(), responseCache(),
requestCache(), requestCache(),
toCorrect(),
muc(false) muc(false)
{ {
archive->open(account); archive->open(account);
@ -75,6 +76,36 @@ void Core::RosterItem::addMessageToArchive(const Shared::Message& msg)
{ {
if (msg.storable()) { if (msg.storable()) {
hisoryCache.push_back(msg); 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; bool found = false;
for (Shared::Message& msg : appendCache) { 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) void Core::RosterItem::flushMessagesToArchive(bool finished, const QString& firstId, const QString& lastId)

View File

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

View File

@ -53,7 +53,10 @@ Shared::Message::Message():
outgoing(false), outgoing(false),
forwarded(false), forwarded(false),
state(State::delivered), 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; thread = p_body;
} }
QDateTime Shared::Message::getLastModified() const
{
return lastModified;
}
QString Shared::Message::getOriginalBody() const
{
return originalMessage;
}
Shared::Message::Type Shared::Message::getType() const Shared::Message::Type Shared::Message::getType() const
{ {
return type; 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) void Shared::Message::setEdited(bool p_edited)
{ {
edited = p_edited; edited = p_edited;
@ -285,6 +303,10 @@ void Shared::Message::serialize(QDataStream& data) const
if (state == State::error) { if (state == State::error) {
data << errorText; data << errorText;
} }
if (edited) {
data << originalMessage;
data << lastModified;
}
} }
void Shared::Message::deserialize(QDataStream& data) void Shared::Message::deserialize(QDataStream& data)
@ -310,6 +332,10 @@ void Shared::Message::deserialize(QDataStream& data)
if (state == State::error) { if (state == State::error) {
data >> errorText; data >> errorText;
} }
if (edited) {
data >> originalMessage;
data >> lastModified;
}
} }
bool Shared::Message::change(const QMap<QString, QVariant>& data) bool Shared::Message::change(const QMap<QString, QVariant>& data)
@ -337,9 +363,20 @@ bool Shared::Message::change(const QMap<QString, QVariant>& data)
} }
itr = data.find("body"); itr = data.find("body");
if (itr != data.end()) { if (itr != data.end()) {
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()); setBody(itr.value().toString());
setEdited(true); setEdited(true);
} }
}
return idChanged; return idChanged;
} }

View File

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

View File

@ -121,6 +121,9 @@ Message::Message(const Shared::Message& source, bool p_outgoing, const QString&
layout->addStretch(); layout->addStretch();
statusLay->addWidget(date); statusLay->addWidget(date);
} }
if (msg.getEdited()) {
setEdited();
}
bodyLayout->addWidget(statusBar); bodyLayout->addWidget(statusBar);
layout->setAlignment(avatar, Qt::AlignTop); layout->setAlignment(avatar, Qt::AlignTop);
@ -315,20 +318,7 @@ bool Message::change(const QMap<QString, QVariant>& data)
text->hide(); text->hide();
} }
if (msg.getEdited()) { if (msg.getEdited()) {
if (!hasEditedLabel) { setEdited();
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);
}
}
} }
if (hasStatusIcon) { if (hasStatusIcon) {
setState(); setState();
@ -338,6 +328,20 @@ bool Message::change(const QMap<QString, QVariant>& data)
return idChanged; 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() void Message::setState()
{ {
Shared::Message::State state = msg.getState(); Shared::Message::State state = msg.getState();

View File

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