mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-28 11:30:54 +00:00
Don't accept drafts older than last saved.
I hope it finally fixes #4922, partially fixes #10001. The rest of #10001 like RAM usage / crashes are unrelated to drafts.
This commit is contained in:
parent
74c21039b3
commit
5794679277
@ -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<MTPMessageEntity>(),
|
||||
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
|
||||
|
@ -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<Draft>(
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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<History*> from);
|
||||
void applyCloudDraft();
|
||||
void draftSavedToCloud();
|
||||
@ -584,8 +584,8 @@ private:
|
||||
std::unique_ptr<BuildingBlock> _buildingFrontBlock;
|
||||
|
||||
Data::HistoryDrafts _drafts;
|
||||
std::optional<QString> _lastSentDraftText;
|
||||
TimeId _lastSentDraftTime = 0;
|
||||
TimeId _acceptCloudDraftsAfter = 0;
|
||||
int _savingCloudDraftRequests = 0;
|
||||
MessageIdsList _forwardDraft;
|
||||
|
||||
QString _topPromotedMessage;
|
||||
|
Loading…
Reference in New Issue
Block a user