diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index a5b76284b..01ffbd175 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -114,6 +114,10 @@ using PhotoFileLocationId = Data::PhotoFileLocationId; using DocumentFileLocationId = Data::DocumentFileLocationId; using UpdatedFileReferences = Data::UpdatedFileReferences; +[[nodiscard]] TimeId UnixtimeFromMsgId(mtpMsgId msgId) { + return TimeId(msgId << 32); +} + } // namespace MTPInputPrivacyKey ApiWrap::Privacy::Input(Key key) { @@ -2445,38 +2449,41 @@ void ApiWrap::saveDraftsToCloud() { TextUtilities::ConvertTextTagsToEntities(textWithTags.tags), Api::ConvertOption::SkipLocal); - const auto draftText = textWithTags.text; - history->setSentDraftText(draftText); + history->startSavingCloudDraft(); cloudDraft->saveRequestId = request(MTPmessages_SaveDraft( MTP_flags(flags), MTP_int(cloudDraft->msgId), history->peer->input, MTP_string(textWithTags.text), entities - )).done([=](const MTPBool &result, mtpRequestId requestId) { - history->clearSentDraftText(draftText); + )).done([=](const MTPBool &result, const MTP::Response &response) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); if (const auto cloudDraft = history->cloudDraft()) { - if (cloudDraft->saveRequestId == requestId) { + if (cloudDraft->saveRequestId == response.requestId) { cloudDraft->saveRequestId = 0; history->draftSavedToCloud(); } } auto i = _draftsSaveRequestIds.find(history); - if (i != _draftsSaveRequestIds.cend() && i->second == requestId) { + if (i != _draftsSaveRequestIds.cend() + && i->second == response.requestId) { _draftsSaveRequestIds.erase(history); checkQuitPreventFinished(); } - }).fail([=](const RPCError &error, mtpRequestId requestId) { - history->clearSentDraftText(draftText); + }).fail([=](const RPCError &error, const MTP::Response &response) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); if (const auto cloudDraft = history->cloudDraft()) { - if (cloudDraft->saveRequestId == requestId) { + if (cloudDraft->saveRequestId == response.requestId) { history->clearCloudDraft(); } } auto i = _draftsSaveRequestIds.find(history); - if (i != _draftsSaveRequestIds.cend() && i->second == requestId) { + if (i != _draftsSaveRequestIds.cend() + && i->second == response.requestId) { _draftsSaveRequestIds.erase(history); checkQuitPreventFinished(); } @@ -4027,10 +4034,11 @@ void ApiWrap::sendMessage(MessageToSend &&message) { if (!sentEntities.v.isEmpty()) { sendFlags |= MTPmessages_SendMessage::Flag::f_entities; } - if (action.clearDraft) { + const auto clearCloudDraft = action.clearDraft; + if (clearCloudDraft) { sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft; history->clearCloudDraft(); - history->setSentDraftText(QString()); + history->startSavingCloudDraft(); } auto messageFromId = anonymousPost ? 0 : _session->userPeerId(); auto messagePostAuthor = peer->isBroadcast() @@ -4080,17 +4088,27 @@ void ApiWrap::sendMessage(MessageToSend &&message) { MTPReplyMarkup(), sentEntities, MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { + )).done([=]( + const MTPUpdates &result, + const MTP::Response &response) { applyUpdates(result, randomId); - history->clearSentDraftText(QString()); + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } finish(); - }).fail([=](const RPCError &error) { + }).fail([=]( + const RPCError &error, + const MTP::Response &response) { if (error.type() == qstr("MESSAGE_EMPTY")) { lastMessage->destroy(); } else { sendMessageFail(error, peer, randomId, newId); } - history->clearSentDraftText(QString()); + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } finish(); }).afterRequest(history->sendRequestId ).send(); @@ -4188,7 +4206,7 @@ void ApiWrap::sendInlineResult( messagePostAuthor); history->clearCloudDraft(); - history->setSentDraftText(QString()); + history->startSavingCloudDraft(); auto &histories = history->owner().histories(); const auto requestType = Data::Histories::RequestType::Send; @@ -4201,13 +4219,19 @@ void ApiWrap::sendInlineResult( MTP_long(data->getQueryId()), MTP_string(data->getId()), MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { + )).done([=]( + const MTPUpdates &result, + const MTP::Response &response) { applyUpdates(result, randomId); - history->clearSentDraftText(QString()); + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); finish(); - }).fail([=](const RPCError &error) { + }).fail([=]( + const RPCError &error, + const MTP::Response &response) { sendMessageFail(error, peer, randomId, newId); - history->clearSentDraftText(QString()); + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); finish(); }).afterRequest(history->sendRequestId ).send(); @@ -4894,10 +4918,12 @@ void ApiWrap::createPoll( if (action.replyTo) { sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; } - if (action.clearDraft) { + const auto clearCloudDraft = action.clearDraft; + if (clearCloudDraft) { sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; history->clearLocalDraft(); history->clearCloudDraft(); + history->startSavingCloudDraft(); } const auto silentPost = ShouldSendSilent(peer, action.options); if (silentPost) { @@ -4920,8 +4946,14 @@ void ApiWrap::createPoll( MTPReplyMarkup(), MTPVector(), MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) mutable { + )).done([=]( + const MTPUpdates &result, + const MTP::Response &response) mutable { applyUpdates(result); + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } _session->changes().historyUpdated( history, (action.options.scheduled @@ -4929,7 +4961,13 @@ void ApiWrap::createPoll( : Data::HistoryUpdate::Flag::MessageSent)); done(); finish(); - }).fail([=](const RPCError &error) mutable { + }).fail([=]( + const RPCError &error, + const MTP::Response &response) mutable { + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } fail(error); finish(); }).afterRequest(history->sendRequestId diff --git a/Telegram/SourceFiles/data/data_drafts.cpp b/Telegram/SourceFiles/data/data_drafts.cpp index ef649ad83..eaeb3ec21 100644 --- a/Telegram/SourceFiles/data/data_drafts.cpp +++ b/Telegram/SourceFiles/data/data_drafts.cpp @@ -48,7 +48,11 @@ void ApplyPeerCloudDraft( PeerId peerId, const MTPDdraftMessage &draft) { const auto history = session->data().history(peerId); - const auto textWithTags = TextWithTags { + const auto date = draft.vdate().v; + if (history->skipCloudDraftUpdate(date)) { + return; + } + const auto textWithTags = TextWithTags{ qs(draft.vmessage()), TextUtilities::ConvertEntitiesToTextTags( Api::EntitiesFromMTP( @@ -56,9 +60,6 @@ void ApplyPeerCloudDraft( draft.ventities().value_or_empty())) }; const auto replyTo = draft.vreply_to_msg_id().value_or_empty(); - if (history->skipCloudDraft(textWithTags.text, replyTo, draft.vdate().v)) { - return; - } auto cloudDraft = std::make_unique( textWithTags, replyTo, @@ -66,7 +67,7 @@ void ApplyPeerCloudDraft( (draft.is_no_webpage() ? Data::PreviewState::Cancelled : Data::PreviewState::Allowed)); - cloudDraft->date = draft.vdate().v; + cloudDraft->date = date; history->setCloudDraft(std::move(cloudDraft)); history->applyCloudDraft(); @@ -77,7 +78,7 @@ void ClearPeerCloudDraft( PeerId peerId, TimeId date) { const auto history = session->data().history(peerId); - if (history->skipCloudDraft(QString(), MsgId(0), date)) { + if (history->skipCloudDraftUpdate(date)) { return; } diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index f6195dd62..ed6ab98f3 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -50,7 +50,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace { constexpr auto kNewBlockEachMessage = 50; -constexpr auto kSkipCloudDraftsFor = TimeId(3); +constexpr auto kSkipCloudDraftsFor = TimeId(2); +constexpr auto kSendingDraftTime = TimeId(-1); using UpdateFlag = Data::HistoryUpdate::Flag; @@ -299,27 +300,21 @@ Data::Draft *History::createCloudDraft(const Data::Draft *fromDraft) { return cloudDraft(); } -bool History::skipCloudDraft(const QString &text, MsgId replyTo, TimeId date) const { - if (Data::draftStringIsEmpty(text) - && !replyTo - && date > 0 - && date <= _lastSentDraftTime + kSkipCloudDraftsFor) { - return true; - } else if (_lastSentDraftText && *_lastSentDraftText == text) { - return true; - } - return false; +bool History::skipCloudDraftUpdate(TimeId date) const { + return (_savingCloudDraftRequests > 0) + || (date < _acceptCloudDraftsAfter); } -void History::setSentDraftText(const QString &text) { - _lastSentDraftText = text; +void History::startSavingCloudDraft() { + ++_savingCloudDraftRequests; } -void History::clearSentDraftText(const QString &text) { - if (_lastSentDraftText && *_lastSentDraftText == text) { - _lastSentDraftText = std::nullopt; +void History::finishSavingCloudDraft(TimeId savedAt) { + if (_savingCloudDraftRequests > 0) { + --_savingCloudDraftRequests; } - accumulate_max(_lastSentDraftTime, base::unixtime::now()); + const auto acceptAfter = savedAt + kSkipCloudDraftsFor; + _acceptCloudDraftsAfter = std::max(_acceptCloudDraftsAfter, acceptAfter); } void History::applyCloudDraft() { diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 2dfc0837e..de84e3dcf 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -339,9 +339,9 @@ public: } void clearDrafts(); Data::Draft *createCloudDraft(const Data::Draft *fromDraft); - bool skipCloudDraft(const QString &text, MsgId replyTo, TimeId date) const; - void setSentDraftText(const QString &text); - void clearSentDraftText(const QString &text); + bool skipCloudDraftUpdate(TimeId date) const; + void startSavingCloudDraft(); + void finishSavingCloudDraft(TimeId savedAt); void takeLocalDraft(not_null from); void applyCloudDraft(); void draftSavedToCloud(); @@ -584,8 +584,8 @@ private: std::unique_ptr _buildingFrontBlock; Data::HistoryDrafts _drafts; - std::optional _lastSentDraftText; - TimeId _lastSentDraftTime = 0; + TimeId _acceptCloudDraftsAfter = 0; + int _savingCloudDraftRequests = 0; MessageIdsList _forwardDraft; QString _topPromotedMessage;