Commit 9964d9b9 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

conversation: handle displayed status

Change-Id: I96c5468e2c02124135f42bee98d7944107405f4b
parent 559bbba0
......@@ -42,6 +42,7 @@ struct Info
QString confId;
std::map<uint64_t, interaction::Info> interactions;
uint64_t lastMessageUid = 0;
std::map<QString, uint64_t> lastDisplayedMessageUid;
unsigned int unreadMessages = 0;
};
......
......@@ -203,6 +203,13 @@ public:
* @param interactionId
*/
void retryInteraction(const QString& convId, const uint64_t& interactionId);
/**
* @param convId
* @param interactionId
* @param participant uri
* @return whether the interaction is last displayed for the conversation
*/
bool isLastDisplayed(const QString& convId, const uint64_t& interactionId, const QString participant);
/**
* delete obsolete history from the database
* @param days, number of days from today. Below this date, interactions will be deleted
......@@ -300,6 +307,15 @@ Q_SIGNALS:
* @param isComposing if contact is composing a message
*/
void composingStatusChanged(const QString& uid, const QString& contactUri, bool isComposing) const;
/**
* Emitted when last displayed interaction changed
* @param uid of conversation
* @param participant URI
* @param previousUid uid of a previous displayed interaction
* @param newdUid uid of a new displayed interaction
*/
void displayedInteractionChanged(const QString& uid, const QString& participantURI,
const uint64_t previousUid, const uint64_t newdUid) const;
private:
std::unique_ptr<ConversationModelPimpl> pimpl_;
......
......@@ -80,6 +80,7 @@ enum class Status {
SENDING,
FAILURE,
SUCCESS,
DISPLAYED,
TRANSFER_CREATED,
TRANSFER_ACCEPTED,
TRANSFER_CANCELED,
......@@ -105,6 +106,8 @@ to_string(const Status& status)
return "FAILURE";
case Status::SUCCESS:
return "SUCCESS";
case Status::DISPLAYED:
return "DISPLAYED";
case Status::TRANSFER_CREATED:
return "TRANSFER_CREATED";
case Status::TRANSFER_ACCEPTED:
......@@ -143,6 +146,8 @@ to_status(const QString& status)
return Status::FAILURE;
else if (status == "SUCCESS")
return Status::SUCCESS;
else if (status == "DISPLAYED")
return Status::DISPLAYED;
else if (status == "TRANSFER_CREATED")
return Status::TRANSFER_CREATED;
else if (status == "TRANSFER_ACCEPTED")
......
......@@ -420,6 +420,25 @@ getHistory(Database& db, api::conversation::Info& conversation)
});
conversation.interactions.emplace(std::stoull(payloads[i].toStdString()), std::move(msg));
conversation.lastMessageUid = std::stoull(payloads[i].toStdString());
if (status != api::interaction::Status::DISPLAYED ||
!payloads[i + 1].isEmpty()) {
continue;
}
auto messageId = conversation.lastDisplayedMessageUid.find(conversation.participants.front());
if (messageId == conversation.lastDisplayedMessageUid.end()) {
conversation.lastDisplayedMessageUid
.emplace(conversation.participants.front(),
std::stoull(payloads[i].toStdString()));
continue;
}
auto lastReadInteraction = conversation.interactions
.find(messageId->second);
auto timestamp = std::stoi(payloads[i + 3].toStdString());
if (lastReadInteraction == conversation.interactions.end() ||
lastReadInteraction->second.timestamp < timestamp) {
conversation.lastDisplayedMessageUid
.at(conversation.participants.front()) = std::stoull(payloads[i].toStdString());
}
}
}
}
......
......@@ -999,6 +999,9 @@ ConversationModel::clearInteractionFromConversation(const QString& convId, const
auto erased_keys = 0;
bool lastInteractionUpdated = false;
bool updateDisplayedUid = false;
uint64_t newDisplayedUid = 0;
QString participantURI = "";
{
std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]);
try
......@@ -1006,6 +1009,23 @@ ConversationModel::clearInteractionFromConversation(const QString& convId, const
auto& conversation = pimpl_->conversations.at(conversationIdx);
storage::clearInteractionFromConversation(pimpl_->db, convId, interactionId);
erased_keys = conversation.interactions.erase(interactionId);
auto messageId = conversation.lastDisplayedMessageUid
.find(conversation.participants.front());
if (messageId != conversation.lastDisplayedMessageUid.end() &&
messageId->second == interactionId) {
// Update lastDisplayedMessageUid
for (auto iter = conversation.interactions.find(interactionId); iter != conversation.interactions.end(); --iter) {
if (isOutgoing(iter->second) && iter->first != interactionId) {
newDisplayedUid = iter->first;
break;
}
}
updateDisplayedUid = true;
participantURI = conversation.participants.front();
conversation.lastDisplayedMessageUid
.at(conversation.participants.front()) = newDisplayedUid;
}
if (conversation.lastMessageUid == interactionId) {
// Update lastMessageUid
......@@ -1020,6 +1040,9 @@ ConversationModel::clearInteractionFromConversation(const QString& convId, const
qDebug() << "can't clear interaction from conversation: " << e.what();
}
}
if (updateDisplayedUid) {
emit displayedInteractionChanged(convId, participantURI, interactionId, newDisplayedUid);
}
if (erased_keys > 0) {
pimpl_->dirtyConversations.first = true;
emit interactionRemoved(convId, interactionId);
......@@ -1080,6 +1103,20 @@ ConversationModel::retryInteraction(const QString& convId, const uint64_t& inter
}
}
bool
ConversationModel::isLastDisplayed(const QString& convId, const uint64_t& interactionId, const QString participant)
{
auto conversationIdx = pimpl_->indexOf(convId);
if (conversationIdx == -1)
return false;
try {
auto& conversation = pimpl_->conversations.at(conversationIdx);
return conversation.lastDisplayedMessageUid.find(participant)->second == interactionId;
} catch (const std::out_of_range& e) {
return false;
}
}
void
ConversationModel::clearAllHistory()
{
......@@ -1901,12 +1938,14 @@ ConversationModelPimpl::slotUpdateInteractionStatus(const QString& accountId,
newStatus = interaction::Status::TRANSFER_CANCELED;
break;
case DRing::Account::MessageStates::SENT:
case DRing::Account::MessageStates::DISPLAYED:
newStatus = interaction::Status::SUCCESS;
break;
case DRing::Account::MessageStates::FAILURE:
newStatus = interaction::Status::FAILURE;
break;
case DRing::Account::MessageStates::DISPLAYED:
newStatus = interaction::Status::DISPLAYED;
break;
case DRing::Account::MessageStates::UNKNOWN:
default:
newStatus = interaction::Status::UNKNOWN;
......@@ -1925,16 +1964,34 @@ ConversationModelPimpl::slotUpdateInteractionStatus(const QString& accountId,
auto conversationIdx = indexOf(convIds[0]);
interaction::Info itCopy;
bool emitUpdated = false;
bool updateDisplayedUid = false;
uint64_t oldDisplayedUid = 0;
if (conversationIdx != -1) {
std::lock_guard<std::mutex> lk(interactionsLocks[conversations[conversationIdx].uid]);
auto& interactions = conversations[conversationIdx].interactions;
auto it = interactions.find(msgId);
auto messageId = conversations[conversationIdx].lastDisplayedMessageUid.find(peer_uri);
if (it != interactions.end()) {
it->second.status = newStatus;
if (messageId != conversations[conversationIdx].lastDisplayedMessageUid.end()) {
auto lastDisplayedIt = interactions.find(messageId->second);
bool interactionDisplayed = newStatus == interaction::Status::DISPLAYED
&& isOutgoing(it->second);
bool interactionIsLast = lastDisplayedIt == interactions.end() ||
lastDisplayedIt->second.timestamp < it->second.timestamp;
updateDisplayedUid = interactionDisplayed && interactionIsLast;
if (updateDisplayedUid) {
oldDisplayedUid = messageId->second;
conversations[conversationIdx].lastDisplayedMessageUid.at(peer_uri) = it->first;
}
}
emitUpdated = true;
itCopy = it->second;
}
}
if (updateDisplayedUid) {
emit linked.displayedInteractionChanged(convIds[0], peer_uri, oldDisplayedUid, msgId);
}
if (emitUpdated) {
dirtyConversations = { true, true };
emit linked.interactionStatusUpdated(convIds[0], msgId, itCopy);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment