From f65556acb7e46e3826dbbd9aaa6a954de0a7b0e9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 20 May 2025 20:32:24 +0400 Subject: [PATCH] Support drafts in monoforum sublists. --- Telegram/SourceFiles/api/api_polls.cpp | 9 +- Telegram/SourceFiles/api/api_updates.cpp | 11 +- Telegram/SourceFiles/apiwrap.cpp | 69 ++++++--- Telegram/SourceFiles/data/data_drafts.cpp | 21 ++- Telegram/SourceFiles/data/data_drafts.h | 87 +++++++++--- Telegram/SourceFiles/data/data_forum.cpp | 4 +- .../SourceFiles/data/data_forum_topic.cpp | 3 +- Telegram/SourceFiles/data/data_msg_id.h | 6 +- .../SourceFiles/data/data_saved_messages.cpp | 11 +- .../SourceFiles/data/data_saved_sublist.cpp | 34 +++-- .../SourceFiles/data/data_saved_sublist.h | 2 + Telegram/SourceFiles/data/data_thread.cpp | 7 + Telegram/SourceFiles/data/data_thread.h | 1 + Telegram/SourceFiles/data/data_types.h | 2 - .../SourceFiles/dialogs/ui/dialogs_layout.cpp | 6 +- Telegram/SourceFiles/history/history.cpp | 132 +++++++++++------- Telegram/SourceFiles/history/history.h | 91 ++++++++---- .../SourceFiles/history/history_widget.cpp | 53 ++++--- .../view/controls/compose_controls_common.h | 1 + .../history_view_compose_controls.cpp | 45 ++++-- .../controls/history_view_compose_controls.h | 1 + .../controls/history_view_draft_options.cpp | 6 +- .../controls/history_view_forward_panel.cpp | 27 +++- .../controls/history_view_forward_panel.h | 1 + .../view/history_view_chat_section.cpp | 7 +- Telegram/SourceFiles/mainwidget.cpp | 13 +- .../SourceFiles/storage/storage_account.cpp | 18 ++- .../SourceFiles/support/support_helper.cpp | 19 ++- .../SourceFiles/window/window_peer_menu.cpp | 6 +- .../window/window_session_controller.cpp | 3 +- 30 files changed, 488 insertions(+), 208 deletions(-) diff --git a/Telegram/SourceFiles/api/api_polls.cpp b/Telegram/SourceFiles/api/api_polls.cpp index 398bd1acbc..d6ffaf551d 100644 --- a/Telegram/SourceFiles/api/api_polls.cpp +++ b/Telegram/SourceFiles/api/api_polls.cpp @@ -47,6 +47,7 @@ void Polls::create( const auto topicRootId = action.replyTo.messageId ? action.replyTo.topicRootId : 0; + const auto monoforumPeerId = action.replyTo.monoforumPeerId; auto sendFlags = MTPmessages_SendMedia::Flags(0); if (action.replyTo) { sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; @@ -54,9 +55,9 @@ void Polls::create( const auto clearCloudDraft = action.clearDraft; if (clearCloudDraft) { sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; - history->clearLocalDraft(topicRootId); - history->clearCloudDraft(topicRootId); - history->startSavingCloudDraft(topicRootId); + history->clearLocalDraft(topicRootId, monoforumPeerId); + history->clearCloudDraft(topicRootId, monoforumPeerId); + history->startSavingCloudDraft(topicRootId, monoforumPeerId); } const auto silentPost = ShouldSendSilent(peer, action.options); const auto starsPaid = std::min( @@ -106,6 +107,7 @@ void Polls::create( if (clearCloudDraft) { history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); } _session->changes().historyUpdated( @@ -118,6 +120,7 @@ void Polls::create( if (clearCloudDraft) { history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); } fail(); diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 8efbfd32a1..c3928b6073 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -2687,13 +2687,22 @@ void Updates::feedUpdate(const MTPUpdate &update) { const auto &data = update.c_updateDraftMessage(); const auto peerId = peerFromMTP(data.vpeer()); const auto topicRootId = data.vtop_msg_id().value_or_empty(); + const auto monoforumPeerId = data.vsaved_peer_id() + ? peerFromMTP(*data.vsaved_peer_id()) + : PeerId(); data.vdraft().match([&](const MTPDdraftMessage &data) { - Data::ApplyPeerCloudDraft(&session(), peerId, topicRootId, data); + Data::ApplyPeerCloudDraft( + &session(), + peerId, + topicRootId, + monoforumPeerId, + data); }, [&](const MTPDdraftMessageEmpty &data) { Data::ClearPeerCloudDraft( &session(), peerId, topicRootId, + monoforumPeerId, data.vdate().value_or_empty()); }); } break; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 352319e89e..5f4a5fda8b 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2064,8 +2064,13 @@ void ApiWrap::saveCurrentDraftToCloud() { _session->local().writeDrafts(history); const auto topicRootId = thread->topicRootId(); - const auto localDraft = history->localDraft(topicRootId); - const auto cloudDraft = history->cloudDraft(topicRootId); + const auto monoforumPeerId = thread->monoforumPeerId(); + const auto localDraft = history->localDraft( + topicRootId, + monoforumPeerId); + const auto cloudDraft = history->cloudDraft( + topicRootId, + monoforumPeerId); if (!Data::DraftsAreEqual(localDraft, cloudDraft) && !_session->supportMode()) { saveDraftToCloudDelayed(thread); @@ -2088,15 +2093,22 @@ void ApiWrap::saveDraftsToCloud() { const auto history = thread->owningHistory(); const auto topicRootId = thread->topicRootId(); - auto cloudDraft = history->cloudDraft(topicRootId); - auto localDraft = history->localDraft(topicRootId); + const auto monoforumPeerId = thread->monoforumPeerId(); + auto cloudDraft = history->cloudDraft(topicRootId, monoforumPeerId); + auto localDraft = history->localDraft(topicRootId, monoforumPeerId); if (cloudDraft && cloudDraft->saveRequestId) { request(base::take(cloudDraft->saveRequestId)).cancel(); } if (!_session->supportMode()) { - cloudDraft = history->createCloudDraft(topicRootId, localDraft); + cloudDraft = history->createCloudDraft( + topicRootId, + monoforumPeerId, + localDraft); } else if (!cloudDraft) { - cloudDraft = history->createCloudDraft(topicRootId, nullptr); + cloudDraft = history->createCloudDraft( + topicRootId, + monoforumPeerId, + nullptr); } auto flags = MTPmessages_SaveDraft::Flags(0); @@ -2106,7 +2118,9 @@ void ApiWrap::saveDraftsToCloud() { } else if (!cloudDraft->webpage.url.isEmpty()) { flags |= MTPmessages_SaveDraft::Flag::f_media; } - if (cloudDraft->reply.messageId || cloudDraft->reply.topicRootId) { + if (cloudDraft->reply.messageId + || cloudDraft->reply.topicRootId + || cloudDraft->reply.monoforumPeerId) { flags |= MTPmessages_SaveDraft::Flag::f_reply_to; } if (!textWithTags.tags.isEmpty()) { @@ -2117,7 +2131,7 @@ void ApiWrap::saveDraftsToCloud() { TextUtilities::ConvertTextTagsToEntities(textWithTags.tags), Api::ConvertOption::SkipLocal); - history->startSavingCloudDraft(topicRootId); + history->startSavingCloudDraft(topicRootId, monoforumPeerId); cloudDraft->saveRequestId = request(MTPmessages_SaveDraft( MTP_flags(flags), ReplyToForMTP(history, cloudDraft->reply), @@ -2132,11 +2146,15 @@ void ApiWrap::saveDraftsToCloud() { const auto requestId = response.requestId; history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); - if (const auto cloudDraft = history->cloudDraft(topicRootId)) { + const auto cloudDraft = history->cloudDraft( + topicRootId, + monoforumPeerId); + if (cloudDraft) { if (cloudDraft->saveRequestId == requestId) { cloudDraft->saveRequestId = 0; - history->draftSavedToCloud(topicRootId); + history->draftSavedToCloud(topicRootId, monoforumPeerId); } } const auto i = _draftsSaveRequestIds.find(weak); @@ -2149,10 +2167,14 @@ void ApiWrap::saveDraftsToCloud() { const auto requestId = response.requestId; history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); - if (const auto cloudDraft = history->cloudDraft(topicRootId)) { + const auto cloudDraft = history->cloudDraft( + topicRootId, + monoforumPeerId); + if (cloudDraft) { if (cloudDraft->saveRequestId == requestId) { - history->clearCloudDraft(topicRootId); + history->clearCloudDraft(topicRootId, monoforumPeerId); } } const auto i = _draftsSaveRequestIds.find(weak); @@ -3223,7 +3245,10 @@ void ApiWrap::sendAction(const SendAction &action) { void ApiWrap::finishForwarding(const SendAction &action) { const auto history = action.history; const auto topicRootId = action.replyTo.topicRootId; - auto toForward = history->resolveForwardDraft(topicRootId); + const auto monoforumPeerId = action.replyTo.monoforumPeerId; + auto toForward = history->resolveForwardDraft( + topicRootId, + monoforumPeerId); if (!toForward.items.empty()) { const auto error = GetErrorForSending( history->peer, @@ -3236,7 +3261,7 @@ void ApiWrap::finishForwarding(const SendAction &action) { } forwardMessages(std::move(toForward), action); - history->setForwardDraft(topicRootId, {}); + history->setForwardDraft(topicRootId, monoforumPeerId, {}); } _session->data().sendHistoryChangeNotifications(); @@ -3728,6 +3753,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { const auto clearCloudDraft = action.clearDraft; const auto draftTopicRootId = action.replyTo.topicRootId; + const auto draftMonoforumPeerId = action.replyTo.monoforumPeerId; const auto replyTo = action.replyTo.messageId ? peer->owner().message(action.replyTo.messageId) : nullptr; @@ -3837,8 +3863,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) { if (clearCloudDraft) { sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft; mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; - history->clearCloudDraft(draftTopicRootId); - history->startSavingCloudDraft(draftTopicRootId); + history->clearCloudDraft(draftTopicRootId, draftMonoforumPeerId); + history->startSavingCloudDraft( + draftTopicRootId, + draftMonoforumPeerId); } const auto sendAs = action.options.sendAs; if (sendAs) { @@ -3884,6 +3912,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { if (clearCloudDraft) { history->finishSavingCloudDraft( draftTopicRootId, + draftMonoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); } }; @@ -3898,6 +3927,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { if (clearCloudDraft) { history->finishSavingCloudDraft( draftTopicRootId, + draftMonoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); } }; @@ -4016,6 +4046,7 @@ void ApiWrap::sendInlineResult( const auto topicRootId = action.replyTo.messageId ? action.replyTo.topicRootId : 0; + const auto monoforumPeerId = action.replyTo.monoforumPeerId; using SendFlag = MTPmessages_SendInlineBotResult::Flag; auto flags = NewMessageFlags(peer); @@ -4068,8 +4099,8 @@ void ApiWrap::sendInlineResult( .postAuthor = NewMessagePostAuthor(action), }); - history->clearCloudDraft(topicRootId); - history->startSavingCloudDraft(topicRootId); + history->clearCloudDraft(topicRootId, monoforumPeerId); + history->startSavingCloudDraft(topicRootId, monoforumPeerId); auto &histories = history->owner().histories(); histories.sendPreparedMessage( @@ -4090,6 +4121,7 @@ void ApiWrap::sendInlineResult( ), [=](const MTPUpdates &result, const MTP::Response &response) { history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); if (done) { done(true); @@ -4098,6 +4130,7 @@ void ApiWrap::sendInlineResult( sendMessageFail(error, peer, randomId, newId); history->finishSavingCloudDraft( topicRootId, + monoforumPeerId, UnixtimeFromMsgId(response.outerMsgId)); if (done) { done(false); diff --git a/Telegram/SourceFiles/data/data_drafts.cpp b/Telegram/SourceFiles/data/data_drafts.cpp index 1bd7135e86..ee8d348f9e 100644 --- a/Telegram/SourceFiles/data/data_drafts.cpp +++ b/Telegram/SourceFiles/data/data_drafts.cpp @@ -70,10 +70,11 @@ void ApplyPeerCloudDraft( not_null session, PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, const MTPDdraftMessage &draft) { const auto history = session->data().history(peerId); const auto date = draft.vdate().v; - if (history->skipCloudDraftUpdate(topicRootId, date)) { + if (history->skipCloudDraftUpdate(topicRootId, monoforumPeerId, date)) { return; } const auto textWithTags = TextWithTags{ @@ -87,6 +88,7 @@ void ApplyPeerCloudDraft( ? ReplyToFromMTP(history, *draft.vreply_to()) : FullReplyTo(); replyTo.topicRootId = topicRootId; + replyTo.monoforumPeerId = monoforumPeerId; auto webpage = WebPageDraft{ .invert = draft.is_invert_media(), .removed = draft.is_no_webpage(), @@ -112,21 +114,22 @@ void ApplyPeerCloudDraft( cloudDraft->date = date; history->setCloudDraft(std::move(cloudDraft)); - history->applyCloudDraft(topicRootId); + history->applyCloudDraft(topicRootId, monoforumPeerId); } void ClearPeerCloudDraft( not_null session, PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, TimeId date) { const auto history = session->data().history(peerId); - if (history->skipCloudDraftUpdate(topicRootId, date)) { + if (history->skipCloudDraftUpdate(topicRootId, monoforumPeerId, date)) { return; } - history->clearCloudDraft(topicRootId); - history->applyCloudDraft(topicRootId); + history->clearCloudDraft(topicRootId, monoforumPeerId); + history->applyCloudDraft(topicRootId, monoforumPeerId); } void SetChatLinkDraft(not_null peer, TextWithEntities draft) { @@ -146,12 +149,16 @@ void SetChatLinkDraft(not_null peer, TextWithEntities draft) { }; const auto history = peer->owner().history(peer->id); const auto topicRootId = MsgId(); + const auto monoforumPeerId = PeerId(); history->setLocalDraft(std::make_unique( textWithTags, - FullReplyTo{ .topicRootId = topicRootId }, + FullReplyTo{ + .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, + }, cursor, Data::WebPageDraft())); - history->clearLocalEditDraft(topicRootId); + history->clearLocalEditDraft(topicRootId, monoforumPeerId); history->session().changes().entryUpdated( history, Data::EntryUpdate::Flag::LocalDraftSet); diff --git a/Telegram/SourceFiles/data/data_drafts.h b/Telegram/SourceFiles/data/data_drafts.h index 1330995ed0..ab19e0cb2e 100644 --- a/Telegram/SourceFiles/data/data_drafts.h +++ b/Telegram/SourceFiles/data/data_drafts.h @@ -23,11 +23,13 @@ void ApplyPeerCloudDraft( not_null session, PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, const MTPDdraftMessage &draft); void ClearPeerCloudDraft( not_null session, PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, TimeId date); struct WebPageDraft { @@ -72,22 +74,38 @@ public: [[nodiscard]] static constexpr DraftKey None() { return 0; } - [[nodiscard]] static constexpr DraftKey Local(MsgId topicRootId) { - return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) + [[nodiscard]] static constexpr DraftKey Local( + MsgId topicRootId, + PeerId monoforumPeerId) { + return Invalid(topicRootId, monoforumPeerId) ? None() - : (topicRootId ? topicRootId.bare : kLocalDraftIndex); + : (topicRootId + ? topicRootId.bare + : monoforumPeerId + ? (monoforumPeerId.value + kMonoforumDraftBit) + : kLocalDraftIndex); } - [[nodiscard]] static constexpr DraftKey LocalEdit(MsgId topicRootId) { - return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) + [[nodiscard]] static constexpr DraftKey LocalEdit( + MsgId topicRootId, + PeerId monoforumPeerId) { + return Invalid(topicRootId, monoforumPeerId) ? None() - : ((topicRootId ? topicRootId.bare : kLocalDraftIndex) - + kEditDraftShift); + : (kEditDraftShift + + (topicRootId + ? topicRootId.bare + : monoforumPeerId + ? (monoforumPeerId.value + kMonoforumDraftBit) + : kLocalDraftIndex)); } - [[nodiscard]] static constexpr DraftKey Cloud(MsgId topicRootId) { - return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) + [[nodiscard]] static constexpr DraftKey Cloud( + MsgId topicRootId, + PeerId monoforumPeerId) { + return Invalid(topicRootId, monoforumPeerId) ? None() : topicRootId ? (kCloudDraftShift + topicRootId.bare) + : monoforumPeerId + ? (kCloudDraftShift + monoforumPeerId.value + kMonoforumDraftBit) : kCloudDraftIndex; } [[nodiscard]] static constexpr DraftKey Scheduled() { @@ -120,40 +138,62 @@ public: return !value ? None() : (value == kLocalDraftIndex + kEditDraftShiftOld) - ? LocalEdit(0) + ? LocalEdit(MsgId(), PeerId()) : (value == kScheduledDraftIndex + kEditDraftShiftOld) ? ScheduledEdit() : (value > 0 && value < 0x4000'0000) - ? Local(MsgId(value)) + ? Local(MsgId(value), PeerId()) : (value > kEditDraftShiftOld && value < kEditDraftShiftOld + 0x4000'000) - ? LocalEdit(int64(value - kEditDraftShiftOld)) + ? LocalEdit(MsgId(int64(value - kEditDraftShiftOld)), PeerId()) : None(); } [[nodiscard]] constexpr bool isLocal() const { return (_value == kLocalDraftIndex) - || (_value > 0 && _value < ServerMaxMsgId.bare); + || (_value > 0 + && (_value & kMonoforumDraftMask) < ServerMaxMsgId.bare); } [[nodiscard]] constexpr bool isCloud() const { return (_value == kCloudDraftIndex) - || (_value > kCloudDraftShift - && _value < kCloudDraftShift + ServerMaxMsgId.bare); + || ((_value & kMonoforumDraftMask) > kCloudDraftShift + && ((_value & kMonoforumDraftMask) + < kCloudDraftShift + ServerMaxMsgId.bare)); } [[nodiscard]] constexpr MsgId topicRootId() const { const auto max = ServerMaxMsgId.bare; - if (_value > kCloudDraftShift && _value < kCloudDraftShift + max) { + if (_value & kMonoforumDraftBit) { + return 0; + } else if ((_value > kCloudDraftShift) + && (_value < kCloudDraftShift + max)) { return (_value - kCloudDraftShift); - } else if (_value > kEditDraftShift && _value < kEditDraftShift + max) { + } else if ((_value > kEditDraftShift) + && (_value < kEditDraftShift + max)) { return (_value - kEditDraftShift); } else if (_value > 0 && _value < max) { return _value; } return 0; } - + [[nodiscard]] constexpr PeerId monoforumPeerId() const { + const auto max = ServerMaxMsgId.bare; + const auto value = _value & kMonoforumDraftMask; + if (!(_value & kMonoforumDraftBit)) { + return 0; + } else if ((value > kCloudDraftShift) + && (value < kCloudDraftShift + max)) { + return PeerId(UserId(value - kCloudDraftShift)); + } else if ((value > kEditDraftShift) + && (value < kEditDraftShift + max)) { + return PeerId(UserId(value - kEditDraftShift)); + } else if (value > 0 && value < max) { + return PeerId(UserId(value)); + } + return 0; + } friend inline constexpr auto operator<=>(DraftKey, DraftKey) = default; + friend inline constexpr bool operator==(DraftKey, DraftKey) = default; inline explicit operator bool() const { return _value != 0; @@ -163,9 +203,20 @@ private: constexpr DraftKey(int64 value) : _value(value) { } + [[nodiscard]] static constexpr bool Invalid( + MsgId topicRootId, + PeerId monoforumPeerId) { + return (topicRootId < 0) + || (topicRootId >= ServerMaxMsgId) + || !peerIsUser(monoforumPeerId) + || (monoforumPeerId.value >= ServerMaxMsgId); + } + static constexpr auto kLocalDraftIndex = -1; static constexpr auto kCloudDraftIndex = -2; static constexpr auto kScheduledDraftIndex = -3; + static constexpr auto kMonoforumDraftBit = (int64(1) << 60); + static constexpr auto kMonoforumDraftMask = (kMonoforumDraftBit - 1); static constexpr auto kEditDraftShift = ServerMaxMsgId.bare; static constexpr auto kCloudDraftShift = 2 * ServerMaxMsgId.bare; static constexpr auto kShortcutDraftShift = 3 * ServerMaxMsgId.bare; diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 80f51c42b2..d422b01947 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -73,7 +73,7 @@ Forum::~Forum() { const auto peerId = _history->peer->id; for (const auto &[rootId, topic] : _topics) { storage.unload(Storage::SharedMediaUnloadThread(peerId, rootId)); - _history->setForwardDraft(rootId, {}); + _history->setForwardDraft(rootId, PeerId(), {}); const auto raw = topic.get(); changes.topicRemoved(raw); @@ -197,7 +197,7 @@ void Forum::applyTopicDeleted(MsgId rootId) { session().storage().unload(Storage::SharedMediaUnloadThread( _history->peer->id, rootId)); - _history->setForwardDraft(rootId, {}); + _history->setForwardDraft(rootId, PeerId(), {}); } } diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index e3bf4757cb..12232d8538 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -406,6 +406,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) { &session(), channel()->id, _rootId, + PeerId(), data); }, [](const MTPDdraftMessageEmpty&) {}); } @@ -709,7 +710,7 @@ void ForumTopic::requestChatListMessage() { TimeId ForumTopic::adjustedChatListTimeId() const { const auto result = chatListTimeId(); - if (const auto draft = history()->cloudDraft(_rootId)) { + if (const auto draft = history()->cloudDraft(_rootId, PeerId())) { if (!Data::DraftIsNull(draft) && !session().supportMode()) { return std::max(result, draft->date); } diff --git a/Telegram/SourceFiles/data/data_msg_id.h b/Telegram/SourceFiles/data/data_msg_id.h index 6a94211cbf..355aff7679 100644 --- a/Telegram/SourceFiles/data/data_msg_id.h +++ b/Telegram/SourceFiles/data/data_msg_id.h @@ -180,11 +180,11 @@ struct FullReplyTo { PeerId monoforumPeerId = 0; int quoteOffset = 0; - [[nodiscard]] bool valid() const { - return messageId || (storyId && storyId.peer) || monoforumPeerId; + [[nodiscard]] bool replying() const { + return messageId || (storyId && storyId.peer); } explicit operator bool() const { - return valid(); + return replying() || monoforumPeerId; } friend inline auto operator<=>(FullReplyTo, FullReplyTo) = default; friend inline bool operator==(FullReplyTo, FullReplyTo) = default; diff --git a/Telegram/SourceFiles/data/data_saved_messages.cpp b/Telegram/SourceFiles/data/data_saved_messages.cpp index 3bcc65ad4e..ef67795445 100644 --- a/Telegram/SourceFiles/data/data_saved_messages.cpp +++ b/Telegram/SourceFiles/data/data_saved_messages.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_saved_messages.h" #include "apiwrap.h" +#include "data/data_changes.h" #include "data/data_channel.h" #include "data/data_user.h" #include "data/data_saved_sublist.h" @@ -47,7 +48,15 @@ SavedMessages::SavedMessages( } } -SavedMessages::~SavedMessages() = default; +SavedMessages::~SavedMessages() { + auto &changes = session().changes(); + for (const auto &[peer, sublist] : _sublists) { + _owningHistory->setForwardDraft(MsgId(), peer->id, {}); + + const auto raw = sublist.get(); + changes.entryRemoved(raw); + } +} bool SavedMessages::supported() const { return !_unsupported; diff --git a/Telegram/SourceFiles/data/data_saved_sublist.cpp b/Telegram/SourceFiles/data/data_saved_sublist.cpp index 64a02b2d9d..e4e420a75e 100644 --- a/Telegram/SourceFiles/data/data_saved_sublist.cpp +++ b/Telegram/SourceFiles/data/data_saved_sublist.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "data/data_changes.h" #include "data/data_channel.h" +#include "data/data_drafts.h" #include "data/data_histories.h" #include "data/data_messages.h" #include "data/data_peer.h" @@ -695,15 +696,18 @@ void SavedSublist::subscribeToUnreadChanges() { void SavedSublist::applyMonoforumDialog( const MTPDmonoForumDialog &data, not_null topItem) { - //if (const auto draft = data.vdraft()) { // #TODO monoforum - // draft->match([&](const MTPDdraftMessage &data) { - // Data::ApplyPeerCloudDraft( - // &session(), - // channel()->id, - // _rootId, - // data); - // }, [](const MTPDdraftMessageEmpty&) {}); - //} + if (const auto parent = parentChat()) { + if (const auto draft = data.vdraft()) { + draft->match([&](const MTPDdraftMessage &data) { + Data::ApplyPeerCloudDraft( + &session(), + parent->id, + MsgId(), + sublistPeer()->id, + data); + }, [](const MTPDdraftMessageEmpty&) {}); + } + } setInboxReadTill( data.vread_inbox_max_id().v, @@ -712,6 +716,18 @@ void SavedSublist::applyMonoforumDialog( applyMaybeLast(topItem); } +TimeId SavedSublist::adjustedChatListTimeId() const { + const auto result = chatListTimeId(); + const auto monoforumPeerId = sublistPeer()->id; + const auto history = _parent->owningHistory(); + if (const auto draft = history->cloudDraft(MsgId(), monoforumPeerId)) { + if (!Data::DraftIsNull(draft) && !session().supportMode()) { + return std::max(result, draft->date); + } + } + return result; +} + rpl::producer<> SavedSublist::changes() const { return _listChanges.events(); } diff --git a/Telegram/SourceFiles/data/data_saved_sublist.h b/Telegram/SourceFiles/data/data_saved_sublist.h index 468e4b647d..0708e1a7a0 100644 --- a/Telegram/SourceFiles/data/data_saved_sublist.h +++ b/Telegram/SourceFiles/data/data_saved_sublist.h @@ -72,6 +72,8 @@ public: void readTillEnd(); void requestChatListMessage(); + TimeId adjustedChatListTimeId() const override; + int fixedOnTopIndex() const override; bool shouldBeInChatList() const override; Dialogs::UnreadState chatListUnreadState() const override; diff --git a/Telegram/SourceFiles/data/data_thread.cpp b/Telegram/SourceFiles/data/data_thread.cpp index 67a346f7e2..dcf9b85f51 100644 --- a/Telegram/SourceFiles/data/data_thread.cpp +++ b/Telegram/SourceFiles/data/data_thread.cpp @@ -32,6 +32,13 @@ MsgId Thread::topicRootId() const { return MsgId(); } +PeerId Thread::monoforumPeerId() const { + if (const auto sublist = asSublist()) { + return sublist->sublistPeer()->id; + } + return PeerId(); +} + PeerData *Thread::maybeSublistPeer() const { if (const auto sublist = asSublist()) { return sublist->sublistPeer(); diff --git a/Telegram/SourceFiles/data/data_thread.h b/Telegram/SourceFiles/data/data_thread.h index 10eb0d27ee..74462a1944 100644 --- a/Telegram/SourceFiles/data/data_thread.h +++ b/Telegram/SourceFiles/data/data_thread.h @@ -67,6 +67,7 @@ public: return const_cast(this)->owningHistory(); } [[nodiscard]] MsgId topicRootId() const; + [[nodiscard]] PeerId monoforumPeerId() const; [[nodiscard]] PeerData *maybeSublistPeer() const; [[nodiscard]] not_null peer() const; [[nodiscard]] PeerNotifySettings ¬ify(); diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 9f0562e1b7..c1ed9c42f7 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -382,8 +382,6 @@ struct ForwardDraft { const ForwardDraft&) = default; }; -using ForwardDrafts = base::flat_map; - struct ResolvedForwardDraft { HistoryItemsList items; ForwardOptions options = ForwardOptions::PreserveInfo; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 1cd8a1e353..f2d58e995e 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -962,10 +962,12 @@ void RowPainter::Paint( if (!thread) { return nullptr; } - if ((!peer || !peer->isForum()) && (!item || !badgesState.unread)) { + if ((!peer || (!peer->isForum() && !peer->amMonoforumAdmin())) + && (!item || !badgesState.unread)) { // Draw item, if there are unread messages. const auto draft = thread->owningHistory()->cloudDraft( - thread->topicRootId()); + thread->topicRootId(), + thread->monoforumPeerId()); if (!Data::DraftIsNull(draft)) { return draft; } diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index a67e60302b..3c40fbe973 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -206,33 +206,39 @@ void History::itemVanished(not_null item) { void History::takeLocalDraft(not_null from) { const auto topicRootId = MsgId(0); - const auto i = from->_drafts.find(Data::DraftKey::Local(topicRootId)); + const auto monoforumPeerId = PeerId(0); + const auto i = from->_drafts.find( + Data::DraftKey::Local(topicRootId, monoforumPeerId)); if (i == end(from->_drafts)) { return; } auto &draft = i->second; if (!draft->textWithTags.text.isEmpty() - && !_drafts.contains(Data::DraftKey::Local(topicRootId))) { + && !_drafts.contains( + Data::DraftKey::Local(topicRootId, monoforumPeerId))) { // Edit and reply to drafts can't migrate. // Cloud drafts do not migrate automatically. draft->reply = FullReplyTo(); setLocalDraft(std::move(draft)); } - from->clearLocalDraft(topicRootId); + from->clearLocalDraft(topicRootId, monoforumPeerId); session().api().saveDraftToCloudDelayed(from); } -void History::createLocalDraftFromCloud(MsgId topicRootId) { - const auto draft = cloudDraft(topicRootId); +void History::createLocalDraftFromCloud( + MsgId topicRootId, + PeerId monoforumPeerId) { + const auto draft = cloudDraft(topicRootId, monoforumPeerId); if (!draft) { - clearLocalDraft(topicRootId); + clearLocalDraft(topicRootId, monoforumPeerId); return; } else if (Data::DraftIsNull(draft) || !draft->date) { return; } draft->reply.topicRootId = topicRootId; - auto existing = localDraft(topicRootId); + draft->reply.monoforumPeerId = monoforumPeerId; + auto existing = localDraft(topicRootId, monoforumPeerId); if (Data::DraftIsNull(existing) || !existing->date || draft->date >= existing->date) { @@ -242,7 +248,7 @@ void History::createLocalDraftFromCloud(MsgId topicRootId) { draft->reply, draft->cursor, draft->webpage)); - existing = localDraft(topicRootId); + existing = localDraft(topicRootId, monoforumPeerId); } else if (existing != draft) { existing->textWithTags = draft->textWithTags; existing->reply = draft->reply; @@ -268,7 +274,7 @@ void History::setDraft( return; } const auto cloudThread = key.isCloud() - ? threadFor(key.topicRootId()) + ? threadFor(key.topicRootId(), key.monoforumPeerId()) : nullptr; if (cloudThread) { cloudThread->cloudDraftTextCache().clear(); @@ -298,7 +304,7 @@ void History::clearDraft(Data::DraftKey key) { void History::clearDrafts() { for (auto &[key, draft] : base::take(_drafts)) { const auto cloudThread = key.isCloud() - ? threadFor(key.topicRootId()) + ? threadFor(key.topicRootId(), key.monoforumPeerId()) : nullptr; if (cloudThread) { cloudThread->cloudDraftTextCache().clear(); @@ -309,25 +315,30 @@ void History::clearDrafts() { Data::Draft *History::createCloudDraft( MsgId topicRootId, + PeerId monoforumPeerId, const Data::Draft *fromDraft) { if (Data::DraftIsNull(fromDraft)) { setCloudDraft(std::make_unique( TextWithTags(), - FullReplyTo{ .topicRootId = topicRootId }, + FullReplyTo{ + .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, + }, MessageCursor(), Data::WebPageDraft())); - cloudDraft(topicRootId)->date = TimeId(0); + cloudDraft(topicRootId, monoforumPeerId)->date = TimeId(0); } else { - auto existing = cloudDraft(topicRootId); + auto existing = cloudDraft(topicRootId, monoforumPeerId); if (!existing) { auto reply = fromDraft->reply; reply.topicRootId = topicRootId; + reply.monoforumPeerId = monoforumPeerId; setCloudDraft(std::make_unique( fromDraft->textWithTags, reply, fromDraft->cursor, fromDraft->webpage)); - existing = cloudDraft(topicRootId); + existing = cloudDraft(topicRootId, monoforumPeerId); } else if (existing != fromDraft) { existing->textWithTags = fromDraft->textWithTags; existing->reply = fromDraft->reply; @@ -336,44 +347,56 @@ Data::Draft *History::createCloudDraft( } existing->date = base::unixtime::now(); existing->reply.topicRootId = topicRootId; + existing->reply.monoforumPeerId = monoforumPeerId; } - if (const auto thread = threadFor(topicRootId)) { + if (const auto thread = threadFor(topicRootId, monoforumPeerId)) { thread->cloudDraftTextCache().clear(); thread->updateChatListSortPosition(); } - return cloudDraft(topicRootId); + return cloudDraft(topicRootId, monoforumPeerId); } -bool History::skipCloudDraftUpdate(MsgId topicRootId, TimeId date) const { - const auto i = _acceptCloudDraftsAfter.find(topicRootId); - return _savingCloudDraftRequests.contains(topicRootId) +bool History::skipCloudDraftUpdate( + MsgId topicRootId, + PeerId monoforumPeerId, + TimeId date) const { + const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId); + const auto i = _acceptCloudDraftsAfter.find(key); + return _savingCloudDraftRequests.contains(key) || (i != _acceptCloudDraftsAfter.end() && date < i->second); } -void History::startSavingCloudDraft(MsgId topicRootId) { - ++_savingCloudDraftRequests[topicRootId]; +void History::startSavingCloudDraft( + MsgId topicRootId, + PeerId monoforumPeerId) { + const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId); + ++_savingCloudDraftRequests[key]; } -void History::finishSavingCloudDraft(MsgId topicRootId, TimeId savedAt) { - const auto i = _savingCloudDraftRequests.find(topicRootId); +void History::finishSavingCloudDraft( + MsgId topicRootId, + PeerId monoforumPeerId, + TimeId savedAt) { + const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId); + const auto i = _savingCloudDraftRequests.find(key); if (i != _savingCloudDraftRequests.end()) { if (--i->second <= 0) { _savingCloudDraftRequests.erase(i); } } - auto &after = _acceptCloudDraftsAfter[topicRootId]; + auto &after = _acceptCloudDraftsAfter[key]; after = std::max(after, savedAt + kSkipCloudDraftsFor); } -void History::applyCloudDraft(MsgId topicRootId) { +void History::applyCloudDraft(MsgId topicRootId, PeerId monoforumPeerId) { if (!topicRootId && session().supportMode()) { updateChatListEntry(); session().supportHelper().cloudDraftChanged(this); } else { - createLocalDraftFromCloud(topicRootId); - if (const auto thread = threadFor(topicRootId)) { + createLocalDraftFromCloud(topicRootId, monoforumPeerId); + if (const auto thread = threadFor(topicRootId, monoforumPeerId)) { thread->updateChatListSortPosition(); if (!topicRootId) { session().changes().historyUpdated( @@ -388,17 +411,19 @@ void History::applyCloudDraft(MsgId topicRootId) { } } -void History::draftSavedToCloud(MsgId topicRootId) { - if (const auto thread = threadFor(topicRootId)) { +void History::draftSavedToCloud(MsgId topicRootId, PeerId monoforumPeerId) { + if (const auto thread = threadFor(topicRootId, monoforumPeerId)) { thread->updateChatListEntry(); } session().local().writeDrafts(this); } const Data::ForwardDraft &History::forwardDraft( - MsgId topicRootId) const { + MsgId topicRootId, + PeerId monoforumPeerId) const { + const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId); static const auto kEmpty = Data::ForwardDraft(); - const auto i = _forwardDrafts.find(topicRootId); + const auto i = _forwardDrafts.find(key); return (i != end(_forwardDrafts)) ? i->second : kEmpty; } @@ -411,11 +436,12 @@ Data::ResolvedForwardDraft History::resolveForwardDraft( } Data::ResolvedForwardDraft History::resolveForwardDraft( - MsgId topicRootId) { - const auto &draft = forwardDraft(topicRootId); + MsgId topicRootId, + PeerId monoforumPeerId) { + const auto &draft = forwardDraft(topicRootId, monoforumPeerId); auto result = resolveForwardDraft(draft); if (result.items.size() != draft.ids.size()) { - setForwardDraft(topicRootId, { + setForwardDraft(topicRootId, monoforumPeerId, { .ids = owner().itemsToIds(result.items), .options = result.options, }); @@ -425,24 +451,23 @@ Data::ResolvedForwardDraft History::resolveForwardDraft( void History::setForwardDraft( MsgId topicRootId, + PeerId monoforumPeerId, Data::ForwardDraft &&draft) { auto changed = false; + const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId); if (draft.ids.empty()) { - changed = _forwardDrafts.remove(topicRootId); + changed = _forwardDrafts.remove(key); } else { - auto &now = _forwardDrafts[topicRootId]; + auto &now = _forwardDrafts[key]; if (now != draft) { now = std::move(draft); changed = true; } } if (changed) { - const auto entry = topicRootId - ? peer->forumTopicFor(topicRootId) - : (Dialogs::Entry*)this; - if (entry) { + if (const auto thread = threadFor(topicRootId, monoforumPeerId)) { session().changes().entryUpdated( - entry, + thread, Data::EntryUpdate::Flag::ForwardDraft); } } @@ -2081,7 +2106,7 @@ void History::applyPinnedUpdate(const MTPDupdateDialogPinned &data) { TimeId History::adjustedChatListTimeId() const { const auto result = chatListTimeId(); - if (const auto draft = cloudDraft(MsgId(0))) { + if (const auto draft = cloudDraft(MsgId(), PeerId())) { if (!peer->forum() && !Data::DraftIsNull(draft) && !session().supportMode()) { @@ -2871,7 +2896,8 @@ void History::applyDialog( Data::ApplyPeerCloudDraft( &session(), peer->id, - MsgId(0), // topicRootId + MsgId(), // topicRootId + PeerId(), // monoforumPeerId draft->c_draftMessage()); } if (const auto ttl = data.vttl_period()) { @@ -3101,14 +3127,22 @@ void History::forceFullResize() { _flags |= Flag::HasPendingResizedItems; } -Data::Thread *History::threadFor(MsgId topicRootId) { +Data::Thread *History::threadFor(MsgId topicRootId, PeerId monoforumPeerId) { return topicRootId ? peer->forumTopicFor(topicRootId) - : static_cast(this); + : !monoforumPeerId + ? static_cast(this) + : peer->monoforum() + ? peer->monoforum()->sublistLoaded(owner().peer(monoforumPeerId)) + : nullptr; } -const Data::Thread *History::threadFor(MsgId topicRootId) const { - return const_cast(this)->threadFor(topicRootId); +const Data::Thread *History::threadFor( + MsgId topicRootId, + PeerId monoforumPeerId) const { + return const_cast(this)->threadFor( + topicRootId, + monoforumPeerId); } void History::forumChanged(Data::Forum *old) { @@ -3137,7 +3171,7 @@ void History::forumChanged(Data::Forum *old) { } else { _flags &= ~Flag::IsForum; } - if (cloudDraft(MsgId(0))) { + if (cloudDraft(MsgId(), PeerId())) { updateChatListSortPosition(); } _flags |= Flag::PendingAllItemsResize; @@ -3173,7 +3207,7 @@ void History::monoforumChanged(Data::SavedMessages *old) { } else { _flags &= ~Flag::IsMonoforumAdmin; } - if (cloudDraft(MsgId(0))) { + if (cloudDraft(MsgId(), PeerId())) { updateChatListSortPosition(); } _flags |= Flag::PendingAllItemsResize; diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 16fe57e351..4a009a4d20 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -62,8 +62,12 @@ public: [[nodiscard]] not_null owningHistory() override { return this; } - [[nodiscard]] Data::Thread *threadFor(MsgId topicRootId); - [[nodiscard]] const Data::Thread *threadFor(MsgId topicRootId) const; + [[nodiscard]] Data::Thread *threadFor( + MsgId topicRootId, + PeerId monoforumPeerId); + [[nodiscard]] const Data::Thread *threadFor( + MsgId topicRootId, + PeerId monoforumPeerId) const; [[nodiscard]] auto delegateMixin() const -> not_null { @@ -288,60 +292,89 @@ public: [[nodiscard]] const Data::HistoryDrafts &draftsMap() const; void setDraftsMap(Data::HistoryDrafts &&map); - Data::Draft *localDraft(MsgId topicRootId) const { - return draft(Data::DraftKey::Local(topicRootId)); + Data::Draft *localDraft( + MsgId topicRootId, + PeerId monoforumPeerId) const { + return draft(Data::DraftKey::Local(topicRootId, monoforumPeerId)); } - Data::Draft *localEditDraft(MsgId topicRootId) const { - return draft(Data::DraftKey::LocalEdit(topicRootId)); + Data::Draft *localEditDraft( + MsgId topicRootId, + PeerId monoforumPeerId) const { + return draft( + Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId)); } - Data::Draft *cloudDraft(MsgId topicRootId) const { - return draft(Data::DraftKey::Cloud(topicRootId)); + Data::Draft *cloudDraft( + MsgId topicRootId, + PeerId monoforumPeerId) const { + return draft(Data::DraftKey::Cloud(topicRootId, monoforumPeerId)); } void setLocalDraft(std::unique_ptr &&draft) { setDraft( - Data::DraftKey::Local(draft->reply.topicRootId), + Data::DraftKey::Local( + draft->reply.topicRootId, + draft->reply.monoforumPeerId), std::move(draft)); } void setLocalEditDraft(std::unique_ptr &&draft) { setDraft( - Data::DraftKey::LocalEdit(draft->reply.topicRootId), + Data::DraftKey::LocalEdit( + draft->reply.topicRootId, + draft->reply.monoforumPeerId), std::move(draft)); } void setCloudDraft(std::unique_ptr &&draft) { setDraft( - Data::DraftKey::Cloud(draft->reply.topicRootId), + Data::DraftKey::Cloud( + draft->reply.topicRootId, + draft->reply.monoforumPeerId), std::move(draft)); } - void clearLocalDraft(MsgId topicRootId) { - clearDraft(Data::DraftKey::Local(topicRootId)); + void clearLocalDraft( + MsgId topicRootId, + PeerId monoforumPeerId) { + clearDraft(Data::DraftKey::Local(topicRootId, monoforumPeerId)); } - void clearCloudDraft(MsgId topicRootId) { - clearDraft(Data::DraftKey::Cloud(topicRootId)); + void clearCloudDraft( + MsgId topicRootId, + PeerId monoforumPeerId) { + clearDraft(Data::DraftKey::Cloud(topicRootId, monoforumPeerId)); } - void clearLocalEditDraft(MsgId topicRootId) { - clearDraft(Data::DraftKey::LocalEdit(topicRootId)); + void clearLocalEditDraft( + MsgId topicRootId, + PeerId monoforumPeerId) { + clearDraft(Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId)); } void clearDrafts(); Data::Draft *createCloudDraft( MsgId topicRootId, + PeerId monoforumPeerId, const Data::Draft *fromDraft); [[nodiscard]] bool skipCloudDraftUpdate( MsgId topicRootId, + PeerId monoforumPeerId, TimeId date) const; - void startSavingCloudDraft(MsgId topicRootId); - void finishSavingCloudDraft(MsgId topicRootId, TimeId savedAt); + void startSavingCloudDraft(MsgId topicRootId, PeerId monoforumPeerId); + void finishSavingCloudDraft( + MsgId topicRootId, + PeerId monoforumPeerId, + TimeId savedAt); void takeLocalDraft(not_null from); - void applyCloudDraft(MsgId topicRootId); - void draftSavedToCloud(MsgId topicRootId); + void applyCloudDraft(MsgId topicRootId, PeerId monoforumPeerId); + void draftSavedToCloud(MsgId topicRootId, PeerId monoforumPeerId); void requestChatListMessage(); [[nodiscard]] const Data::ForwardDraft &forwardDraft( - MsgId topicRootId) const; + MsgId topicRootId, + PeerId monoforumPeerId) const; [[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft( const Data::ForwardDraft &draft) const; [[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft( - MsgId topicRootId); - void setForwardDraft(MsgId topicRootId, Data::ForwardDraft &&draft); + MsgId topicRootId, + PeerId monoforumPeerId); + void setForwardDraft( + MsgId topicRootId, + PeerId monoforumPeerId, + Data::ForwardDraft &&draft); History *migrateSibling() const; [[nodiscard]] bool useTopPromotion() const; @@ -548,7 +581,9 @@ private: void viewReplaced(not_null was, Element *now); - void createLocalDraftFromCloud(MsgId topicRootId); + void createLocalDraftFromCloud( + MsgId topicRootId, + PeerId monoforumPeerId); HistoryItem *insertJoinedMessage(); void insertMessageToBlocks(not_null item); @@ -606,9 +641,9 @@ private: std::unique_ptr _translation; Data::HistoryDrafts _drafts; - base::flat_map _acceptCloudDraftsAfter; - base::flat_map _savingCloudDraftRequests; - Data::ForwardDrafts _forwardDrafts; + base::flat_map _acceptCloudDraftsAfter; + base::flat_map _savingCloudDraftRequests; + base::flat_map _forwardDrafts; QString _topPromotedMessage; QString _topPromotedType; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index c66d5cbb86..4007594a05 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1118,7 +1118,7 @@ void HistoryWidget::initVoiceRecordBar() { }); const auto applyLocalDraft = [=] { - if (_history && _history->localDraft({})) { + if (_history && _history->localDraft(MsgId(), PeerId())) { applyDraft(); } }; @@ -1874,12 +1874,14 @@ void HistoryWidget::saveFieldToHistoryLocalDraft() { } const auto topicRootId = MsgId(); + const auto monoforumPeerId = PeerId(); if (_editMsgId) { _history->setLocalEditDraft(std::make_unique( _field, FullReplyTo{ .messageId = FullMsgId(_history->peer->id, _editMsgId), .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, }, _preview->draft(), _saveEditMsgRequestId)); @@ -1890,9 +1892,9 @@ void HistoryWidget::saveFieldToHistoryLocalDraft() { _replyTo, _preview->draft())); } else { - _history->clearLocalDraft(topicRootId); + _history->clearLocalDraft(topicRootId, monoforumPeerId); } - _history->clearLocalEditDraft(topicRootId); + _history->clearLocalEditDraft(topicRootId, monoforumPeerId); } } @@ -2187,11 +2189,13 @@ bool HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) { } }); - const auto editDraft = _history ? _history->localEditDraft({}) : nullptr; + const auto editDraft = _history + ? _history->localEditDraft(MsgId(), PeerId()) + : nullptr; const auto draft = editDraft ? editDraft : _history - ? _history->localDraft({}) + ? _history->localDraft(MsgId(), PeerId()) : nullptr; auto fieldAvailable = canWriteMessage(); const auto editMsgId = editDraft ? editDraft->reply.messageId.msg : 0; @@ -2241,7 +2245,7 @@ bool HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) { requestMessageData(_editMsgId); } } else { - const auto draft = _history->localDraft({}); + const auto draft = _history->localDraft(MsgId(), PeerId()); _processingReplyTo = draft ? draft->reply : FullReplyTo(); if (_processingReplyTo) { _processingReplyItem = session().data().message( @@ -2408,7 +2412,7 @@ void HistoryWidget::showHistory( info->inlineReturnTo = wasState; } sendBotStartCommand(); - _history->clearLocalDraft({}); + _history->clearLocalDraft(MsgId(), PeerId()); applyDraft(); _send->finishAnimating(); } @@ -2864,10 +2868,10 @@ void HistoryWidget::unregisterDraftSources() { } session().local().unregisterDraftSource( _history, - Data::DraftKey::Local({})); + Data::DraftKey::Local(MsgId(), PeerId())); session().local().unregisterDraftSource( _history, - Data::DraftKey::LocalEdit({})); + Data::DraftKey::LocalEdit(MsgId(), PeerId())); } void HistoryWidget::registerDraftSource() { @@ -2892,8 +2896,8 @@ void HistoryWidget::registerDraftSource() { session().local().registerDraftSource( _history, (editMsgId - ? Data::DraftKey::LocalEdit({}) - : Data::DraftKey::Local({})), + ? Data::DraftKey::LocalEdit(MsgId(), PeerId()) + : Data::DraftKey::Local(MsgId(), PeerId())), std::move(draftSource)); } @@ -3630,6 +3634,7 @@ void HistoryWidget::unreadCountUpdated() { }); } else { const auto hideCounter = _history->isForum() + || _history->amMonoforumAdmin() || !_history->trackUnreadMessages(); _cornerButtons.updateJumpDownVisibility(hideCounter ? 0 @@ -4376,16 +4381,16 @@ void HistoryWidget::saveEditMsg() { cancelEdit(); } })(); - if (const auto editDraft = history->localEditDraft({})) { + if (const auto editDraft = history->localEditDraft({}, {})) { if (editDraft->saveRequestId == requestId) { - history->clearLocalEditDraft({}); + history->clearLocalEditDraft(MsgId(), PeerId()); history->session().local().writeDrafts(history); } } }; const auto fail = [=](const QString &error, mtpRequestId requestId) { - if (const auto editDraft = history->localEditDraft({})) { + if (const auto editDraft = history->localEditDraft({}, {})) { if (editDraft->saveRequestId == requestId) { editDraft->saveRequestId = 0; } @@ -7276,7 +7281,7 @@ void HistoryWidget::editDraftOptions() { } else { cancelReply(); } - history->setForwardDraft({}, std::move(forward)); + history->setForwardDraft(MsgId(), PeerId(), std::move(forward)); _preview->apply(webpage); }; const auto replyToId = reply.messageId; @@ -7295,7 +7300,9 @@ void HistoryWidget::editDraftOptions() { .resolver = _preview->resolver(), .done = done, .highlight = highlight, - .clearOldDraft = [=] { ClearDraftReplyTo(history, 0, replyToId); }, + .clearOldDraft = [=] { + ClearDraftReplyTo(history, MsgId(), PeerId(), replyToId); + }, }); } @@ -8418,7 +8425,7 @@ void HistoryWidget::setReplyFieldsFromProcessing() { const auto id = base::take(_processingReplyTo); const auto item = base::take(_processingReplyItem); if (_editMsgId) { - if (const auto localDraft = _history->localDraft({})) { + if (const auto localDraft = _history->localDraft({}, {})) { localDraft->reply = id; } else { _history->setLocalDraft(std::make_unique( @@ -8470,7 +8477,7 @@ void HistoryWidget::editMessage( _replyTo, _preview->draft())); } else { - _history->clearLocalDraft({}); + _history->clearLocalDraft(MsgId(), PeerId()); } } @@ -8580,10 +8587,10 @@ bool HistoryWidget::cancelReply(bool lastKeyboardUsed) { updateControlsGeometry(); update(); } else if (const auto localDraft - = (_history ? _history->localDraft({}) : nullptr)) { + = (_history ? _history->localDraft({}, {}) : nullptr)) { if (localDraft->reply) { if (localDraft->textWithTags.text.isEmpty()) { - _history->clearLocalDraft({}); + _history->clearLocalDraft(MsgId(), PeerId()); } else { localDraft->reply = {}; } @@ -8629,7 +8636,7 @@ void HistoryWidget::cancelEdit() { updateReplaceMediaButton(); _replyEditMsg = nullptr; setEditMsgId(0); - _history->clearLocalEditDraft({}); + _history->clearLocalEditDraft(MsgId(), PeerId()); applyDraft(); if (_saveEditMsgRequestId) { @@ -8671,7 +8678,7 @@ void HistoryWidget::cancelFieldAreaState() { } else if (_replyTo) { cancelReply(); } else if (readyToForward()) { - _history->setForwardDraft(MsgId(), {}); + _history->setForwardDraft(MsgId(), PeerId(), {}); } else if (_kbReplyTo) { toggleKeyboard(); } @@ -9039,7 +9046,7 @@ void HistoryWidget::updateReplyEditTexts(bool force) { void HistoryWidget::updateForwarding() { _forwardPanel->update(_history, _history - ? _history->resolveForwardDraft(MsgId()) + ? _history->resolveForwardDraft(MsgId(), PeerId()) : Data::ResolvedForwardDraft()); updateControlsVisibility(); updateControlsGeometry(); diff --git a/Telegram/SourceFiles/history/view/controls/compose_controls_common.h b/Telegram/SourceFiles/history/view/controls/compose_controls_common.h index ea4bcb3178..3e76145f2e 100644 --- a/Telegram/SourceFiles/history/view/controls/compose_controls_common.h +++ b/Telegram/SourceFiles/history/view/controls/compose_controls_common.h @@ -66,6 +66,7 @@ struct WriteRestriction { struct SetHistoryArgs { required history; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; Fn showSlowmodeError; Fn sendActionFactory; rpl::producer slowmodeSecondsLeft; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 5e4f936f1f..e0b3256f4d 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_drafts.h" #include "data/data_messages.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "data/data_user.h" #include "data/data_chat.h" @@ -197,6 +198,7 @@ private: History *_history = nullptr; MsgId _topicRootId = 0; + PeerId _monoforumPeerId = 0; Preview _preview; rpl::event_stream<> _editCancelled; @@ -254,6 +256,7 @@ FieldHeader::FieldHeader( void FieldHeader::setHistory(const SetHistoryArgs &args) { _history = *args.history; _topicRootId = args.topicRootId; + _monoforumPeerId = args.monoforumPeerId; } void FieldHeader::updateTopicRootId(MsgId topicRootId) { @@ -282,7 +285,7 @@ void FieldHeader::init() { st::historyLinkIcon.paint(p, position, width()); } else if (isEditingMessage()) { st::historyEditIcon.paint(p, position, width()); - } else if (const auto reply = replyingToMessage()) { + } else if (const auto reply = replyingToMessage(); reply.replying()) { if (!reply.quote.empty()) { st::historyQuoteIcon.paint(p, position, width()); } else { @@ -760,6 +763,7 @@ void FieldHeader::editMessage(FullMsgId id, bool photoEditAllowed) { } void FieldHeader::replyToMessage(FullReplyTo id) { + id.monoforumPeerId = 0; _replyTo = id; } @@ -956,6 +960,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) { unregisterDraftSources(); _history = history; _topicRootId = args.topicRootId; + _monoforumPeerId = args.monoforumPeerId; _historyLifetime.destroy(); _header->setHistory(args); registerDraftSource(); @@ -999,6 +1004,7 @@ void ComposeControls::setCurrentDialogsEntryState( Dialogs::EntryState state) { unregisterDraftSources(); state.currentReplyTo.topicRootId = _topicRootId; + state.currentReplyTo.monoforumPeerId = _monoforumPeerId; _currentDialogsEntryState = state; updateForwarding(); registerDraftSource(); @@ -1405,6 +1411,7 @@ void ComposeControls::init() { ) | rpl::start_with_next([=] { const auto history = _history; const auto topicRootId = _topicRootId; + const auto monoforumPeerId = _monoforumPeerId; const auto reply = _header->replyingToMessage(); const auto webpage = _preview->draft(); @@ -1417,7 +1424,10 @@ void ComposeControls::init() { } else { cancelReplyMessage(); } - history->setForwardDraft(topicRootId, std::move(forward)); + history->setForwardDraft( + topicRootId, + monoforumPeerId, + std::move(forward)); _preview->apply(webpage); _field->setFocus(); }; @@ -1440,6 +1450,7 @@ void ComposeControls::init() { .clearOldDraft = [=] { ClearDraftReplyTo( history, topicRootId, + monoforumPeerId, replyToId); }, }); }, _wrap->lifetime()); @@ -1809,8 +1820,8 @@ Data::DraftKey ComposeControls::draftKey(DraftType type) const { case Section::Replies: case Section::SavedSublist: return (type == DraftType::Edit) - ? Key::LocalEdit(_topicRootId) - : Key::Local(_topicRootId); + ? Key::LocalEdit(_topicRootId, _monoforumPeerId) + : Key::Local(_topicRootId, _monoforumPeerId); case Section::Scheduled: return (type == DraftType::Edit) ? Key::ScheduledEdit() @@ -2038,7 +2049,7 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) { } void ComposeControls::cancelForward() { - _history->setForwardDraft(_topicRootId, {}); + _history->setForwardDraft(_topicRootId, _monoforumPeerId, {}); updateForwarding(); } @@ -2902,9 +2913,11 @@ void ComposeControls::toggleTabbedSelectorMode() { && !_regularWindow->adaptive().isOneColumn()) { Core::App().settings().setTabbedSelectorSectionEnabled(true); Core::App().saveSettingsDelayed(); - const auto topic = _history->peer->forumTopicFor(_topicRootId); + const auto thread = _history->threadFor( + _topicRootId, + _monoforumPeerId); pushTabbedSelectorToThirdSection( - (topic ? topic : (Data::Thread*)_history), + thread ? thread : _history, Window::SectionShow::Way::ClearStack); } else { _tabbedPanel->toggleAnimated(); @@ -2958,6 +2971,7 @@ void ComposeControls::editMessage(not_null item) { FullReplyTo{ .messageId = item->fullId(), .topicRootId = key.topicRootId(), + .monoforumPeerId = key.monoforumPeerId(), }, cursor, Data::WebPageDraft::FromItem(item))); @@ -3038,6 +3052,7 @@ void ComposeControls::replyToMessage(FullReplyTo id) { Expects(draftKeyCurrent() != Data::DraftKey::None()); id.topicRootId = _topicRootId; + id.monoforumPeerId = _monoforumPeerId; if (!id) { cancelReplyMessage(); return; @@ -3045,6 +3060,7 @@ void ComposeControls::replyToMessage(FullReplyTo id) { if (isEditingMessage()) { const auto key = draftKey(DraftType::Normal); Assert(key.topicRootId() == id.topicRootId); + Assert(key.monoforumPeerId() == id.monoforumPeerId); if (const auto localDraft = _history->draft(key)) { localDraft->reply = id; } else { @@ -3088,12 +3104,11 @@ void ComposeControls::cancelReplyMessage() { } void ComposeControls::updateForwarding() { - const auto rootId = _topicRootId; - const auto thread = (_history && rootId) - ? _history->peer->forumTopicFor(rootId) + const auto thread = (_history && (_topicRootId || _monoforumPeerId)) + ? _history->threadFor(_topicRootId, _monoforumPeerId) : (Data::Thread*)_history; _header->updateForwarding(thread, thread - ? _history->resolveForwardDraft(rootId) + ? _history->resolveForwardDraft(_topicRootId, _monoforumPeerId) : Data::ResolvedForwardDraft()); updateSendButtonType(); } @@ -3108,7 +3123,7 @@ bool ComposeControls::handleCancelRequest() { } else if (isEditingMessage()) { maybeCancelEditMessage(); return true; - } else if (replyingToMessage()) { + } else if (replyingToMessage().replying()) { cancelReplyMessage(); return true; } else if (readyToForward()) { @@ -3186,6 +3201,11 @@ void ComposeControls::initForwardProcess() { && topic->rootId() == _topicRootId) { updateForwarding(); } + } else if (const auto sublist = update.entry->asSublist()) { + if (sublist->owningHistory() == _history + && sublist->sublistPeer()->id == _monoforumPeerId) { + updateForwarding(); + } } }, _wrap->lifetime()); @@ -3209,6 +3229,7 @@ bool ComposeControls::isEditingMessage() const { FullReplyTo ComposeControls::replyingToMessage() const { auto result = _header->replyingToMessage(); result.topicRootId = _topicRootId; + result.monoforumPeerId = _monoforumPeerId; return result; } diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h index 2b97c4f985..cd391e0078 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h @@ -365,6 +365,7 @@ private: History *_history = nullptr; MsgId _topicRootId = 0; + PeerId _monoforumPeerId = 0; BusinessShortcutId _shortcutId = 0; Fn _showSlowmodeError; Fn _sendActionFactory; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp index 549d252331..1277052948 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp @@ -1375,18 +1375,20 @@ void ShowReplyToChatBox( auto chosen = [=](not_null thread) mutable { const auto history = thread->owningHistory(); const auto topicRootId = thread->topicRootId(); - const auto draft = history->localDraft(topicRootId); + const auto monoforumPeerId = thread->monoforumPeerId(); + const auto draft = history->localDraft(topicRootId, monoforumPeerId); const auto textWithTags = draft ? draft->textWithTags : TextWithTags(); const auto cursor = draft ? draft->cursor : MessageCursor(); reply.topicRootId = topicRootId; + reply.monoforumPeerId = monoforumPeerId; history->setLocalDraft(std::make_unique( textWithTags, reply, cursor, Data::WebPageDraft())); - history->clearLocalEditDraft(topicRootId); + history->clearLocalEditDraft(topicRootId, monoforumPeerId); history->session().changes().entryUpdated( thread, Data::EntryUpdate::Flag::LocalDraftSet); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp index 44e059ff34..ff314cdf9e 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_helpers.h" #include "history/history_item_components.h" #include "history/view/history_view_item_preview.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "data/data_media_types.h" #include "data/data_forum_topic.h" @@ -74,6 +75,11 @@ void ForwardPanel::update( ) | rpl::start_with_next([=] { update(nullptr, {}); }, _dataLifetime); + } else if (const auto sublist = _to->asSublist()) { + sublist->destroyed( + ) | rpl::start_with_next([=] { + update(nullptr, {}); + }, _dataLifetime); } updateTexts(); @@ -231,8 +237,10 @@ void ForwardPanel::applyOptions(Data::ForwardOptions options) { if (_data.items.empty()) { return; } else if (_data.options != options) { + const auto topicRootId = _to->topicRootId(); + const auto monoforumPeerId = _to->monoforumPeerId(); _data.options = options; - _to->owningHistory()->setForwardDraft(_to->topicRootId(), { + _to->owningHistory()->setForwardDraft(topicRootId, monoforumPeerId, { .ids = _to->owner().itemsToIds(_data.items), .options = options, }); @@ -256,7 +264,9 @@ void ForwardPanel::editToNextOption() { ? Options::NoNamesAndCaptions : Options::PreserveInfo; - _to->owningHistory()->setForwardDraft(_to->topicRootId(), { + const auto topicRootId = _to->topicRootId(); + const auto monoforumPeerId = _to->monoforumPeerId(); + _to->owningHistory()->setForwardDraft(topicRootId, monoforumPeerId, { .ids = _to->owner().itemsToIds(_data.items), .options = next, }); @@ -332,20 +342,25 @@ void ForwardPanel::paint( void ClearDraftReplyTo( not_null history, MsgId topicRootId, + PeerId monoforumPeerId, FullMsgId equalTo) { - const auto local = history->localDraft(topicRootId); + const auto local = history->localDraft(topicRootId, monoforumPeerId); if (!local || (equalTo && local->reply.messageId != equalTo)) { return; } auto draft = *local; - draft.reply = { .topicRootId = topicRootId }; + draft.reply = { + .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, + }; if (Data::DraftIsNull(&draft)) { - history->clearLocalDraft(topicRootId); + history->clearLocalDraft(topicRootId, monoforumPeerId); } else { history->setLocalDraft( std::make_unique(std::move(draft))); } - if (const auto thread = history->threadFor(topicRootId)) { + const auto thread = history->threadFor(topicRootId, monoforumPeerId); + if (thread) { history->session().api().saveDraftToCloudDelayed(thread); } } diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h index 54624d47d8..2e8dcc36d5 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h @@ -76,6 +76,7 @@ private: void ClearDraftReplyTo( not_null history, MsgId topicRootId, + PeerId monoforumPeerId, FullMsgId equalTo); void EditWebPageOptions( diff --git a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp index 0cd5a0fe00..7545a3e79f 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp @@ -438,8 +438,10 @@ ChatWidget::ChatWidget( ChatWidget::~ChatWidget() { base::take(_sendAction); - if (_repliesRootId) { + if (_repliesRootId || _sublist) { session().api().saveCurrentDraftToCloud(); + } + if (_repliesRootId) { controller()->sendingAnimation().clear(); } if (_topic) { @@ -747,7 +749,8 @@ void ChatWidget::setupComposeControls() { _composeControls->setHistory({ .history = _history.get(), - .topicRootId = _topic ? _topic->rootId() : MsgId(0), + .topicRootId = _topic ? _topic->rootId() : MsgId(), + .monoforumPeerId = _sublist ? _sublist->sublistPeer()->id : PeerId(), .showSlowmodeError = [=] { return showSlowmodeError(); }, .sendActionFactory = [=] { return prepareSendAction({}); }, .slowmodeSecondsLeft = SlowmodeSecondsLeft(_peer), diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index e0953d45ca..e2de892e69 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -557,6 +557,7 @@ bool MainWidget::setForwardDraft( const auto history = thread->owningHistory(); const auto items = session().data().idsToItems(draft.ids); const auto topicRootId = thread->topicRootId(); + const auto monoforumPeerId = thread->monoforumPeerId(); const auto error = GetErrorForSending( history->peer, { @@ -569,7 +570,7 @@ bool MainWidget::setForwardDraft( return false; } - history->setForwardDraft(topicRootId, std::move(draft)); + history->setForwardDraft(topicRootId, monoforumPeerId, std::move(draft)); _controller->showThread( thread, ShowAtUnreadMsgId, @@ -596,12 +597,16 @@ bool MainWidget::shareUrl( }; const auto history = thread->owningHistory(); const auto topicRootId = thread->topicRootId(); + const auto monoforumPeerId = thread->monoforumPeerId(); history->setLocalDraft(std::make_unique( textWithTags, - FullReplyTo{ .topicRootId = topicRootId }, + FullReplyTo{ + .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, + }, cursor, Data::WebPageDraft())); - history->clearLocalEditDraft(topicRootId); + history->clearLocalEditDraft(topicRootId, monoforumPeerId); history->session().changes().entryUpdated( thread, Data::EntryUpdate::Flag::LocalDraftSet); @@ -2044,6 +2049,8 @@ bool MainWidget::showBackFromStack(const SectionShow ¶ms) { }); return (_dialogs != nullptr); } + session().api().saveCurrentDraftToCloud(); + auto item = std::move(_stack.back()); _stack.pop_back(); if (const auto currentHistoryPeer = _history->peer()) { diff --git a/Telegram/SourceFiles/storage/storage_account.cpp b/Telegram/SourceFiles/storage/storage_account.cpp index 339840de23..5d88879bfa 100644 --- a/Telegram/SourceFiles/storage/storage_account.cpp +++ b/Telegram/SourceFiles/storage/storage_account.cpp @@ -1176,7 +1176,9 @@ void EnumerateDrafts( } else if (key.isLocal() && (!supportMode || key.topicRootId())) { const auto i = map.find( - Data::DraftKey::Cloud(key.topicRootId())); + Data::DraftKey::Cloud( + key.topicRootId(), + key.monoforumPeerId())); const auto cloud = (i != end(map)) ? i->second.get() : nullptr; if (Data::DraftsAreEqual(draft.get(), cloud)) { continue; @@ -1426,7 +1428,7 @@ void Account::readDraftCursors(PeerId peerId, Data::HistoryDrafts &map) { ? Data::DraftKey::FromSerialized(keyValue) : keysOld ? Data::DraftKey::FromSerializedOld(keyValueOld) - : Data::DraftKey::Local(0); + : Data::DraftKey::Local(MsgId(), PeerId()); qint32 position = 0, anchor = 0, scroll = Ui::kQFixedMax; draft.stream >> position >> anchor >> scroll; if (const auto i = map.find(key); i != end(map)) { @@ -1453,13 +1455,14 @@ void Account::readDraftCursorsLegacy( return; } - if (const auto i = map.find(Data::DraftKey::Local({})); i != end(map)) { + if (const auto i = map.find(Data::DraftKey::Local(MsgId(), PeerId())) + ; i != end(map)) { i->second->cursor = MessageCursor( localPosition, localAnchor, localScroll); } - if (const auto i = map.find(Data::DraftKey::LocalEdit({})) + if (const auto i = map.find(Data::DraftKey::LocalEdit(MsgId(), PeerId())) ; i != end(map)) { i->second->cursor = MessageCursor( editPosition, @@ -1472,7 +1475,7 @@ void Account::readDraftsWithCursors(not_null history) { const auto guard = gsl::finally([&] { if (const auto migrated = history->migrateFrom()) { readDraftsWithCursors(migrated); - migrated->clearLocalEditDraft({}); + migrated->clearLocalEditDraft(MsgId(), PeerId()); history->takeLocalDraft(migrated); } }); @@ -1643,10 +1646,11 @@ void Account::readDraftsWithCursorsLegacy( editData.text.size()); const auto topicRootId = MsgId(); + const auto monoforumPeerId = PeerId(); auto map = base::flat_map>(); if (!msgData.text.isEmpty() || msgReplyTo) { map.emplace( - Data::DraftKey::Local(topicRootId), + Data::DraftKey::Local(topicRootId, monoforumPeerId), std::make_unique( msgData, FullReplyTo{ FullMsgId(peerId, MsgId(msgReplyTo)) }, @@ -1657,7 +1661,7 @@ void Account::readDraftsWithCursorsLegacy( } if (editMsgId) { map.emplace( - Data::DraftKey::LocalEdit(topicRootId), + Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId), std::make_unique( editData, FullReplyTo{ FullMsgId(peerId, editMsgId) }, diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp index 892bda6311..64e9ff8152 100644 --- a/Telegram/SourceFiles/support/support_helper.cpp +++ b/Telegram/SourceFiles/support/support_helper.cpp @@ -54,6 +54,7 @@ constexpr auto kOccupyFor = TimeId(60); constexpr auto kReoccupyEach = 30 * crl::time(1000); constexpr auto kMaxSupportInfoLength = MaxMessageSize * 4; constexpr auto kTopicRootId = MsgId(0); +constexpr auto kMonoforumPeerId = PeerId(0); class EditInfoBox : public Ui::BoxContent { public: @@ -183,7 +184,7 @@ uint32 ParseOccupationTag(History *history) { if (!TrackHistoryOccupation(history)) { return 0; } - const auto draft = history->cloudDraft(kTopicRootId); + const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId); if (!draft) { return 0; } @@ -209,7 +210,7 @@ QString ParseOccupationName(History *history) { if (!TrackHistoryOccupation(history)) { return QString(); } - const auto draft = history->cloudDraft(kTopicRootId); + const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId); if (!draft) { return QString(); } @@ -235,7 +236,7 @@ TimeId OccupiedBySomeoneTill(History *history) { if (!TrackHistoryOccupation(history)) { return 0; } - const auto draft = history->cloudDraft(kTopicRootId); + const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId); if (!draft) { return 0; } @@ -353,7 +354,7 @@ void Helper::updateOccupiedHistory( not_null controller, History *history) { if (isOccupiedByMe(_occupiedHistory)) { - _occupiedHistory->clearCloudDraft(kTopicRootId); + _occupiedHistory->clearCloudDraft(kTopicRootId, kMonoforumPeerId); _session->api().saveDraftToCloudDelayed(_occupiedHistory); } _occupiedHistory = history; @@ -377,7 +378,10 @@ void Helper::occupyInDraft() { && !isOccupiedBySomeone(_occupiedHistory) && !_supportName.isEmpty()) { const auto draft = OccupiedDraft(_supportNameNormalized); - _occupiedHistory->createCloudDraft(kTopicRootId, &draft); + _occupiedHistory->createCloudDraft( + kTopicRootId, + kMonoforumPeerId, + &draft); _session->api().saveDraftToCloudDelayed(_occupiedHistory); _reoccupyTimer.callEach(kReoccupyEach); } @@ -386,7 +390,10 @@ void Helper::occupyInDraft() { void Helper::reoccupy() { if (isOccupiedByMe(_occupiedHistory)) { const auto draft = OccupiedDraft(_supportNameNormalized); - _occupiedHistory->createCloudDraft(kTopicRootId, &draft); + _occupiedHistory->createCloudDraft( + kTopicRootId, + kMonoforumPeerId, + &draft); _session->api().saveDraftToCloudDelayed(_occupiedHistory); } } diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 2f14936778..39f8100ffd 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1802,8 +1802,10 @@ void PeerMenuCreatePoll( peer->owner().history(peer), result.options); action.replyTo = replyTo; - const auto topicRootId = replyTo.topicRootId; - if (const auto local = action.history->localDraft(topicRootId)) { + const auto local = action.history->localDraft( + replyTo.topicRootId, + replyTo.monoforumPeerId); + if (local) { action.clearDraft = local->textWithTags.text.isEmpty(); } else { action.clearDraft = false; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 9ea12353a1..73e6e0110f 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -2150,8 +2150,9 @@ bool SessionController::switchInlineQuery( params); } else { const auto topicRootId = to.currentReplyTo.topicRootId; + const auto monoforumPeerId = to.currentReplyTo.monoforumPeerId; history->setLocalDraft(std::move(draft)); - history->clearLocalEditDraft(topicRootId); + history->clearLocalEditDraft(topicRootId, monoforumPeerId); if (to.section == Section::Replies) { const auto commentId = MsgId(); showRepliesForMessage(history, topicRootId, commentId, params);