forked from blue/squawk
corrected messages now are supposed to display correctly
This commit is contained in:
parent
fe1ae8567a
commit
ff2c9831cf
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
43
global.cpp
43
global.cpp
@ -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;
|
||||
|
5
global.h
5
global.h
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -94,6 +94,7 @@ private:
|
||||
void hideProgress();
|
||||
void hideFile();
|
||||
void setState();
|
||||
void setEdited();
|
||||
};
|
||||
|
||||
#endif // MESSAGE_H
|
||||
|
Loading…
Reference in New Issue
Block a user