now it's possible to fix your messages

This commit is contained in:
Blue 2022-03-28 23:25:33 +03:00
parent bf4a27f35d
commit 788c6ca556
Signed by: blue
GPG Key ID: 9B203B252A63EE38
13 changed files with 204 additions and 85 deletions

View File

@ -4,6 +4,7 @@
### Bug fixes ### Bug fixes
- build in release mode now no longer spams warnings - build in release mode now no longer spams warnings
- build now correctly installs all build plugin libs - build now correctly installs all build plugin libs
- a bug where the correction message was received, the indication was on but the text didn't actually change
### Improvements ### Improvements
- reduced amount of places where platform specific path separator is used - reduced amount of places where platform specific path separator is used
@ -13,6 +14,7 @@
- now it's possible to set up different qt styles from settings - now it's possible to set up different qt styles from settings
- if you have KConfig nad KConfigWidgets packages installed - you can chose from global color schemes - if you have KConfig nad KConfigWidgets packages installed - you can chose from global color schemes
- it's possible now to chose a folder where squawk is going to store downloaded files - it's possible now to chose a folder where squawk is going to store downloaded files
- now you can correct your message
## Squawk 0.2.0 (Jan 10, 2022) ## Squawk 0.2.0 (Jan 10, 2022)
### Bug fixes ### Bug fixes

View File

@ -935,3 +935,7 @@ void Core::Account::requestChangeMessage(const QString& jid, const QString& mess
void Core::Account::resendMessage(const QString& jid, const QString& id) { void Core::Account::resendMessage(const QString& jid, const QString& id) {
mh->resendMessage(jid, id);} mh->resendMessage(jid, id);}
void Core::Account::replaceMessage(const QString& originalId, const Shared::Message& data) {
mh->sendMessage(data, false, originalId);}

View File

@ -104,6 +104,7 @@ public:
void addRoomRequest(const QString& jid, const QString& nick, const QString& password, bool autoJoin); void addRoomRequest(const QString& jid, const QString& nick, const QString& password, bool autoJoin);
void uploadVCard(const Shared::VCard& card); void uploadVCard(const Shared::VCard& card);
void resendMessage(const QString& jid, const QString& id); void resendMessage(const QString& jid, const QString& id);
void replaceMessage(const QString& originalId, const Shared::Message& data);
public slots: public slots:
void connect(); void connect();

View File

@ -41,10 +41,10 @@ void Core::MessageHandler::onMessageReceived(const QXmppMessage& msg)
handled = handleGroupMessage(msg); handled = handleGroupMessage(msg);
break; break;
case QXmppMessage::Error: { case QXmppMessage::Error: {
QString id = msg.id(); std::tuple<bool, QString, QString> ids = getOriginalPendingMessageId(msg.id());
std::map<QString, QString>::const_iterator itr = pendingStateMessages.find(id); if (std::get<0>(ids)) {
if (itr != pendingStateMessages.end()) { QString id = std::get<1>(ids);
QString jid = itr->second; QString jid = std::get<2>(ids);
RosterItem* cnt = acc->rh->getRosterItem(jid); RosterItem* cnt = acc->rh->getRosterItem(jid);
QMap<QString, QVariant> cData = { QMap<QString, QVariant> cData = {
{"state", static_cast<uint>(Shared::Message::State::error)}, {"state", static_cast<uint>(Shared::Message::State::error)},
@ -53,9 +53,7 @@ void Core::MessageHandler::onMessageReceived(const QXmppMessage& msg)
if (cnt != 0) { if (cnt != 0) {
cnt->changeMessage(id, cData); cnt->changeMessage(id, cData);
} }
;
emit acc->changeMessage(jid, id, cData); emit acc->changeMessage(jid, id, cData);
pendingStateMessages.erase(itr);
handled = true; handled = true;
} else { } else {
qDebug() << "received a message with type \"Error\", not sure what to do with it now, skipping"; qDebug() << "received a message with type \"Error\", not sure what to do with it now, skipping";
@ -111,7 +109,6 @@ bool Core::MessageHandler::handleGroupMessage(const QXmppMessage& msg, bool outg
{ {
const QString& body(msg.body()); const QString& body(msg.body());
if (body.size() != 0) { if (body.size() != 0) {
QString id = msg.id();
Shared::Message sMsg(Shared::Message::groupChat); Shared::Message sMsg(Shared::Message::groupChat);
initializeMessage(sMsg, msg, outgoing, forwarded, guessing); initializeMessage(sMsg, msg, outgoing, forwarded, guessing);
@ -121,12 +118,11 @@ bool Core::MessageHandler::handleGroupMessage(const QXmppMessage& msg, bool outg
return false; return false;
} }
std::map<QString, QString>::const_iterator pItr = pendingStateMessages.find(id); std::tuple<bool, QString, QString> ids = getOriginalPendingMessageId(msg.id());
if (pItr != pendingStateMessages.end()) { if (std::get<0>(ids)) {
QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}}; QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}};
cnt->changeMessage(id, cData); cnt->changeMessage(std::get<1>(ids), cData);
pendingStateMessages.erase(pItr); emit acc->changeMessage(std::get<2>(ids), std::get<1>(ids), cData);
emit acc->changeMessage(jid, id, cData);
} else { } else {
QString oId = msg.replaceId(); QString oId = msg.replaceId();
if (oId.size() > 0) { if (oId.size() > 0) {
@ -227,53 +223,70 @@ void Core::MessageHandler::onCarbonMessageSent(const QXmppMessage& msg)
handleChatMessage(msg, true, true); handleChatMessage(msg, true, true);
} }
void Core::MessageHandler::onReceiptReceived(const QString& jid, const QString& id) std::tuple<bool, QString, QString> Core::MessageHandler::getOriginalPendingMessageId(const QString& id)
{ {
std::tuple<bool, QString, QString> result({false, "", ""});
std::map<QString, QString>::const_iterator itr = pendingStateMessages.find(id); std::map<QString, QString>::const_iterator itr = pendingStateMessages.find(id);
if (itr != pendingStateMessages.end()) { if (itr != pendingStateMessages.end()) {
QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}}; std::get<0>(result) = true;
RosterItem* ri = acc->rh->getRosterItem(itr->second); std::get<2>(result) = itr->second;
if (ri != 0) {
ri->changeMessage(id, cData); std::map<QString, QString>::const_iterator itrC = pendingCorrectionMessages.find(id);
if (itrC != pendingCorrectionMessages.end()) {
std::get<1>(result) = itrC->second;
pendingCorrectionMessages.erase(itrC);
} else {
std::get<1>(result) = itr->first;
} }
emit acc->changeMessage(itr->second, id, cData);
pendingStateMessages.erase(itr); pendingStateMessages.erase(itr);
} }
return result;
} }
void Core::MessageHandler::sendMessage(const Shared::Message& data, bool newMessage) void Core::MessageHandler::onReceiptReceived(const QString& jid, const QString& id)
{ {
if (data.getOutOfBandUrl().size() == 0 && data.getAttachPath().size() > 0) { std::tuple<bool, QString, QString> ids = getOriginalPendingMessageId(id);
prepareUpload(data, newMessage); if (std::get<0>(ids)) {
} else { QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}};
performSending(data, newMessage); RosterItem* ri = acc->rh->getRosterItem(std::get<2>(ids));
if (ri != 0) {
ri->changeMessage(std::get<1>(ids), cData);
}
emit acc->changeMessage(std::get<2>(ids), std::get<1>(ids), cData);
} }
} }
void Core::MessageHandler::performSending(Shared::Message data, bool newMessage) void Core::MessageHandler::sendMessage(const Shared::Message& data, bool newMessage, QString originalId)
{
if (data.getOutOfBandUrl().size() == 0 && data.getAttachPath().size() > 0) {
pendingCorrectionMessages.insert(std::make_pair(data.getId(), originalId));
prepareUpload(data, newMessage);
} else {
performSending(data, originalId, newMessage);
}
}
void Core::MessageHandler::performSending(Shared::Message data, const QString& originalId, bool newMessage)
{ {
QString jid = data.getPenPalJid(); QString jid = data.getPenPalJid();
QString id = data.getId(); QString id = data.getId();
QString oob = data.getOutOfBandUrl(); qDebug() << "Sending message with id:" << id;
if (originalId.size() > 0) {
qDebug() << "To replace one with id:" << originalId;
}
RosterItem* ri = acc->rh->getRosterItem(jid); RosterItem* ri = acc->rh->getRosterItem(jid);
bool sent = false; bool sent = false;
QMap<QString, QVariant> changes; if (newMessage && originalId.size() > 0) {
newMessage = false;
}
QDateTime sendTime = QDateTime::currentDateTimeUtc(); QDateTime sendTime = QDateTime::currentDateTimeUtc();
if (acc->state == Shared::ConnectionState::connected) { if (acc->state == Shared::ConnectionState::connected) {
QXmppMessage msg(acc->getFullJid(), data.getTo(), data.getBody(), data.getThread()); QXmppMessage msg(createPacket(data, sendTime, originalId));
#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 3, 0)
msg.setOriginId(id);
#endif
msg.setId(id);
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
msg.setOutOfBandUrl(oob);
msg.setReceiptRequested(true);
msg.setStamp(sendTime);
sent = acc->client.sendPacket(msg); sent = acc->client.sendPacket(msg);
//sent = false;
if (sent) { if (sent) {
data.setState(Shared::Message::State::sent); data.setState(Shared::Message::State::sent);
} else { } else {
@ -286,6 +299,39 @@ void Core::MessageHandler::performSending(Shared::Message data, bool newMessage)
data.setErrorText("You are is offline or reconnecting"); data.setErrorText("You are is offline or reconnecting");
} }
QMap<QString, QVariant> changes(getChanges(data, sendTime, newMessage, originalId));
QString realId;
if (originalId.size() > 0) {
realId = originalId;
} else {
realId = id;
}
if (ri != 0) {
if (newMessage) {
ri->appendMessageToArchive(data);
} else {
ri->changeMessage(realId, changes);
}
if (sent) {
pendingStateMessages.insert(std::make_pair(id, jid));
if (originalId.size() > 0) {
pendingCorrectionMessages.insert(std::make_pair(id, originalId));
}
} else {
pendingStateMessages.erase(id);
pendingCorrectionMessages.erase(id);
}
}
emit acc->changeMessage(jid, realId, changes);
}
QMap<QString, QVariant> Core::MessageHandler::getChanges(Shared::Message& data, const QDateTime& time, bool newMessage, const QString& originalId) const
{
QMap<QString, QVariant> changes;
QString oob = data.getOutOfBandUrl();
Shared::Message::State mstate = data.getState(); Shared::Message::State mstate = data.getState();
changes.insert("state", static_cast<uint>(mstate)); changes.insert("state", static_cast<uint>(mstate));
if (mstate == Shared::Message::State::error) { if (mstate == Shared::Message::State::error) {
@ -295,9 +341,12 @@ void Core::MessageHandler::performSending(Shared::Message data, bool newMessage)
changes.insert("outOfBandUrl", oob); changes.insert("outOfBandUrl", oob);
} }
if (newMessage) { if (newMessage) {
data.setTime(sendTime); data.setTime(time);
} }
changes.insert("stamp", sendTime); if (originalId.size() > 0) {
changes.insert("body", data.getBody());
}
changes.insert("stamp", time);
//sometimes (when the image is pasted with ctrl+v) //sometimes (when the image is pasted with ctrl+v)
//I start sending message with one path, then copy it to downloads directory //I start sending message with one path, then copy it to downloads directory
@ -310,21 +359,29 @@ void Core::MessageHandler::performSending(Shared::Message data, bool newMessage)
data.setAttachPath(squawkified); data.setAttachPath(squawkified);
} }
} }
if (ri != 0) { return changes;
if (newMessage) { }
ri->appendMessageToArchive(data);
} else { QXmppMessage Core::MessageHandler::createPacket(const Shared::Message& data, const QDateTime& time, const QString& originalId) const
ri->changeMessage(id, changes); {
} QXmppMessage msg(acc->getFullJid(), data.getTo(), data.getBody(), data.getThread());
if (sent) { QString id(data.getId());
pendingStateMessages.insert(std::make_pair(id, jid));
} else { if (originalId.size() > 0) {
pendingStateMessages.erase(id); msg.setReplaceId(originalId);
}
} }
emit acc->changeMessage(jid, id, changes); #if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 3, 0)
msg.setOriginId(id);
#endif
msg.setId(id);
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
msg.setOutOfBandUrl(data.getOutOfBandUrl());
msg.setReceiptRequested(true);
msg.setStamp(time);
return msg;
} }
void Core::MessageHandler::prepareUpload(const Shared::Message& data, bool newMessage) void Core::MessageHandler::prepareUpload(const Shared::Message& data, bool newMessage)
@ -444,7 +501,8 @@ void Core::MessageHandler::onLoadFileError(const std::list<Shared::MessageInfo>&
void Core::MessageHandler::handleUploadError(const QString& jid, const QString& messageId, const QString& errorText) void Core::MessageHandler::handleUploadError(const QString& jid, const QString& messageId, const QString& errorText)
{ {
emit acc->uploadFileError(jid, messageId, "Error requesting slot to upload file: " + errorText); emit acc->uploadFileError(jid, messageId, "Error requesting slot to upload file: " + errorText);
pendingStateMessages.erase(jid); pendingStateMessages.erase(messageId);
pendingCorrectionMessages.erase(messageId);
requestChangeMessage(jid, messageId, { requestChangeMessage(jid, messageId, {
{"state", static_cast<uint>(Shared::Message::State::error)}, {"state", static_cast<uint>(Shared::Message::State::error)},
{"errorText", errorText} {"errorText", errorText}
@ -473,11 +531,11 @@ void Core::MessageHandler::sendMessageWithLocalUploadedFile(Shared::Message msg,
if (msg.getBody().size() == 0) { //not sure why, but most messages do that if (msg.getBody().size() == 0) { //not sure why, but most messages do that
msg.setBody(url); //they duplicate oob in body, some of them wouldn't even show an attachment if you don't do that msg.setBody(url); //they duplicate oob in body, some of them wouldn't even show an attachment if you don't do that
} }
performSending(msg, newMessage); performSending(msg, pendingCorrectionMessages.at(msg.getId()), newMessage);
//TODO removal/progress update //TODO removal/progress update
} }
static const std::set<QString> allowerToChangeKeys({ static const std::set<QString> allowedToChangeKeys({
"attachPath", "attachPath",
"outOfBandUrl", "outOfBandUrl",
"state", "state",
@ -490,12 +548,12 @@ void Core::MessageHandler::requestChangeMessage(const QString& jid, const QStrin
if (cnt != 0) { if (cnt != 0) {
bool allSupported = true; bool allSupported = true;
QString unsupportedString; QString unsupportedString;
for (QMap<QString, QVariant>::const_iterator itr = data.begin(); itr != data.end(); ++itr) { //I need all this madness for (QMap<QString, QVariant>::const_iterator itr = data.begin(); itr != data.end(); ++itr) { //I need all this madness
if (allowerToChangeKeys.count(itr.key()) != 1) { //to not allow this method if (allowedToChangeKeys.count(itr.key()) != 1) { //to not allow this method
allSupported = false; //to make a message to look like if it was edited allSupported = false; //to make a message to look like if it was edited
unsupportedString = itr.key(); //basically I needed to control who exaclty calls this method unsupportedString = itr.key(); //basically I needed to control who exaclty calls this method
break; //because the underlying tech assumes that the change is initiated by user break; //because the underlying tech assumes that
} //not by system } //the change is initiated by user, not by system
} }
if (allSupported) { if (allSupported) {
cnt->changeMessage(messageId, data); cnt->changeMessage(messageId, data);
@ -514,7 +572,13 @@ void Core::MessageHandler::resendMessage(const QString& jid, const QString& id)
try { try {
Shared::Message msg = cnt->getMessage(id); Shared::Message msg = cnt->getMessage(id);
if (msg.getState() == Shared::Message::State::error) { if (msg.getState() == Shared::Message::State::error) {
sendMessage(msg, false); if (msg.getEdited()){
QString originalId = msg.getId();
msg.generateRandomId();
sendMessage(msg, false, originalId);
} else {
sendMessage(msg, false);
}
} else { } else {
qDebug() << "An attempt to resend a message to" << jid << "by account" << acc->getName() << ", but this message seems to have been normally sent, this method was made to retry sending failed to be sent messages, skipping"; qDebug() << "An attempt to resend a message to" << jid << "by account" << acc->getName() << ", but this message seems to have been normally sent, this method was made to retry sending failed to be sent messages, skipping";
} }

View File

@ -46,7 +46,7 @@ public:
MessageHandler(Account* account); MessageHandler(Account* account);
public: public:
void sendMessage(const Shared::Message& data, bool newMessage = true); void sendMessage(const Shared::Message& data, bool newMessage = true, QString originalId = "");
void initializeMessage(Shared::Message& target, const QXmppMessage& source, bool outgoing = false, bool forwarded = false, bool guessing = false) const; void initializeMessage(Shared::Message& target, const QXmppMessage& source, bool outgoing = false, bool forwarded = false, bool guessing = false) const;
void resendMessage(const QString& jid, const QString& id); void resendMessage(const QString& jid, const QString& id);
@ -67,13 +67,17 @@ private:
bool handleGroupMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false); bool handleGroupMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false);
void logMessage(const QXmppMessage& msg, const QString& reason = "Message wasn't handled: "); void logMessage(const QXmppMessage& msg, const QString& reason = "Message wasn't handled: ");
void sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url, bool newMessage = true); void sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url, bool newMessage = true);
void performSending(Shared::Message data, bool newMessage = true); void performSending(Shared::Message data, const QString& originalId, bool newMessage = true);
void prepareUpload(const Shared::Message& data, bool newMessage = true); void prepareUpload(const Shared::Message& data, bool newMessage = true);
void handleUploadError(const QString& jid, const QString& messageId, const QString& errorText); void handleUploadError(const QString& jid, const QString& messageId, const QString& errorText);
QXmppMessage createPacket(const Shared::Message& data, const QDateTime& time, const QString& originalId) const;
QMap<QString, QVariant> getChanges(Shared::Message& data, const QDateTime& time, bool newMessage, const QString& originalId) const;
std::tuple<bool, QString, QString> getOriginalPendingMessageId(const QString& id);
private: private:
Account* acc; Account* acc;
std::map<QString, QString> pendingStateMessages; //key is message id, value is JID std::map<QString, QString> pendingStateMessages; //key is message id, value is JID
std::map<QString, QString> pendingCorrectionMessages; //key is new mesage, value is originalOne
std::deque<std::pair<QString, QString>> uploadingSlotsQueue; std::deque<std::pair<QString, QString>> uploadingSlotsQueue;
}; };

View File

@ -142,6 +142,7 @@ int main(int argc, char *argv[])
QObject::connect(&w, &Squawk::disconnectAccount, squawk, &Core::Squawk::disconnectAccount); QObject::connect(&w, &Squawk::disconnectAccount, squawk, &Core::Squawk::disconnectAccount);
QObject::connect(&w, &Squawk::changeState, squawk, &Core::Squawk::changeState); QObject::connect(&w, &Squawk::changeState, squawk, &Core::Squawk::changeState);
QObject::connect(&w, &Squawk::sendMessage, squawk,&Core::Squawk::sendMessage); QObject::connect(&w, &Squawk::sendMessage, squawk,&Core::Squawk::sendMessage);
QObject::connect(&w, &Squawk::replaceMessage, squawk,&Core::Squawk::replaceMessage);
QObject::connect(&w, &Squawk::resendMessage, squawk,&Core::Squawk::resendMessage); QObject::connect(&w, &Squawk::resendMessage, squawk,&Core::Squawk::resendMessage);
QObject::connect(&w, &Squawk::requestArchive, squawk, &Core::Squawk::requestArchive); QObject::connect(&w, &Squawk::requestArchive, squawk, &Core::Squawk::requestArchive);
QObject::connect(&w, &Squawk::subscribeContact, squawk, &Core::Squawk::subscribeContact); QObject::connect(&w, &Squawk::subscribeContact, squawk, &Core::Squawk::subscribeContact);

View File

@ -341,6 +341,17 @@ void Core::Squawk::sendMessage(const QString& account, const Shared::Message& da
itr->second->sendMessage(data); itr->second->sendMessage(data);
} }
void Core::Squawk::replaceMessage(const QString& account, const QString& originalId, const Shared::Message& data)
{
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug() << "An attempt to replace a message with non existing account" << account << ", skipping";
return;
}
itr->second->replaceMessage(originalId, data);
}
void Core::Squawk::resendMessage(const QString& account, const QString& jid, const QString& id) void Core::Squawk::resendMessage(const QString& account, const QString& jid, const QString& id)
{ {
AccountsMap::const_iterator itr = amap.find(account); AccountsMap::const_iterator itr = amap.find(account);

View File

@ -101,6 +101,7 @@ public slots:
void changeState(Shared::Availability state); void changeState(Shared::Availability state);
void sendMessage(const QString& account, const Shared::Message& data); void sendMessage(const QString& account, const Shared::Message& data);
void replaceMessage(const QString& account, const QString& originalId, const Shared::Message& data);
void resendMessage(const QString& account, const QString& jid, const QString& id); void resendMessage(const QString& account, const QString& jid, const QString& id);
void requestArchive(const QString& account, const QString& jid, int count, const QString& before); void requestArchive(const QString& account, const QString& jid, int count, const QString& before);

View File

@ -404,7 +404,9 @@ bool Shared::Message::change(const QMap<QString, QVariant>& data)
correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied
} }
if (!edited || lastModified < correctionDate) { if (!edited || lastModified < correctionDate) {
originalMessage = body; if (!edited) {
originalMessage = body;
}
lastModified = correctionDate; lastModified = correctionDate;
setBody(b); setBody(b);
setEdited(true); setEdited(true);

View File

@ -497,6 +497,17 @@ void Squawk::onConversationMessage(const Shared::Message& msg)
emit sendMessage(acc, msg); emit sendMessage(acc, msg);
} }
void Squawk::onConversationReplaceMessage(const QString& originalId, const Shared::Message& msg)
{
Conversation* conv = static_cast<Conversation*>(sender());
QString acc = conv->getAccount();
rosterModel.changeMessage(acc, msg.getPenPalJid(), originalId, {
{"state", static_cast<uint>(Shared::Message::State::pending)}
});
emit replaceMessage(acc, originalId, msg);
}
void Squawk::onConversationResend(const QString& id) void Squawk::onConversationResend(const QString& id)
{ {
Conversation* conv = static_cast<Conversation*>(sender()); Conversation* conv = static_cast<Conversation*>(sender());
@ -958,6 +969,7 @@ void Squawk::subscribeConversation(Conversation* conv)
{ {
connect(conv, &Conversation::destroyed, this, &Squawk::onConversationClosed); connect(conv, &Conversation::destroyed, this, &Squawk::onConversationClosed);
connect(conv, &Conversation::sendMessage, this, &Squawk::onConversationMessage); connect(conv, &Conversation::sendMessage, this, &Squawk::onConversationMessage);
connect(conv, &Conversation::replaceMessage, this, &Squawk::onConversationReplaceMessage);
connect(conv, &Conversation::resendMessage, this, &Squawk::onConversationResend); connect(conv, &Conversation::resendMessage, this, &Squawk::onConversationResend);
connect(conv, &Conversation::notifyableMessage, this, &Squawk::notify); connect(conv, &Conversation::notifyableMessage, this, &Squawk::notify);
} }

View File

@ -62,6 +62,7 @@ signals:
void disconnectAccount(const QString&); void disconnectAccount(const QString&);
void changeState(Shared::Availability state); void changeState(Shared::Availability state);
void sendMessage(const QString& account, const Shared::Message& data); void sendMessage(const QString& account, const Shared::Message& data);
void replaceMessage(const QString& account, const QString& originalId, const Shared::Message& data);
void resendMessage(const QString& account, const QString& jid, const QString& id); void resendMessage(const QString& account, const QString& jid, const QString& id);
void requestArchive(const QString& account, const QString& jid, int count, const QString& before); void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
void subscribeContact(const QString& account, const QString& jid, const QString& reason); void subscribeContact(const QString& account, const QString& jid, const QString& reason);
@ -153,6 +154,7 @@ private slots:
void onComboboxActivated(int index); void onComboboxActivated(int index);
void onRosterItemDoubleClicked(const QModelIndex& item); void onRosterItemDoubleClicked(const QModelIndex& item);
void onConversationMessage(const Shared::Message& msg); void onConversationMessage(const Shared::Message& msg);
void onConversationReplaceMessage(const QString& originalId, const Shared::Message& msg);
void onConversationResend(const QString& id); void onConversationResend(const QString& id);
void onRequestArchive(const QString& account, const QString& jid, const QString& before); void onRequestArchive(const QString& account, const QString& jid, const QString& before);
void onRosterContextMenu(const QPoint& point); void onRosterContextMenu(const QPoint& point);

View File

@ -58,7 +58,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
pasteImageAction(new QAction(tr("Paste Image"), this)), pasteImageAction(new QAction(tr("Paste Image"), this)),
shadow(10, 1, Qt::black, this), shadow(10, 1, Qt::black, this),
contextMenu(new QMenu()), contextMenu(new QMenu()),
currentAction(CurrentAction::none) currentAction(CurrentAction::none),
currentMessageId()
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -84,11 +85,11 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
statusIcon = m_ui->statusIcon; statusIcon = m_ui->statusIcon;
statusLabel = m_ui->statusLabel; statusLabel = m_ui->statusLabel;
connect(&ker, &KeyEnterReceiver::enterPressed, this, &Conversation::onEnterPressed); connect(&ker, &KeyEnterReceiver::enterPressed, this, qOverload<>(&Conversation::initiateMessageSending));
connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted); connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted);
connect(m_ui->sendButton, &QPushButton::clicked, this, &Conversation::onEnterPressed); connect(m_ui->sendButton, &QPushButton::clicked, this, qOverload<>(&Conversation::initiateMessageSending));
connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach); connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach);
connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::onClearButton); connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::clear);
connect(m_ui->messageEditor->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, connect(m_ui->messageEditor->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged,
this, &Conversation::onTextEditDocSizeChanged); this, &Conversation::onTextEditDocSizeChanged);
@ -98,6 +99,9 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, &Conversation::onMessageEditorContext); connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, &Conversation::onMessageEditorContext);
connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted); connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted);
connect(m_ui->currentActionBadge, &Badge::close, this, &Conversation::clear);
m_ui->currentActionBadge->setVisible(false);
//line->setAutoFillBackground(false); //line->setAutoFillBackground(false);
//if (testAttribute(Qt::WA_TranslucentBackground)) { //if (testAttribute(Qt::WA_TranslucentBackground)) {
//m_ui->scrollArea->setAutoFillBackground(false); //m_ui->scrollArea->setAutoFillBackground(false);
@ -109,9 +113,6 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
//line->setMyName(acc->getName()); //line->setMyName(acc->getName());
initializeOverlay(); initializeOverlay();
m_ui->currentActionBadge->setVisible(false);
// m_ui->currentActionBadge->setText(tr("Editing message..."));
} }
Conversation::~Conversation() Conversation::~Conversation()
@ -224,24 +225,33 @@ void Conversation::setPalResource(const QString& res)
activePalResource = res; activePalResource = res;
} }
void Conversation::onEnterPressed() void Conversation::initiateMessageSending()
{ {
QString body(m_ui->messageEditor->toPlainText()); QString body(m_ui->messageEditor->toPlainText());
if (body.size() > 0) { if (body.size() > 0) {
m_ui->messageEditor->clear();
Shared::Message msg = createMessage(); Shared::Message msg = createMessage();
msg.setBody(body); msg.setBody(body);
emit sendMessage(msg); initiateMessageSending(msg);
} }
if (filesToAttach.size() > 0) { if (filesToAttach.size() > 0) {
for (Badge* badge : filesToAttach) { for (Badge* badge : filesToAttach) {
Shared::Message msg = createMessage(); Shared::Message msg = createMessage();
msg.setAttachPath(badge->id); msg.setAttachPath(badge->id);
element->feed->registerUpload(msg.getId()); element->feed->registerUpload(msg.getId());
emit sendMessage(msg); initiateMessageSending(msg);
} }
clearAttachedFiles(); }
clear();
}
void Conversation::initiateMessageSending(const Shared::Message& msg)
{
if (currentAction == CurrentAction::edit) {
emit replaceMessage(currentMessageId, msg);
currentAction = CurrentAction::none;
} else {
emit sendMessage(msg);
} }
} }
@ -348,8 +358,11 @@ void Conversation::clearAttachedFiles()
filesLayout->setContentsMargins(0, 0, 0, 0); filesLayout->setContentsMargins(0, 0, 0, 0);
} }
void Conversation::onClearButton() void Conversation::clear()
{ {
currentMessageId.clear();
currentAction = CurrentAction::none;
m_ui->currentActionBadge->setVisible(false);
clearAttachedFiles(); clearAttachedFiles();
m_ui->messageEditor->clear(); m_ui->messageEditor->clear();
} }
@ -526,13 +539,12 @@ void Conversation::onMessageEditorContext(const QPoint& pos)
void Conversation::onMessageEditRequested(const QString& id) void Conversation::onMessageEditRequested(const QString& id)
{ {
if (currentAction == CurrentAction::edit) { clear();
//todo;
}
try { try {
Shared::Message msg = element->feed->getMessage(id); Shared::Message msg = element->feed->getMessage(id);
currentMessageId = id;
m_ui->currentActionBadge->setVisible(true); m_ui->currentActionBadge->setVisible(true);
m_ui->currentActionBadge->setText(tr("Editing message...")); m_ui->currentActionBadge->setText(tr("Editing message..."));
currentAction = CurrentAction::edit; currentAction = CurrentAction::edit;

View File

@ -83,6 +83,7 @@ public:
signals: signals:
void sendMessage(const Shared::Message& message); void sendMessage(const Shared::Message& message);
void replaceMessage(const QString& originalId, const Shared::Message& message);
void resendMessage(const QString& id); void resendMessage(const QString& id);
void requestArchive(const QString& before); void requestArchive(const QString& before);
void shown(); void shown();
@ -104,12 +105,13 @@ protected:
virtual void onMessage(const Shared::Message& msg); virtual void onMessage(const Shared::Message& msg);
protected slots: protected slots:
void onEnterPressed(); void initiateMessageSending();
void initiateMessageSending(const Shared::Message& msg);
void onImagePasted(); void onImagePasted();
void onAttach(); void onAttach();
void onFileSelected(); void onFileSelected();
void onBadgeClose(); void onBadgeClose();
void onClearButton(); void clear();
void onTextEditDocSizeChanged(const QSizeF& size); void onTextEditDocSizeChanged(const QSizeF& size);
void onAccountChanged(Models::Item* item, int row, int col); void onAccountChanged(Models::Item* item, int row, int col);
void onFeedMessage(const Shared::Message& msg); void onFeedMessage(const Shared::Message& msg);
@ -149,6 +151,7 @@ protected:
ShadowOverlay shadow; ShadowOverlay shadow;
QMenu* contextMenu; QMenu* contextMenu;
CurrentAction currentAction; CurrentAction currentAction;
QString currentMessageId;
private: private:
static bool painterInitialized; static bool painterInitialized;