Support drafts in monoforum sublists.

This commit is contained in:
John Preston 2025-05-20 20:32:24 +04:00
parent b2c01991a6
commit f65556acb7
30 changed files with 488 additions and 208 deletions

View file

@ -47,6 +47,7 @@ void Polls::create(
const auto topicRootId = action.replyTo.messageId const auto topicRootId = action.replyTo.messageId
? action.replyTo.topicRootId ? action.replyTo.topicRootId
: 0; : 0;
const auto monoforumPeerId = action.replyTo.monoforumPeerId;
auto sendFlags = MTPmessages_SendMedia::Flags(0); auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (action.replyTo) { if (action.replyTo) {
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
@ -54,9 +55,9 @@ void Polls::create(
const auto clearCloudDraft = action.clearDraft; const auto clearCloudDraft = action.clearDraft;
if (clearCloudDraft) { if (clearCloudDraft) {
sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
history->clearLocalDraft(topicRootId); history->clearLocalDraft(topicRootId, monoforumPeerId);
history->clearCloudDraft(topicRootId); history->clearCloudDraft(topicRootId, monoforumPeerId);
history->startSavingCloudDraft(topicRootId); history->startSavingCloudDraft(topicRootId, monoforumPeerId);
} }
const auto silentPost = ShouldSendSilent(peer, action.options); const auto silentPost = ShouldSendSilent(peer, action.options);
const auto starsPaid = std::min( const auto starsPaid = std::min(
@ -106,6 +107,7 @@ void Polls::create(
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
_session->changes().historyUpdated( _session->changes().historyUpdated(
@ -118,6 +120,7 @@ void Polls::create(
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
fail(); fail();

View file

@ -2687,13 +2687,22 @@ void Updates::feedUpdate(const MTPUpdate &update) {
const auto &data = update.c_updateDraftMessage(); const auto &data = update.c_updateDraftMessage();
const auto peerId = peerFromMTP(data.vpeer()); const auto peerId = peerFromMTP(data.vpeer());
const auto topicRootId = data.vtop_msg_id().value_or_empty(); 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.vdraft().match([&](const MTPDdraftMessage &data) {
Data::ApplyPeerCloudDraft(&session(), peerId, topicRootId, data); Data::ApplyPeerCloudDraft(
&session(),
peerId,
topicRootId,
monoforumPeerId,
data);
}, [&](const MTPDdraftMessageEmpty &data) { }, [&](const MTPDdraftMessageEmpty &data) {
Data::ClearPeerCloudDraft( Data::ClearPeerCloudDraft(
&session(), &session(),
peerId, peerId,
topicRootId, topicRootId,
monoforumPeerId,
data.vdate().value_or_empty()); data.vdate().value_or_empty());
}); });
} break; } break;

View file

@ -2064,8 +2064,13 @@ void ApiWrap::saveCurrentDraftToCloud() {
_session->local().writeDrafts(history); _session->local().writeDrafts(history);
const auto topicRootId = thread->topicRootId(); const auto topicRootId = thread->topicRootId();
const auto localDraft = history->localDraft(topicRootId); const auto monoforumPeerId = thread->monoforumPeerId();
const auto cloudDraft = history->cloudDraft(topicRootId); const auto localDraft = history->localDraft(
topicRootId,
monoforumPeerId);
const auto cloudDraft = history->cloudDraft(
topicRootId,
monoforumPeerId);
if (!Data::DraftsAreEqual(localDraft, cloudDraft) if (!Data::DraftsAreEqual(localDraft, cloudDraft)
&& !_session->supportMode()) { && !_session->supportMode()) {
saveDraftToCloudDelayed(thread); saveDraftToCloudDelayed(thread);
@ -2088,15 +2093,22 @@ void ApiWrap::saveDraftsToCloud() {
const auto history = thread->owningHistory(); const auto history = thread->owningHistory();
const auto topicRootId = thread->topicRootId(); const auto topicRootId = thread->topicRootId();
auto cloudDraft = history->cloudDraft(topicRootId); const auto monoforumPeerId = thread->monoforumPeerId();
auto localDraft = history->localDraft(topicRootId); auto cloudDraft = history->cloudDraft(topicRootId, monoforumPeerId);
auto localDraft = history->localDraft(topicRootId, monoforumPeerId);
if (cloudDraft && cloudDraft->saveRequestId) { if (cloudDraft && cloudDraft->saveRequestId) {
request(base::take(cloudDraft->saveRequestId)).cancel(); request(base::take(cloudDraft->saveRequestId)).cancel();
} }
if (!_session->supportMode()) { if (!_session->supportMode()) {
cloudDraft = history->createCloudDraft(topicRootId, localDraft); cloudDraft = history->createCloudDraft(
topicRootId,
monoforumPeerId,
localDraft);
} else if (!cloudDraft) { } else if (!cloudDraft) {
cloudDraft = history->createCloudDraft(topicRootId, nullptr); cloudDraft = history->createCloudDraft(
topicRootId,
monoforumPeerId,
nullptr);
} }
auto flags = MTPmessages_SaveDraft::Flags(0); auto flags = MTPmessages_SaveDraft::Flags(0);
@ -2106,7 +2118,9 @@ void ApiWrap::saveDraftsToCloud() {
} else if (!cloudDraft->webpage.url.isEmpty()) { } else if (!cloudDraft->webpage.url.isEmpty()) {
flags |= MTPmessages_SaveDraft::Flag::f_media; 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; flags |= MTPmessages_SaveDraft::Flag::f_reply_to;
} }
if (!textWithTags.tags.isEmpty()) { if (!textWithTags.tags.isEmpty()) {
@ -2117,7 +2131,7 @@ void ApiWrap::saveDraftsToCloud() {
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags), TextUtilities::ConvertTextTagsToEntities(textWithTags.tags),
Api::ConvertOption::SkipLocal); Api::ConvertOption::SkipLocal);
history->startSavingCloudDraft(topicRootId); history->startSavingCloudDraft(topicRootId, monoforumPeerId);
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft( cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(
MTP_flags(flags), MTP_flags(flags),
ReplyToForMTP(history, cloudDraft->reply), ReplyToForMTP(history, cloudDraft->reply),
@ -2132,11 +2146,15 @@ void ApiWrap::saveDraftsToCloud() {
const auto requestId = response.requestId; const auto requestId = response.requestId;
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
if (const auto cloudDraft = history->cloudDraft(topicRootId)) { const auto cloudDraft = history->cloudDraft(
topicRootId,
monoforumPeerId);
if (cloudDraft) {
if (cloudDraft->saveRequestId == requestId) { if (cloudDraft->saveRequestId == requestId) {
cloudDraft->saveRequestId = 0; cloudDraft->saveRequestId = 0;
history->draftSavedToCloud(topicRootId); history->draftSavedToCloud(topicRootId, monoforumPeerId);
} }
} }
const auto i = _draftsSaveRequestIds.find(weak); const auto i = _draftsSaveRequestIds.find(weak);
@ -2149,10 +2167,14 @@ void ApiWrap::saveDraftsToCloud() {
const auto requestId = response.requestId; const auto requestId = response.requestId;
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
if (const auto cloudDraft = history->cloudDraft(topicRootId)) { const auto cloudDraft = history->cloudDraft(
topicRootId,
monoforumPeerId);
if (cloudDraft) {
if (cloudDraft->saveRequestId == requestId) { if (cloudDraft->saveRequestId == requestId) {
history->clearCloudDraft(topicRootId); history->clearCloudDraft(topicRootId, monoforumPeerId);
} }
} }
const auto i = _draftsSaveRequestIds.find(weak); const auto i = _draftsSaveRequestIds.find(weak);
@ -3223,7 +3245,10 @@ void ApiWrap::sendAction(const SendAction &action) {
void ApiWrap::finishForwarding(const SendAction &action) { void ApiWrap::finishForwarding(const SendAction &action) {
const auto history = action.history; const auto history = action.history;
const auto topicRootId = action.replyTo.topicRootId; 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()) { if (!toForward.items.empty()) {
const auto error = GetErrorForSending( const auto error = GetErrorForSending(
history->peer, history->peer,
@ -3236,7 +3261,7 @@ void ApiWrap::finishForwarding(const SendAction &action) {
} }
forwardMessages(std::move(toForward), action); forwardMessages(std::move(toForward), action);
history->setForwardDraft(topicRootId, {}); history->setForwardDraft(topicRootId, monoforumPeerId, {});
} }
_session->data().sendHistoryChangeNotifications(); _session->data().sendHistoryChangeNotifications();
@ -3728,6 +3753,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
const auto clearCloudDraft = action.clearDraft; const auto clearCloudDraft = action.clearDraft;
const auto draftTopicRootId = action.replyTo.topicRootId; const auto draftTopicRootId = action.replyTo.topicRootId;
const auto draftMonoforumPeerId = action.replyTo.monoforumPeerId;
const auto replyTo = action.replyTo.messageId const auto replyTo = action.replyTo.messageId
? peer->owner().message(action.replyTo.messageId) ? peer->owner().message(action.replyTo.messageId)
: nullptr; : nullptr;
@ -3837,8 +3863,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (clearCloudDraft) { if (clearCloudDraft) {
sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft; sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
history->clearCloudDraft(draftTopicRootId); history->clearCloudDraft(draftTopicRootId, draftMonoforumPeerId);
history->startSavingCloudDraft(draftTopicRootId); history->startSavingCloudDraft(
draftTopicRootId,
draftMonoforumPeerId);
} }
const auto sendAs = action.options.sendAs; const auto sendAs = action.options.sendAs;
if (sendAs) { if (sendAs) {
@ -3884,6 +3912,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
draftTopicRootId, draftTopicRootId,
draftMonoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
}; };
@ -3898,6 +3927,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
draftTopicRootId, draftTopicRootId,
draftMonoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
}; };
@ -4016,6 +4046,7 @@ void ApiWrap::sendInlineResult(
const auto topicRootId = action.replyTo.messageId const auto topicRootId = action.replyTo.messageId
? action.replyTo.topicRootId ? action.replyTo.topicRootId
: 0; : 0;
const auto monoforumPeerId = action.replyTo.monoforumPeerId;
using SendFlag = MTPmessages_SendInlineBotResult::Flag; using SendFlag = MTPmessages_SendInlineBotResult::Flag;
auto flags = NewMessageFlags(peer); auto flags = NewMessageFlags(peer);
@ -4068,8 +4099,8 @@ void ApiWrap::sendInlineResult(
.postAuthor = NewMessagePostAuthor(action), .postAuthor = NewMessagePostAuthor(action),
}); });
history->clearCloudDraft(topicRootId); history->clearCloudDraft(topicRootId, monoforumPeerId);
history->startSavingCloudDraft(topicRootId); history->startSavingCloudDraft(topicRootId, monoforumPeerId);
auto &histories = history->owner().histories(); auto &histories = history->owner().histories();
histories.sendPreparedMessage( histories.sendPreparedMessage(
@ -4090,6 +4121,7 @@ void ApiWrap::sendInlineResult(
), [=](const MTPUpdates &result, const MTP::Response &response) { ), [=](const MTPUpdates &result, const MTP::Response &response) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
if (done) { if (done) {
done(true); done(true);
@ -4098,6 +4130,7 @@ void ApiWrap::sendInlineResult(
sendMessageFail(error, peer, randomId, newId); sendMessageFail(error, peer, randomId, newId);
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, topicRootId,
monoforumPeerId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
if (done) { if (done) {
done(false); done(false);

View file

@ -70,10 +70,11 @@ void ApplyPeerCloudDraft(
not_null<Main::Session*> session, not_null<Main::Session*> session,
PeerId peerId, PeerId peerId,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
const MTPDdraftMessage &draft) { const MTPDdraftMessage &draft) {
const auto history = session->data().history(peerId); const auto history = session->data().history(peerId);
const auto date = draft.vdate().v; const auto date = draft.vdate().v;
if (history->skipCloudDraftUpdate(topicRootId, date)) { if (history->skipCloudDraftUpdate(topicRootId, monoforumPeerId, date)) {
return; return;
} }
const auto textWithTags = TextWithTags{ const auto textWithTags = TextWithTags{
@ -87,6 +88,7 @@ void ApplyPeerCloudDraft(
? ReplyToFromMTP(history, *draft.vreply_to()) ? ReplyToFromMTP(history, *draft.vreply_to())
: FullReplyTo(); : FullReplyTo();
replyTo.topicRootId = topicRootId; replyTo.topicRootId = topicRootId;
replyTo.monoforumPeerId = monoforumPeerId;
auto webpage = WebPageDraft{ auto webpage = WebPageDraft{
.invert = draft.is_invert_media(), .invert = draft.is_invert_media(),
.removed = draft.is_no_webpage(), .removed = draft.is_no_webpage(),
@ -112,21 +114,22 @@ void ApplyPeerCloudDraft(
cloudDraft->date = date; cloudDraft->date = date;
history->setCloudDraft(std::move(cloudDraft)); history->setCloudDraft(std::move(cloudDraft));
history->applyCloudDraft(topicRootId); history->applyCloudDraft(topicRootId, monoforumPeerId);
} }
void ClearPeerCloudDraft( void ClearPeerCloudDraft(
not_null<Main::Session*> session, not_null<Main::Session*> session,
PeerId peerId, PeerId peerId,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
TimeId date) { TimeId date) {
const auto history = session->data().history(peerId); const auto history = session->data().history(peerId);
if (history->skipCloudDraftUpdate(topicRootId, date)) { if (history->skipCloudDraftUpdate(topicRootId, monoforumPeerId, date)) {
return; return;
} }
history->clearCloudDraft(topicRootId); history->clearCloudDraft(topicRootId, monoforumPeerId);
history->applyCloudDraft(topicRootId); history->applyCloudDraft(topicRootId, monoforumPeerId);
} }
void SetChatLinkDraft(not_null<PeerData*> peer, TextWithEntities draft) { void SetChatLinkDraft(not_null<PeerData*> peer, TextWithEntities draft) {
@ -146,12 +149,16 @@ void SetChatLinkDraft(not_null<PeerData*> peer, TextWithEntities draft) {
}; };
const auto history = peer->owner().history(peer->id); const auto history = peer->owner().history(peer->id);
const auto topicRootId = MsgId(); const auto topicRootId = MsgId();
const auto monoforumPeerId = PeerId();
history->setLocalDraft(std::make_unique<Data::Draft>( history->setLocalDraft(std::make_unique<Data::Draft>(
textWithTags, textWithTags,
FullReplyTo{ .topicRootId = topicRootId }, FullReplyTo{
.topicRootId = topicRootId,
.monoforumPeerId = monoforumPeerId,
},
cursor, cursor,
Data::WebPageDraft())); Data::WebPageDraft()));
history->clearLocalEditDraft(topicRootId); history->clearLocalEditDraft(topicRootId, monoforumPeerId);
history->session().changes().entryUpdated( history->session().changes().entryUpdated(
history, history,
Data::EntryUpdate::Flag::LocalDraftSet); Data::EntryUpdate::Flag::LocalDraftSet);

View file

@ -23,11 +23,13 @@ void ApplyPeerCloudDraft(
not_null<Main::Session*> session, not_null<Main::Session*> session,
PeerId peerId, PeerId peerId,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
const MTPDdraftMessage &draft); const MTPDdraftMessage &draft);
void ClearPeerCloudDraft( void ClearPeerCloudDraft(
not_null<Main::Session*> session, not_null<Main::Session*> session,
PeerId peerId, PeerId peerId,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
TimeId date); TimeId date);
struct WebPageDraft { struct WebPageDraft {
@ -72,22 +74,38 @@ public:
[[nodiscard]] static constexpr DraftKey None() { [[nodiscard]] static constexpr DraftKey None() {
return 0; return 0;
} }
[[nodiscard]] static constexpr DraftKey Local(MsgId topicRootId) { [[nodiscard]] static constexpr DraftKey Local(
return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) MsgId topicRootId,
PeerId monoforumPeerId) {
return Invalid(topicRootId, monoforumPeerId)
? None() ? None()
: (topicRootId ? topicRootId.bare : kLocalDraftIndex); : (topicRootId
? topicRootId.bare
: monoforumPeerId
? (monoforumPeerId.value + kMonoforumDraftBit)
: kLocalDraftIndex);
} }
[[nodiscard]] static constexpr DraftKey LocalEdit(MsgId topicRootId) { [[nodiscard]] static constexpr DraftKey LocalEdit(
return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) MsgId topicRootId,
PeerId monoforumPeerId) {
return Invalid(topicRootId, monoforumPeerId)
? None() ? None()
: ((topicRootId ? topicRootId.bare : kLocalDraftIndex) : (kEditDraftShift
+ kEditDraftShift); + (topicRootId
? topicRootId.bare
: monoforumPeerId
? (monoforumPeerId.value + kMonoforumDraftBit)
: kLocalDraftIndex));
} }
[[nodiscard]] static constexpr DraftKey Cloud(MsgId topicRootId) { [[nodiscard]] static constexpr DraftKey Cloud(
return (topicRootId < 0 || topicRootId >= ServerMaxMsgId) MsgId topicRootId,
PeerId monoforumPeerId) {
return Invalid(topicRootId, monoforumPeerId)
? None() ? None()
: topicRootId : topicRootId
? (kCloudDraftShift + topicRootId.bare) ? (kCloudDraftShift + topicRootId.bare)
: monoforumPeerId
? (kCloudDraftShift + monoforumPeerId.value + kMonoforumDraftBit)
: kCloudDraftIndex; : kCloudDraftIndex;
} }
[[nodiscard]] static constexpr DraftKey Scheduled() { [[nodiscard]] static constexpr DraftKey Scheduled() {
@ -120,40 +138,62 @@ public:
return !value return !value
? None() ? None()
: (value == kLocalDraftIndex + kEditDraftShiftOld) : (value == kLocalDraftIndex + kEditDraftShiftOld)
? LocalEdit(0) ? LocalEdit(MsgId(), PeerId())
: (value == kScheduledDraftIndex + kEditDraftShiftOld) : (value == kScheduledDraftIndex + kEditDraftShiftOld)
? ScheduledEdit() ? ScheduledEdit()
: (value > 0 && value < 0x4000'0000) : (value > 0 && value < 0x4000'0000)
? Local(MsgId(value)) ? Local(MsgId(value), PeerId())
: (value > kEditDraftShiftOld : (value > kEditDraftShiftOld
&& value < kEditDraftShiftOld + 0x4000'000) && value < kEditDraftShiftOld + 0x4000'000)
? LocalEdit(int64(value - kEditDraftShiftOld)) ? LocalEdit(MsgId(int64(value - kEditDraftShiftOld)), PeerId())
: None(); : None();
} }
[[nodiscard]] constexpr bool isLocal() const { [[nodiscard]] constexpr bool isLocal() const {
return (_value == kLocalDraftIndex) return (_value == kLocalDraftIndex)
|| (_value > 0 && _value < ServerMaxMsgId.bare); || (_value > 0
&& (_value & kMonoforumDraftMask) < ServerMaxMsgId.bare);
} }
[[nodiscard]] constexpr bool isCloud() const { [[nodiscard]] constexpr bool isCloud() const {
return (_value == kCloudDraftIndex) return (_value == kCloudDraftIndex)
|| (_value > kCloudDraftShift || ((_value & kMonoforumDraftMask) > kCloudDraftShift
&& _value < kCloudDraftShift + ServerMaxMsgId.bare); && ((_value & kMonoforumDraftMask)
< kCloudDraftShift + ServerMaxMsgId.bare));
} }
[[nodiscard]] constexpr MsgId topicRootId() const { [[nodiscard]] constexpr MsgId topicRootId() const {
const auto max = ServerMaxMsgId.bare; 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); return (_value - kCloudDraftShift);
} else if (_value > kEditDraftShift && _value < kEditDraftShift + max) { } else if ((_value > kEditDraftShift)
&& (_value < kEditDraftShift + max)) {
return (_value - kEditDraftShift); return (_value - kEditDraftShift);
} else if (_value > 0 && _value < max) { } else if (_value > 0 && _value < max) {
return _value; return _value;
} }
return 0; 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 auto operator<=>(DraftKey, DraftKey) = default;
friend inline constexpr bool operator==(DraftKey, DraftKey) = default;
inline explicit operator bool() const { inline explicit operator bool() const {
return _value != 0; return _value != 0;
@ -163,9 +203,20 @@ private:
constexpr DraftKey(int64 value) : _value(value) { 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 kLocalDraftIndex = -1;
static constexpr auto kCloudDraftIndex = -2; static constexpr auto kCloudDraftIndex = -2;
static constexpr auto kScheduledDraftIndex = -3; 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 kEditDraftShift = ServerMaxMsgId.bare;
static constexpr auto kCloudDraftShift = 2 * ServerMaxMsgId.bare; static constexpr auto kCloudDraftShift = 2 * ServerMaxMsgId.bare;
static constexpr auto kShortcutDraftShift = 3 * ServerMaxMsgId.bare; static constexpr auto kShortcutDraftShift = 3 * ServerMaxMsgId.bare;

View file

@ -73,7 +73,7 @@ Forum::~Forum() {
const auto peerId = _history->peer->id; const auto peerId = _history->peer->id;
for (const auto &[rootId, topic] : _topics) { for (const auto &[rootId, topic] : _topics) {
storage.unload(Storage::SharedMediaUnloadThread(peerId, rootId)); storage.unload(Storage::SharedMediaUnloadThread(peerId, rootId));
_history->setForwardDraft(rootId, {}); _history->setForwardDraft(rootId, PeerId(), {});
const auto raw = topic.get(); const auto raw = topic.get();
changes.topicRemoved(raw); changes.topicRemoved(raw);
@ -197,7 +197,7 @@ void Forum::applyTopicDeleted(MsgId rootId) {
session().storage().unload(Storage::SharedMediaUnloadThread( session().storage().unload(Storage::SharedMediaUnloadThread(
_history->peer->id, _history->peer->id,
rootId)); rootId));
_history->setForwardDraft(rootId, {}); _history->setForwardDraft(rootId, PeerId(), {});
} }
} }

View file

@ -406,6 +406,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) {
&session(), &session(),
channel()->id, channel()->id,
_rootId, _rootId,
PeerId(),
data); data);
}, [](const MTPDdraftMessageEmpty&) {}); }, [](const MTPDdraftMessageEmpty&) {});
} }
@ -709,7 +710,7 @@ void ForumTopic::requestChatListMessage() {
TimeId ForumTopic::adjustedChatListTimeId() const { TimeId ForumTopic::adjustedChatListTimeId() const {
const auto result = chatListTimeId(); 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()) { if (!Data::DraftIsNull(draft) && !session().supportMode()) {
return std::max(result, draft->date); return std::max(result, draft->date);
} }

View file

@ -180,11 +180,11 @@ struct FullReplyTo {
PeerId monoforumPeerId = 0; PeerId monoforumPeerId = 0;
int quoteOffset = 0; int quoteOffset = 0;
[[nodiscard]] bool valid() const { [[nodiscard]] bool replying() const {
return messageId || (storyId && storyId.peer) || monoforumPeerId; return messageId || (storyId && storyId.peer);
} }
explicit operator bool() const { explicit operator bool() const {
return valid(); return replying() || monoforumPeerId;
} }
friend inline auto operator<=>(FullReplyTo, FullReplyTo) = default; friend inline auto operator<=>(FullReplyTo, FullReplyTo) = default;
friend inline bool operator==(FullReplyTo, FullReplyTo) = default; friend inline bool operator==(FullReplyTo, FullReplyTo) = default;

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_saved_messages.h" #include "data/data_saved_messages.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_changes.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_saved_sublist.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 { bool SavedMessages::supported() const {
return !_unsupported; return !_unsupported;

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_drafts.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_messages.h" #include "data/data_messages.h"
#include "data/data_peer.h" #include "data/data_peer.h"
@ -695,15 +696,18 @@ void SavedSublist::subscribeToUnreadChanges() {
void SavedSublist::applyMonoforumDialog( void SavedSublist::applyMonoforumDialog(
const MTPDmonoForumDialog &data, const MTPDmonoForumDialog &data,
not_null<HistoryItem*> topItem) { not_null<HistoryItem*> topItem) {
//if (const auto draft = data.vdraft()) { // #TODO monoforum if (const auto parent = parentChat()) {
// draft->match([&](const MTPDdraftMessage &data) { if (const auto draft = data.vdraft()) {
// Data::ApplyPeerCloudDraft( draft->match([&](const MTPDdraftMessage &data) {
// &session(), Data::ApplyPeerCloudDraft(
// channel()->id, &session(),
// _rootId, parent->id,
// data); MsgId(),
// }, [](const MTPDdraftMessageEmpty&) {}); sublistPeer()->id,
//} data);
}, [](const MTPDdraftMessageEmpty&) {});
}
}
setInboxReadTill( setInboxReadTill(
data.vread_inbox_max_id().v, data.vread_inbox_max_id().v,
@ -712,6 +716,18 @@ void SavedSublist::applyMonoforumDialog(
applyMaybeLast(topItem); 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 { rpl::producer<> SavedSublist::changes() const {
return _listChanges.events(); return _listChanges.events();
} }

View file

@ -72,6 +72,8 @@ public:
void readTillEnd(); void readTillEnd();
void requestChatListMessage(); void requestChatListMessage();
TimeId adjustedChatListTimeId() const override;
int fixedOnTopIndex() const override; int fixedOnTopIndex() const override;
bool shouldBeInChatList() const override; bool shouldBeInChatList() const override;
Dialogs::UnreadState chatListUnreadState() const override; Dialogs::UnreadState chatListUnreadState() const override;

View file

@ -32,6 +32,13 @@ MsgId Thread::topicRootId() const {
return MsgId(); return MsgId();
} }
PeerId Thread::monoforumPeerId() const {
if (const auto sublist = asSublist()) {
return sublist->sublistPeer()->id;
}
return PeerId();
}
PeerData *Thread::maybeSublistPeer() const { PeerData *Thread::maybeSublistPeer() const {
if (const auto sublist = asSublist()) { if (const auto sublist = asSublist()) {
return sublist->sublistPeer(); return sublist->sublistPeer();

View file

@ -67,6 +67,7 @@ public:
return const_cast<Thread*>(this)->owningHistory(); return const_cast<Thread*>(this)->owningHistory();
} }
[[nodiscard]] MsgId topicRootId() const; [[nodiscard]] MsgId topicRootId() const;
[[nodiscard]] PeerId monoforumPeerId() const;
[[nodiscard]] PeerData *maybeSublistPeer() const; [[nodiscard]] PeerData *maybeSublistPeer() const;
[[nodiscard]] not_null<PeerData*> peer() const; [[nodiscard]] not_null<PeerData*> peer() const;
[[nodiscard]] PeerNotifySettings &notify(); [[nodiscard]] PeerNotifySettings &notify();

View file

@ -382,8 +382,6 @@ struct ForwardDraft {
const ForwardDraft&) = default; const ForwardDraft&) = default;
}; };
using ForwardDrafts = base::flat_map<MsgId, ForwardDraft>;
struct ResolvedForwardDraft { struct ResolvedForwardDraft {
HistoryItemsList items; HistoryItemsList items;
ForwardOptions options = ForwardOptions::PreserveInfo; ForwardOptions options = ForwardOptions::PreserveInfo;

View file

@ -962,10 +962,12 @@ void RowPainter::Paint(
if (!thread) { if (!thread) {
return nullptr; 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. // Draw item, if there are unread messages.
const auto draft = thread->owningHistory()->cloudDraft( const auto draft = thread->owningHistory()->cloudDraft(
thread->topicRootId()); thread->topicRootId(),
thread->monoforumPeerId());
if (!Data::DraftIsNull(draft)) { if (!Data::DraftIsNull(draft)) {
return draft; return draft;
} }

View file

@ -206,33 +206,39 @@ void History::itemVanished(not_null<HistoryItem*> item) {
void History::takeLocalDraft(not_null<History*> from) { void History::takeLocalDraft(not_null<History*> from) {
const auto topicRootId = MsgId(0); 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)) { if (i == end(from->_drafts)) {
return; return;
} }
auto &draft = i->second; auto &draft = i->second;
if (!draft->textWithTags.text.isEmpty() 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. // Edit and reply to drafts can't migrate.
// Cloud drafts do not migrate automatically. // Cloud drafts do not migrate automatically.
draft->reply = FullReplyTo(); draft->reply = FullReplyTo();
setLocalDraft(std::move(draft)); setLocalDraft(std::move(draft));
} }
from->clearLocalDraft(topicRootId); from->clearLocalDraft(topicRootId, monoforumPeerId);
session().api().saveDraftToCloudDelayed(from); session().api().saveDraftToCloudDelayed(from);
} }
void History::createLocalDraftFromCloud(MsgId topicRootId) { void History::createLocalDraftFromCloud(
const auto draft = cloudDraft(topicRootId); MsgId topicRootId,
PeerId monoforumPeerId) {
const auto draft = cloudDraft(topicRootId, monoforumPeerId);
if (!draft) { if (!draft) {
clearLocalDraft(topicRootId); clearLocalDraft(topicRootId, monoforumPeerId);
return; return;
} else if (Data::DraftIsNull(draft) || !draft->date) { } else if (Data::DraftIsNull(draft) || !draft->date) {
return; return;
} }
draft->reply.topicRootId = topicRootId; draft->reply.topicRootId = topicRootId;
auto existing = localDraft(topicRootId); draft->reply.monoforumPeerId = monoforumPeerId;
auto existing = localDraft(topicRootId, monoforumPeerId);
if (Data::DraftIsNull(existing) if (Data::DraftIsNull(existing)
|| !existing->date || !existing->date
|| draft->date >= existing->date) { || draft->date >= existing->date) {
@ -242,7 +248,7 @@ void History::createLocalDraftFromCloud(MsgId topicRootId) {
draft->reply, draft->reply,
draft->cursor, draft->cursor,
draft->webpage)); draft->webpage));
existing = localDraft(topicRootId); existing = localDraft(topicRootId, monoforumPeerId);
} else if (existing != draft) { } else if (existing != draft) {
existing->textWithTags = draft->textWithTags; existing->textWithTags = draft->textWithTags;
existing->reply = draft->reply; existing->reply = draft->reply;
@ -268,7 +274,7 @@ void History::setDraft(
return; return;
} }
const auto cloudThread = key.isCloud() const auto cloudThread = key.isCloud()
? threadFor(key.topicRootId()) ? threadFor(key.topicRootId(), key.monoforumPeerId())
: nullptr; : nullptr;
if (cloudThread) { if (cloudThread) {
cloudThread->cloudDraftTextCache().clear(); cloudThread->cloudDraftTextCache().clear();
@ -298,7 +304,7 @@ void History::clearDraft(Data::DraftKey key) {
void History::clearDrafts() { void History::clearDrafts() {
for (auto &[key, draft] : base::take(_drafts)) { for (auto &[key, draft] : base::take(_drafts)) {
const auto cloudThread = key.isCloud() const auto cloudThread = key.isCloud()
? threadFor(key.topicRootId()) ? threadFor(key.topicRootId(), key.monoforumPeerId())
: nullptr; : nullptr;
if (cloudThread) { if (cloudThread) {
cloudThread->cloudDraftTextCache().clear(); cloudThread->cloudDraftTextCache().clear();
@ -309,25 +315,30 @@ void History::clearDrafts() {
Data::Draft *History::createCloudDraft( Data::Draft *History::createCloudDraft(
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
const Data::Draft *fromDraft) { const Data::Draft *fromDraft) {
if (Data::DraftIsNull(fromDraft)) { if (Data::DraftIsNull(fromDraft)) {
setCloudDraft(std::make_unique<Data::Draft>( setCloudDraft(std::make_unique<Data::Draft>(
TextWithTags(), TextWithTags(),
FullReplyTo{ .topicRootId = topicRootId }, FullReplyTo{
.topicRootId = topicRootId,
.monoforumPeerId = monoforumPeerId,
},
MessageCursor(), MessageCursor(),
Data::WebPageDraft())); Data::WebPageDraft()));
cloudDraft(topicRootId)->date = TimeId(0); cloudDraft(topicRootId, monoforumPeerId)->date = TimeId(0);
} else { } else {
auto existing = cloudDraft(topicRootId); auto existing = cloudDraft(topicRootId, monoforumPeerId);
if (!existing) { if (!existing) {
auto reply = fromDraft->reply; auto reply = fromDraft->reply;
reply.topicRootId = topicRootId; reply.topicRootId = topicRootId;
reply.monoforumPeerId = monoforumPeerId;
setCloudDraft(std::make_unique<Data::Draft>( setCloudDraft(std::make_unique<Data::Draft>(
fromDraft->textWithTags, fromDraft->textWithTags,
reply, reply,
fromDraft->cursor, fromDraft->cursor,
fromDraft->webpage)); fromDraft->webpage));
existing = cloudDraft(topicRootId); existing = cloudDraft(topicRootId, monoforumPeerId);
} else if (existing != fromDraft) { } else if (existing != fromDraft) {
existing->textWithTags = fromDraft->textWithTags; existing->textWithTags = fromDraft->textWithTags;
existing->reply = fromDraft->reply; existing->reply = fromDraft->reply;
@ -336,44 +347,56 @@ Data::Draft *History::createCloudDraft(
} }
existing->date = base::unixtime::now(); existing->date = base::unixtime::now();
existing->reply.topicRootId = topicRootId; 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->cloudDraftTextCache().clear();
thread->updateChatListSortPosition(); thread->updateChatListSortPosition();
} }
return cloudDraft(topicRootId); return cloudDraft(topicRootId, monoforumPeerId);
} }
bool History::skipCloudDraftUpdate(MsgId topicRootId, TimeId date) const { bool History::skipCloudDraftUpdate(
const auto i = _acceptCloudDraftsAfter.find(topicRootId); MsgId topicRootId,
return _savingCloudDraftRequests.contains(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); || (i != _acceptCloudDraftsAfter.end() && date < i->second);
} }
void History::startSavingCloudDraft(MsgId topicRootId) { void History::startSavingCloudDraft(
++_savingCloudDraftRequests[topicRootId]; MsgId topicRootId,
PeerId monoforumPeerId) {
const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId);
++_savingCloudDraftRequests[key];
} }
void History::finishSavingCloudDraft(MsgId topicRootId, TimeId savedAt) { void History::finishSavingCloudDraft(
const auto i = _savingCloudDraftRequests.find(topicRootId); 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 != _savingCloudDraftRequests.end()) {
if (--i->second <= 0) { if (--i->second <= 0) {
_savingCloudDraftRequests.erase(i); _savingCloudDraftRequests.erase(i);
} }
} }
auto &after = _acceptCloudDraftsAfter[topicRootId]; auto &after = _acceptCloudDraftsAfter[key];
after = std::max(after, savedAt + kSkipCloudDraftsFor); after = std::max(after, savedAt + kSkipCloudDraftsFor);
} }
void History::applyCloudDraft(MsgId topicRootId) { void History::applyCloudDraft(MsgId topicRootId, PeerId monoforumPeerId) {
if (!topicRootId && session().supportMode()) { if (!topicRootId && session().supportMode()) {
updateChatListEntry(); updateChatListEntry();
session().supportHelper().cloudDraftChanged(this); session().supportHelper().cloudDraftChanged(this);
} else { } else {
createLocalDraftFromCloud(topicRootId); createLocalDraftFromCloud(topicRootId, monoforumPeerId);
if (const auto thread = threadFor(topicRootId)) { if (const auto thread = threadFor(topicRootId, monoforumPeerId)) {
thread->updateChatListSortPosition(); thread->updateChatListSortPosition();
if (!topicRootId) { if (!topicRootId) {
session().changes().historyUpdated( session().changes().historyUpdated(
@ -388,17 +411,19 @@ void History::applyCloudDraft(MsgId topicRootId) {
} }
} }
void History::draftSavedToCloud(MsgId topicRootId) { void History::draftSavedToCloud(MsgId topicRootId, PeerId monoforumPeerId) {
if (const auto thread = threadFor(topicRootId)) { if (const auto thread = threadFor(topicRootId, monoforumPeerId)) {
thread->updateChatListEntry(); thread->updateChatListEntry();
} }
session().local().writeDrafts(this); session().local().writeDrafts(this);
} }
const Data::ForwardDraft &History::forwardDraft( 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(); 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; return (i != end(_forwardDrafts)) ? i->second : kEmpty;
} }
@ -411,11 +436,12 @@ Data::ResolvedForwardDraft History::resolveForwardDraft(
} }
Data::ResolvedForwardDraft History::resolveForwardDraft( Data::ResolvedForwardDraft History::resolveForwardDraft(
MsgId topicRootId) { MsgId topicRootId,
const auto &draft = forwardDraft(topicRootId); PeerId monoforumPeerId) {
const auto &draft = forwardDraft(topicRootId, monoforumPeerId);
auto result = resolveForwardDraft(draft); auto result = resolveForwardDraft(draft);
if (result.items.size() != draft.ids.size()) { if (result.items.size() != draft.ids.size()) {
setForwardDraft(topicRootId, { setForwardDraft(topicRootId, monoforumPeerId, {
.ids = owner().itemsToIds(result.items), .ids = owner().itemsToIds(result.items),
.options = result.options, .options = result.options,
}); });
@ -425,24 +451,23 @@ Data::ResolvedForwardDraft History::resolveForwardDraft(
void History::setForwardDraft( void History::setForwardDraft(
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
Data::ForwardDraft &&draft) { Data::ForwardDraft &&draft) {
auto changed = false; auto changed = false;
const auto key = Data::DraftKey::Local(topicRootId, monoforumPeerId);
if (draft.ids.empty()) { if (draft.ids.empty()) {
changed = _forwardDrafts.remove(topicRootId); changed = _forwardDrafts.remove(key);
} else { } else {
auto &now = _forwardDrafts[topicRootId]; auto &now = _forwardDrafts[key];
if (now != draft) { if (now != draft) {
now = std::move(draft); now = std::move(draft);
changed = true; changed = true;
} }
} }
if (changed) { if (changed) {
const auto entry = topicRootId if (const auto thread = threadFor(topicRootId, monoforumPeerId)) {
? peer->forumTopicFor(topicRootId)
: (Dialogs::Entry*)this;
if (entry) {
session().changes().entryUpdated( session().changes().entryUpdated(
entry, thread,
Data::EntryUpdate::Flag::ForwardDraft); Data::EntryUpdate::Flag::ForwardDraft);
} }
} }
@ -2081,7 +2106,7 @@ void History::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
TimeId History::adjustedChatListTimeId() const { TimeId History::adjustedChatListTimeId() const {
const auto result = chatListTimeId(); const auto result = chatListTimeId();
if (const auto draft = cloudDraft(MsgId(0))) { if (const auto draft = cloudDraft(MsgId(), PeerId())) {
if (!peer->forum() if (!peer->forum()
&& !Data::DraftIsNull(draft) && !Data::DraftIsNull(draft)
&& !session().supportMode()) { && !session().supportMode()) {
@ -2871,7 +2896,8 @@ void History::applyDialog(
Data::ApplyPeerCloudDraft( Data::ApplyPeerCloudDraft(
&session(), &session(),
peer->id, peer->id,
MsgId(0), // topicRootId MsgId(), // topicRootId
PeerId(), // monoforumPeerId
draft->c_draftMessage()); draft->c_draftMessage());
} }
if (const auto ttl = data.vttl_period()) { if (const auto ttl = data.vttl_period()) {
@ -3101,14 +3127,22 @@ void History::forceFullResize() {
_flags |= Flag::HasPendingResizedItems; _flags |= Flag::HasPendingResizedItems;
} }
Data::Thread *History::threadFor(MsgId topicRootId) { Data::Thread *History::threadFor(MsgId topicRootId, PeerId monoforumPeerId) {
return topicRootId return topicRootId
? peer->forumTopicFor(topicRootId) ? peer->forumTopicFor(topicRootId)
: static_cast<Data::Thread*>(this); : !monoforumPeerId
? static_cast<Data::Thread*>(this)
: peer->monoforum()
? peer->monoforum()->sublistLoaded(owner().peer(monoforumPeerId))
: nullptr;
} }
const Data::Thread *History::threadFor(MsgId topicRootId) const { const Data::Thread *History::threadFor(
return const_cast<History*>(this)->threadFor(topicRootId); MsgId topicRootId,
PeerId monoforumPeerId) const {
return const_cast<History*>(this)->threadFor(
topicRootId,
monoforumPeerId);
} }
void History::forumChanged(Data::Forum *old) { void History::forumChanged(Data::Forum *old) {
@ -3137,7 +3171,7 @@ void History::forumChanged(Data::Forum *old) {
} else { } else {
_flags &= ~Flag::IsForum; _flags &= ~Flag::IsForum;
} }
if (cloudDraft(MsgId(0))) { if (cloudDraft(MsgId(), PeerId())) {
updateChatListSortPosition(); updateChatListSortPosition();
} }
_flags |= Flag::PendingAllItemsResize; _flags |= Flag::PendingAllItemsResize;
@ -3173,7 +3207,7 @@ void History::monoforumChanged(Data::SavedMessages *old) {
} else { } else {
_flags &= ~Flag::IsMonoforumAdmin; _flags &= ~Flag::IsMonoforumAdmin;
} }
if (cloudDraft(MsgId(0))) { if (cloudDraft(MsgId(), PeerId())) {
updateChatListSortPosition(); updateChatListSortPosition();
} }
_flags |= Flag::PendingAllItemsResize; _flags |= Flag::PendingAllItemsResize;

View file

@ -62,8 +62,12 @@ public:
[[nodiscard]] not_null<History*> owningHistory() override { [[nodiscard]] not_null<History*> owningHistory() override {
return this; return this;
} }
[[nodiscard]] Data::Thread *threadFor(MsgId topicRootId); [[nodiscard]] Data::Thread *threadFor(
[[nodiscard]] const Data::Thread *threadFor(MsgId topicRootId) const; MsgId topicRootId,
PeerId monoforumPeerId);
[[nodiscard]] const Data::Thread *threadFor(
MsgId topicRootId,
PeerId monoforumPeerId) const;
[[nodiscard]] auto delegateMixin() const [[nodiscard]] auto delegateMixin() const
-> not_null<HistoryMainElementDelegateMixin*> { -> not_null<HistoryMainElementDelegateMixin*> {
@ -288,60 +292,89 @@ public:
[[nodiscard]] const Data::HistoryDrafts &draftsMap() const; [[nodiscard]] const Data::HistoryDrafts &draftsMap() const;
void setDraftsMap(Data::HistoryDrafts &&map); void setDraftsMap(Data::HistoryDrafts &&map);
Data::Draft *localDraft(MsgId topicRootId) const { Data::Draft *localDraft(
return draft(Data::DraftKey::Local(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) const {
return draft(Data::DraftKey::Local(topicRootId, monoforumPeerId));
} }
Data::Draft *localEditDraft(MsgId topicRootId) const { Data::Draft *localEditDraft(
return draft(Data::DraftKey::LocalEdit(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) const {
return draft(
Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId));
} }
Data::Draft *cloudDraft(MsgId topicRootId) const { Data::Draft *cloudDraft(
return draft(Data::DraftKey::Cloud(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) const {
return draft(Data::DraftKey::Cloud(topicRootId, monoforumPeerId));
} }
void setLocalDraft(std::unique_ptr<Data::Draft> &&draft) { void setLocalDraft(std::unique_ptr<Data::Draft> &&draft) {
setDraft( setDraft(
Data::DraftKey::Local(draft->reply.topicRootId), Data::DraftKey::Local(
draft->reply.topicRootId,
draft->reply.monoforumPeerId),
std::move(draft)); std::move(draft));
} }
void setLocalEditDraft(std::unique_ptr<Data::Draft> &&draft) { void setLocalEditDraft(std::unique_ptr<Data::Draft> &&draft) {
setDraft( setDraft(
Data::DraftKey::LocalEdit(draft->reply.topicRootId), Data::DraftKey::LocalEdit(
draft->reply.topicRootId,
draft->reply.monoforumPeerId),
std::move(draft)); std::move(draft));
} }
void setCloudDraft(std::unique_ptr<Data::Draft> &&draft) { void setCloudDraft(std::unique_ptr<Data::Draft> &&draft) {
setDraft( setDraft(
Data::DraftKey::Cloud(draft->reply.topicRootId), Data::DraftKey::Cloud(
draft->reply.topicRootId,
draft->reply.monoforumPeerId),
std::move(draft)); std::move(draft));
} }
void clearLocalDraft(MsgId topicRootId) { void clearLocalDraft(
clearDraft(Data::DraftKey::Local(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) {
clearDraft(Data::DraftKey::Local(topicRootId, monoforumPeerId));
} }
void clearCloudDraft(MsgId topicRootId) { void clearCloudDraft(
clearDraft(Data::DraftKey::Cloud(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) {
clearDraft(Data::DraftKey::Cloud(topicRootId, monoforumPeerId));
} }
void clearLocalEditDraft(MsgId topicRootId) { void clearLocalEditDraft(
clearDraft(Data::DraftKey::LocalEdit(topicRootId)); MsgId topicRootId,
PeerId monoforumPeerId) {
clearDraft(Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId));
} }
void clearDrafts(); void clearDrafts();
Data::Draft *createCloudDraft( Data::Draft *createCloudDraft(
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
const Data::Draft *fromDraft); const Data::Draft *fromDraft);
[[nodiscard]] bool skipCloudDraftUpdate( [[nodiscard]] bool skipCloudDraftUpdate(
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
TimeId date) const; TimeId date) const;
void startSavingCloudDraft(MsgId topicRootId); void startSavingCloudDraft(MsgId topicRootId, PeerId monoforumPeerId);
void finishSavingCloudDraft(MsgId topicRootId, TimeId savedAt); void finishSavingCloudDraft(
MsgId topicRootId,
PeerId monoforumPeerId,
TimeId savedAt);
void takeLocalDraft(not_null<History*> from); void takeLocalDraft(not_null<History*> from);
void applyCloudDraft(MsgId topicRootId); void applyCloudDraft(MsgId topicRootId, PeerId monoforumPeerId);
void draftSavedToCloud(MsgId topicRootId); void draftSavedToCloud(MsgId topicRootId, PeerId monoforumPeerId);
void requestChatListMessage(); void requestChatListMessage();
[[nodiscard]] const Data::ForwardDraft &forwardDraft( [[nodiscard]] const Data::ForwardDraft &forwardDraft(
MsgId topicRootId) const; MsgId topicRootId,
PeerId monoforumPeerId) const;
[[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft( [[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft(
const Data::ForwardDraft &draft) const; const Data::ForwardDraft &draft) const;
[[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft( [[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft(
MsgId topicRootId); MsgId topicRootId,
void setForwardDraft(MsgId topicRootId, Data::ForwardDraft &&draft); PeerId monoforumPeerId);
void setForwardDraft(
MsgId topicRootId,
PeerId monoforumPeerId,
Data::ForwardDraft &&draft);
History *migrateSibling() const; History *migrateSibling() const;
[[nodiscard]] bool useTopPromotion() const; [[nodiscard]] bool useTopPromotion() const;
@ -548,7 +581,9 @@ private:
void viewReplaced(not_null<const Element*> was, Element *now); void viewReplaced(not_null<const Element*> was, Element *now);
void createLocalDraftFromCloud(MsgId topicRootId); void createLocalDraftFromCloud(
MsgId topicRootId,
PeerId monoforumPeerId);
HistoryItem *insertJoinedMessage(); HistoryItem *insertJoinedMessage();
void insertMessageToBlocks(not_null<HistoryItem*> item); void insertMessageToBlocks(not_null<HistoryItem*> item);
@ -606,9 +641,9 @@ private:
std::unique_ptr<HistoryTranslation> _translation; std::unique_ptr<HistoryTranslation> _translation;
Data::HistoryDrafts _drafts; Data::HistoryDrafts _drafts;
base::flat_map<MsgId, TimeId> _acceptCloudDraftsAfter; base::flat_map<Data::DraftKey, TimeId> _acceptCloudDraftsAfter;
base::flat_map<MsgId, int> _savingCloudDraftRequests; base::flat_map<Data::DraftKey, int> _savingCloudDraftRequests;
Data::ForwardDrafts _forwardDrafts; base::flat_map<Data::DraftKey, Data::ForwardDraft> _forwardDrafts;
QString _topPromotedMessage; QString _topPromotedMessage;
QString _topPromotedType; QString _topPromotedType;

View file

@ -1118,7 +1118,7 @@ void HistoryWidget::initVoiceRecordBar() {
}); });
const auto applyLocalDraft = [=] { const auto applyLocalDraft = [=] {
if (_history && _history->localDraft({})) { if (_history && _history->localDraft(MsgId(), PeerId())) {
applyDraft(); applyDraft();
} }
}; };
@ -1874,12 +1874,14 @@ void HistoryWidget::saveFieldToHistoryLocalDraft() {
} }
const auto topicRootId = MsgId(); const auto topicRootId = MsgId();
const auto monoforumPeerId = PeerId();
if (_editMsgId) { if (_editMsgId) {
_history->setLocalEditDraft(std::make_unique<Data::Draft>( _history->setLocalEditDraft(std::make_unique<Data::Draft>(
_field, _field,
FullReplyTo{ FullReplyTo{
.messageId = FullMsgId(_history->peer->id, _editMsgId), .messageId = FullMsgId(_history->peer->id, _editMsgId),
.topicRootId = topicRootId, .topicRootId = topicRootId,
.monoforumPeerId = monoforumPeerId,
}, },
_preview->draft(), _preview->draft(),
_saveEditMsgRequestId)); _saveEditMsgRequestId));
@ -1890,9 +1892,9 @@ void HistoryWidget::saveFieldToHistoryLocalDraft() {
_replyTo, _replyTo,
_preview->draft())); _preview->draft()));
} else { } 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 const auto draft = editDraft
? editDraft ? editDraft
: _history : _history
? _history->localDraft({}) ? _history->localDraft(MsgId(), PeerId())
: nullptr; : nullptr;
auto fieldAvailable = canWriteMessage(); auto fieldAvailable = canWriteMessage();
const auto editMsgId = editDraft ? editDraft->reply.messageId.msg : 0; const auto editMsgId = editDraft ? editDraft->reply.messageId.msg : 0;
@ -2241,7 +2245,7 @@ bool HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) {
requestMessageData(_editMsgId); requestMessageData(_editMsgId);
} }
} else { } else {
const auto draft = _history->localDraft({}); const auto draft = _history->localDraft(MsgId(), PeerId());
_processingReplyTo = draft ? draft->reply : FullReplyTo(); _processingReplyTo = draft ? draft->reply : FullReplyTo();
if (_processingReplyTo) { if (_processingReplyTo) {
_processingReplyItem = session().data().message( _processingReplyItem = session().data().message(
@ -2408,7 +2412,7 @@ void HistoryWidget::showHistory(
info->inlineReturnTo = wasState; info->inlineReturnTo = wasState;
} }
sendBotStartCommand(); sendBotStartCommand();
_history->clearLocalDraft({}); _history->clearLocalDraft(MsgId(), PeerId());
applyDraft(); applyDraft();
_send->finishAnimating(); _send->finishAnimating();
} }
@ -2864,10 +2868,10 @@ void HistoryWidget::unregisterDraftSources() {
} }
session().local().unregisterDraftSource( session().local().unregisterDraftSource(
_history, _history,
Data::DraftKey::Local({})); Data::DraftKey::Local(MsgId(), PeerId()));
session().local().unregisterDraftSource( session().local().unregisterDraftSource(
_history, _history,
Data::DraftKey::LocalEdit({})); Data::DraftKey::LocalEdit(MsgId(), PeerId()));
} }
void HistoryWidget::registerDraftSource() { void HistoryWidget::registerDraftSource() {
@ -2892,8 +2896,8 @@ void HistoryWidget::registerDraftSource() {
session().local().registerDraftSource( session().local().registerDraftSource(
_history, _history,
(editMsgId (editMsgId
? Data::DraftKey::LocalEdit({}) ? Data::DraftKey::LocalEdit(MsgId(), PeerId())
: Data::DraftKey::Local({})), : Data::DraftKey::Local(MsgId(), PeerId())),
std::move(draftSource)); std::move(draftSource));
} }
@ -3630,6 +3634,7 @@ void HistoryWidget::unreadCountUpdated() {
}); });
} else { } else {
const auto hideCounter = _history->isForum() const auto hideCounter = _history->isForum()
|| _history->amMonoforumAdmin()
|| !_history->trackUnreadMessages(); || !_history->trackUnreadMessages();
_cornerButtons.updateJumpDownVisibility(hideCounter _cornerButtons.updateJumpDownVisibility(hideCounter
? 0 ? 0
@ -4376,16 +4381,16 @@ void HistoryWidget::saveEditMsg() {
cancelEdit(); cancelEdit();
} }
})(); })();
if (const auto editDraft = history->localEditDraft({})) { if (const auto editDraft = history->localEditDraft({}, {})) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
history->clearLocalEditDraft({}); history->clearLocalEditDraft(MsgId(), PeerId());
history->session().local().writeDrafts(history); history->session().local().writeDrafts(history);
} }
} }
}; };
const auto fail = [=](const QString &error, mtpRequestId requestId) { const auto fail = [=](const QString &error, mtpRequestId requestId) {
if (const auto editDraft = history->localEditDraft({})) { if (const auto editDraft = history->localEditDraft({}, {})) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
editDraft->saveRequestId = 0; editDraft->saveRequestId = 0;
} }
@ -7276,7 +7281,7 @@ void HistoryWidget::editDraftOptions() {
} else { } else {
cancelReply(); cancelReply();
} }
history->setForwardDraft({}, std::move(forward)); history->setForwardDraft(MsgId(), PeerId(), std::move(forward));
_preview->apply(webpage); _preview->apply(webpage);
}; };
const auto replyToId = reply.messageId; const auto replyToId = reply.messageId;
@ -7295,7 +7300,9 @@ void HistoryWidget::editDraftOptions() {
.resolver = _preview->resolver(), .resolver = _preview->resolver(),
.done = done, .done = done,
.highlight = highlight, .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 id = base::take(_processingReplyTo);
const auto item = base::take(_processingReplyItem); const auto item = base::take(_processingReplyItem);
if (_editMsgId) { if (_editMsgId) {
if (const auto localDraft = _history->localDraft({})) { if (const auto localDraft = _history->localDraft({}, {})) {
localDraft->reply = id; localDraft->reply = id;
} else { } else {
_history->setLocalDraft(std::make_unique<Data::Draft>( _history->setLocalDraft(std::make_unique<Data::Draft>(
@ -8470,7 +8477,7 @@ void HistoryWidget::editMessage(
_replyTo, _replyTo,
_preview->draft())); _preview->draft()));
} else { } else {
_history->clearLocalDraft({}); _history->clearLocalDraft(MsgId(), PeerId());
} }
} }
@ -8580,10 +8587,10 @@ bool HistoryWidget::cancelReply(bool lastKeyboardUsed) {
updateControlsGeometry(); updateControlsGeometry();
update(); update();
} else if (const auto localDraft } else if (const auto localDraft
= (_history ? _history->localDraft({}) : nullptr)) { = (_history ? _history->localDraft({}, {}) : nullptr)) {
if (localDraft->reply) { if (localDraft->reply) {
if (localDraft->textWithTags.text.isEmpty()) { if (localDraft->textWithTags.text.isEmpty()) {
_history->clearLocalDraft({}); _history->clearLocalDraft(MsgId(), PeerId());
} else { } else {
localDraft->reply = {}; localDraft->reply = {};
} }
@ -8629,7 +8636,7 @@ void HistoryWidget::cancelEdit() {
updateReplaceMediaButton(); updateReplaceMediaButton();
_replyEditMsg = nullptr; _replyEditMsg = nullptr;
setEditMsgId(0); setEditMsgId(0);
_history->clearLocalEditDraft({}); _history->clearLocalEditDraft(MsgId(), PeerId());
applyDraft(); applyDraft();
if (_saveEditMsgRequestId) { if (_saveEditMsgRequestId) {
@ -8671,7 +8678,7 @@ void HistoryWidget::cancelFieldAreaState() {
} else if (_replyTo) { } else if (_replyTo) {
cancelReply(); cancelReply();
} else if (readyToForward()) { } else if (readyToForward()) {
_history->setForwardDraft(MsgId(), {}); _history->setForwardDraft(MsgId(), PeerId(), {});
} else if (_kbReplyTo) { } else if (_kbReplyTo) {
toggleKeyboard(); toggleKeyboard();
} }
@ -9039,7 +9046,7 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
void HistoryWidget::updateForwarding() { void HistoryWidget::updateForwarding() {
_forwardPanel->update(_history, _history _forwardPanel->update(_history, _history
? _history->resolveForwardDraft(MsgId()) ? _history->resolveForwardDraft(MsgId(), PeerId())
: Data::ResolvedForwardDraft()); : Data::ResolvedForwardDraft());
updateControlsVisibility(); updateControlsVisibility();
updateControlsGeometry(); updateControlsGeometry();

View file

@ -66,6 +66,7 @@ struct WriteRestriction {
struct SetHistoryArgs { struct SetHistoryArgs {
required<History*> history; required<History*> history;
MsgId topicRootId = 0; MsgId topicRootId = 0;
PeerId monoforumPeerId = 0;
Fn<bool()> showSlowmodeError; Fn<bool()> showSlowmodeError;
Fn<Api::SendAction()> sendActionFactory; Fn<Api::SendAction()> sendActionFactory;
rpl::producer<int> slowmodeSecondsLeft; rpl::producer<int> slowmodeSecondsLeft;

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "data/data_messages.h" #include "data/data_messages.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat.h" #include "data/data_chat.h"
@ -197,6 +198,7 @@ private:
History *_history = nullptr; History *_history = nullptr;
MsgId _topicRootId = 0; MsgId _topicRootId = 0;
PeerId _monoforumPeerId = 0;
Preview _preview; Preview _preview;
rpl::event_stream<> _editCancelled; rpl::event_stream<> _editCancelled;
@ -254,6 +256,7 @@ FieldHeader::FieldHeader(
void FieldHeader::setHistory(const SetHistoryArgs &args) { void FieldHeader::setHistory(const SetHistoryArgs &args) {
_history = *args.history; _history = *args.history;
_topicRootId = args.topicRootId; _topicRootId = args.topicRootId;
_monoforumPeerId = args.monoforumPeerId;
} }
void FieldHeader::updateTopicRootId(MsgId topicRootId) { void FieldHeader::updateTopicRootId(MsgId topicRootId) {
@ -282,7 +285,7 @@ void FieldHeader::init() {
st::historyLinkIcon.paint(p, position, width()); st::historyLinkIcon.paint(p, position, width());
} else if (isEditingMessage()) { } else if (isEditingMessage()) {
st::historyEditIcon.paint(p, position, width()); st::historyEditIcon.paint(p, position, width());
} else if (const auto reply = replyingToMessage()) { } else if (const auto reply = replyingToMessage(); reply.replying()) {
if (!reply.quote.empty()) { if (!reply.quote.empty()) {
st::historyQuoteIcon.paint(p, position, width()); st::historyQuoteIcon.paint(p, position, width());
} else { } else {
@ -760,6 +763,7 @@ void FieldHeader::editMessage(FullMsgId id, bool photoEditAllowed) {
} }
void FieldHeader::replyToMessage(FullReplyTo id) { void FieldHeader::replyToMessage(FullReplyTo id) {
id.monoforumPeerId = 0;
_replyTo = id; _replyTo = id;
} }
@ -956,6 +960,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
unregisterDraftSources(); unregisterDraftSources();
_history = history; _history = history;
_topicRootId = args.topicRootId; _topicRootId = args.topicRootId;
_monoforumPeerId = args.monoforumPeerId;
_historyLifetime.destroy(); _historyLifetime.destroy();
_header->setHistory(args); _header->setHistory(args);
registerDraftSource(); registerDraftSource();
@ -999,6 +1004,7 @@ void ComposeControls::setCurrentDialogsEntryState(
Dialogs::EntryState state) { Dialogs::EntryState state) {
unregisterDraftSources(); unregisterDraftSources();
state.currentReplyTo.topicRootId = _topicRootId; state.currentReplyTo.topicRootId = _topicRootId;
state.currentReplyTo.monoforumPeerId = _monoforumPeerId;
_currentDialogsEntryState = state; _currentDialogsEntryState = state;
updateForwarding(); updateForwarding();
registerDraftSource(); registerDraftSource();
@ -1405,6 +1411,7 @@ void ComposeControls::init() {
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
const auto history = _history; const auto history = _history;
const auto topicRootId = _topicRootId; const auto topicRootId = _topicRootId;
const auto monoforumPeerId = _monoforumPeerId;
const auto reply = _header->replyingToMessage(); const auto reply = _header->replyingToMessage();
const auto webpage = _preview->draft(); const auto webpage = _preview->draft();
@ -1417,7 +1424,10 @@ void ComposeControls::init() {
} else { } else {
cancelReplyMessage(); cancelReplyMessage();
} }
history->setForwardDraft(topicRootId, std::move(forward)); history->setForwardDraft(
topicRootId,
monoforumPeerId,
std::move(forward));
_preview->apply(webpage); _preview->apply(webpage);
_field->setFocus(); _field->setFocus();
}; };
@ -1440,6 +1450,7 @@ void ComposeControls::init() {
.clearOldDraft = [=] { ClearDraftReplyTo( .clearOldDraft = [=] { ClearDraftReplyTo(
history, history,
topicRootId, topicRootId,
monoforumPeerId,
replyToId); }, replyToId); },
}); });
}, _wrap->lifetime()); }, _wrap->lifetime());
@ -1809,8 +1820,8 @@ Data::DraftKey ComposeControls::draftKey(DraftType type) const {
case Section::Replies: case Section::Replies:
case Section::SavedSublist: case Section::SavedSublist:
return (type == DraftType::Edit) return (type == DraftType::Edit)
? Key::LocalEdit(_topicRootId) ? Key::LocalEdit(_topicRootId, _monoforumPeerId)
: Key::Local(_topicRootId); : Key::Local(_topicRootId, _monoforumPeerId);
case Section::Scheduled: case Section::Scheduled:
return (type == DraftType::Edit) return (type == DraftType::Edit)
? Key::ScheduledEdit() ? Key::ScheduledEdit()
@ -2038,7 +2049,7 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
} }
void ComposeControls::cancelForward() { void ComposeControls::cancelForward() {
_history->setForwardDraft(_topicRootId, {}); _history->setForwardDraft(_topicRootId, _monoforumPeerId, {});
updateForwarding(); updateForwarding();
} }
@ -2902,9 +2913,11 @@ void ComposeControls::toggleTabbedSelectorMode() {
&& !_regularWindow->adaptive().isOneColumn()) { && !_regularWindow->adaptive().isOneColumn()) {
Core::App().settings().setTabbedSelectorSectionEnabled(true); Core::App().settings().setTabbedSelectorSectionEnabled(true);
Core::App().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
const auto topic = _history->peer->forumTopicFor(_topicRootId); const auto thread = _history->threadFor(
_topicRootId,
_monoforumPeerId);
pushTabbedSelectorToThirdSection( pushTabbedSelectorToThirdSection(
(topic ? topic : (Data::Thread*)_history), thread ? thread : _history,
Window::SectionShow::Way::ClearStack); Window::SectionShow::Way::ClearStack);
} else { } else {
_tabbedPanel->toggleAnimated(); _tabbedPanel->toggleAnimated();
@ -2958,6 +2971,7 @@ void ComposeControls::editMessage(not_null<HistoryItem*> item) {
FullReplyTo{ FullReplyTo{
.messageId = item->fullId(), .messageId = item->fullId(),
.topicRootId = key.topicRootId(), .topicRootId = key.topicRootId(),
.monoforumPeerId = key.monoforumPeerId(),
}, },
cursor, cursor,
Data::WebPageDraft::FromItem(item))); Data::WebPageDraft::FromItem(item)));
@ -3038,6 +3052,7 @@ void ComposeControls::replyToMessage(FullReplyTo id) {
Expects(draftKeyCurrent() != Data::DraftKey::None()); Expects(draftKeyCurrent() != Data::DraftKey::None());
id.topicRootId = _topicRootId; id.topicRootId = _topicRootId;
id.monoforumPeerId = _monoforumPeerId;
if (!id) { if (!id) {
cancelReplyMessage(); cancelReplyMessage();
return; return;
@ -3045,6 +3060,7 @@ void ComposeControls::replyToMessage(FullReplyTo id) {
if (isEditingMessage()) { if (isEditingMessage()) {
const auto key = draftKey(DraftType::Normal); const auto key = draftKey(DraftType::Normal);
Assert(key.topicRootId() == id.topicRootId); Assert(key.topicRootId() == id.topicRootId);
Assert(key.monoforumPeerId() == id.monoforumPeerId);
if (const auto localDraft = _history->draft(key)) { if (const auto localDraft = _history->draft(key)) {
localDraft->reply = id; localDraft->reply = id;
} else { } else {
@ -3088,12 +3104,11 @@ void ComposeControls::cancelReplyMessage() {
} }
void ComposeControls::updateForwarding() { void ComposeControls::updateForwarding() {
const auto rootId = _topicRootId; const auto thread = (_history && (_topicRootId || _monoforumPeerId))
const auto thread = (_history && rootId) ? _history->threadFor(_topicRootId, _monoforumPeerId)
? _history->peer->forumTopicFor(rootId)
: (Data::Thread*)_history; : (Data::Thread*)_history;
_header->updateForwarding(thread, thread _header->updateForwarding(thread, thread
? _history->resolveForwardDraft(rootId) ? _history->resolveForwardDraft(_topicRootId, _monoforumPeerId)
: Data::ResolvedForwardDraft()); : Data::ResolvedForwardDraft());
updateSendButtonType(); updateSendButtonType();
} }
@ -3108,7 +3123,7 @@ bool ComposeControls::handleCancelRequest() {
} else if (isEditingMessage()) { } else if (isEditingMessage()) {
maybeCancelEditMessage(); maybeCancelEditMessage();
return true; return true;
} else if (replyingToMessage()) { } else if (replyingToMessage().replying()) {
cancelReplyMessage(); cancelReplyMessage();
return true; return true;
} else if (readyToForward()) { } else if (readyToForward()) {
@ -3186,6 +3201,11 @@ void ComposeControls::initForwardProcess() {
&& topic->rootId() == _topicRootId) { && topic->rootId() == _topicRootId) {
updateForwarding(); updateForwarding();
} }
} else if (const auto sublist = update.entry->asSublist()) {
if (sublist->owningHistory() == _history
&& sublist->sublistPeer()->id == _monoforumPeerId) {
updateForwarding();
}
} }
}, _wrap->lifetime()); }, _wrap->lifetime());
@ -3209,6 +3229,7 @@ bool ComposeControls::isEditingMessage() const {
FullReplyTo ComposeControls::replyingToMessage() const { FullReplyTo ComposeControls::replyingToMessage() const {
auto result = _header->replyingToMessage(); auto result = _header->replyingToMessage();
result.topicRootId = _topicRootId; result.topicRootId = _topicRootId;
result.monoforumPeerId = _monoforumPeerId;
return result; return result;
} }

View file

@ -365,6 +365,7 @@ private:
History *_history = nullptr; History *_history = nullptr;
MsgId _topicRootId = 0; MsgId _topicRootId = 0;
PeerId _monoforumPeerId = 0;
BusinessShortcutId _shortcutId = 0; BusinessShortcutId _shortcutId = 0;
Fn<bool()> _showSlowmodeError; Fn<bool()> _showSlowmodeError;
Fn<Api::SendAction()> _sendActionFactory; Fn<Api::SendAction()> _sendActionFactory;

View file

@ -1375,18 +1375,20 @@ void ShowReplyToChatBox(
auto chosen = [=](not_null<Data::Thread*> thread) mutable { auto chosen = [=](not_null<Data::Thread*> thread) mutable {
const auto history = thread->owningHistory(); const auto history = thread->owningHistory();
const auto topicRootId = thread->topicRootId(); 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 const auto textWithTags = draft
? draft->textWithTags ? draft->textWithTags
: TextWithTags(); : TextWithTags();
const auto cursor = draft ? draft->cursor : MessageCursor(); const auto cursor = draft ? draft->cursor : MessageCursor();
reply.topicRootId = topicRootId; reply.topicRootId = topicRootId;
reply.monoforumPeerId = monoforumPeerId;
history->setLocalDraft(std::make_unique<Data::Draft>( history->setLocalDraft(std::make_unique<Data::Draft>(
textWithTags, textWithTags,
reply, reply,
cursor, cursor,
Data::WebPageDraft())); Data::WebPageDraft()));
history->clearLocalEditDraft(topicRootId); history->clearLocalEditDraft(topicRootId, monoforumPeerId);
history->session().changes().entryUpdated( history->session().changes().entryUpdated(
thread, thread,
Data::EntryUpdate::Flag::LocalDraftSet); Data::EntryUpdate::Flag::LocalDraftSet);

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_helpers.h" #include "history/history_item_helpers.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/view/history_view_item_preview.h" #include "history/view/history_view_item_preview.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
@ -74,6 +75,11 @@ void ForwardPanel::update(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
update(nullptr, {}); update(nullptr, {});
}, _dataLifetime); }, _dataLifetime);
} else if (const auto sublist = _to->asSublist()) {
sublist->destroyed(
) | rpl::start_with_next([=] {
update(nullptr, {});
}, _dataLifetime);
} }
updateTexts(); updateTexts();
@ -231,8 +237,10 @@ void ForwardPanel::applyOptions(Data::ForwardOptions options) {
if (_data.items.empty()) { if (_data.items.empty()) {
return; return;
} else if (_data.options != options) { } else if (_data.options != options) {
const auto topicRootId = _to->topicRootId();
const auto monoforumPeerId = _to->monoforumPeerId();
_data.options = options; _data.options = options;
_to->owningHistory()->setForwardDraft(_to->topicRootId(), { _to->owningHistory()->setForwardDraft(topicRootId, monoforumPeerId, {
.ids = _to->owner().itemsToIds(_data.items), .ids = _to->owner().itemsToIds(_data.items),
.options = options, .options = options,
}); });
@ -256,7 +264,9 @@ void ForwardPanel::editToNextOption() {
? Options::NoNamesAndCaptions ? Options::NoNamesAndCaptions
: Options::PreserveInfo; : 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), .ids = _to->owner().itemsToIds(_data.items),
.options = next, .options = next,
}); });
@ -332,20 +342,25 @@ void ForwardPanel::paint(
void ClearDraftReplyTo( void ClearDraftReplyTo(
not_null<History*> history, not_null<History*> history,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
FullMsgId equalTo) { FullMsgId equalTo) {
const auto local = history->localDraft(topicRootId); const auto local = history->localDraft(topicRootId, monoforumPeerId);
if (!local || (equalTo && local->reply.messageId != equalTo)) { if (!local || (equalTo && local->reply.messageId != equalTo)) {
return; return;
} }
auto draft = *local; auto draft = *local;
draft.reply = { .topicRootId = topicRootId }; draft.reply = {
.topicRootId = topicRootId,
.monoforumPeerId = monoforumPeerId,
};
if (Data::DraftIsNull(&draft)) { if (Data::DraftIsNull(&draft)) {
history->clearLocalDraft(topicRootId); history->clearLocalDraft(topicRootId, monoforumPeerId);
} else { } else {
history->setLocalDraft( history->setLocalDraft(
std::make_unique<Data::Draft>(std::move(draft))); std::make_unique<Data::Draft>(std::move(draft)));
} }
if (const auto thread = history->threadFor(topicRootId)) { const auto thread = history->threadFor(topicRootId, monoforumPeerId);
if (thread) {
history->session().api().saveDraftToCloudDelayed(thread); history->session().api().saveDraftToCloudDelayed(thread);
} }
} }

View file

@ -76,6 +76,7 @@ private:
void ClearDraftReplyTo( void ClearDraftReplyTo(
not_null<History*> history, not_null<History*> history,
MsgId topicRootId, MsgId topicRootId,
PeerId monoforumPeerId,
FullMsgId equalTo); FullMsgId equalTo);
void EditWebPageOptions( void EditWebPageOptions(

View file

@ -438,8 +438,10 @@ ChatWidget::ChatWidget(
ChatWidget::~ChatWidget() { ChatWidget::~ChatWidget() {
base::take(_sendAction); base::take(_sendAction);
if (_repliesRootId) { if (_repliesRootId || _sublist) {
session().api().saveCurrentDraftToCloud(); session().api().saveCurrentDraftToCloud();
}
if (_repliesRootId) {
controller()->sendingAnimation().clear(); controller()->sendingAnimation().clear();
} }
if (_topic) { if (_topic) {
@ -747,7 +749,8 @@ void ChatWidget::setupComposeControls() {
_composeControls->setHistory({ _composeControls->setHistory({
.history = _history.get(), .history = _history.get(),
.topicRootId = _topic ? _topic->rootId() : MsgId(0), .topicRootId = _topic ? _topic->rootId() : MsgId(),
.monoforumPeerId = _sublist ? _sublist->sublistPeer()->id : PeerId(),
.showSlowmodeError = [=] { return showSlowmodeError(); }, .showSlowmodeError = [=] { return showSlowmodeError(); },
.sendActionFactory = [=] { return prepareSendAction({}); }, .sendActionFactory = [=] { return prepareSendAction({}); },
.slowmodeSecondsLeft = SlowmodeSecondsLeft(_peer), .slowmodeSecondsLeft = SlowmodeSecondsLeft(_peer),

View file

@ -557,6 +557,7 @@ bool MainWidget::setForwardDraft(
const auto history = thread->owningHistory(); const auto history = thread->owningHistory();
const auto items = session().data().idsToItems(draft.ids); const auto items = session().data().idsToItems(draft.ids);
const auto topicRootId = thread->topicRootId(); const auto topicRootId = thread->topicRootId();
const auto monoforumPeerId = thread->monoforumPeerId();
const auto error = GetErrorForSending( const auto error = GetErrorForSending(
history->peer, history->peer,
{ {
@ -569,7 +570,7 @@ bool MainWidget::setForwardDraft(
return false; return false;
} }
history->setForwardDraft(topicRootId, std::move(draft)); history->setForwardDraft(topicRootId, monoforumPeerId, std::move(draft));
_controller->showThread( _controller->showThread(
thread, thread,
ShowAtUnreadMsgId, ShowAtUnreadMsgId,
@ -596,12 +597,16 @@ bool MainWidget::shareUrl(
}; };
const auto history = thread->owningHistory(); const auto history = thread->owningHistory();
const auto topicRootId = thread->topicRootId(); const auto topicRootId = thread->topicRootId();
const auto monoforumPeerId = thread->monoforumPeerId();
history->setLocalDraft(std::make_unique<Data::Draft>( history->setLocalDraft(std::make_unique<Data::Draft>(
textWithTags, textWithTags,
FullReplyTo{ .topicRootId = topicRootId }, FullReplyTo{
.topicRootId = topicRootId,
.monoforumPeerId = monoforumPeerId,
},
cursor, cursor,
Data::WebPageDraft())); Data::WebPageDraft()));
history->clearLocalEditDraft(topicRootId); history->clearLocalEditDraft(topicRootId, monoforumPeerId);
history->session().changes().entryUpdated( history->session().changes().entryUpdated(
thread, thread,
Data::EntryUpdate::Flag::LocalDraftSet); Data::EntryUpdate::Flag::LocalDraftSet);
@ -2044,6 +2049,8 @@ bool MainWidget::showBackFromStack(const SectionShow &params) {
}); });
return (_dialogs != nullptr); return (_dialogs != nullptr);
} }
session().api().saveCurrentDraftToCloud();
auto item = std::move(_stack.back()); auto item = std::move(_stack.back());
_stack.pop_back(); _stack.pop_back();
if (const auto currentHistoryPeer = _history->peer()) { if (const auto currentHistoryPeer = _history->peer()) {

View file

@ -1176,7 +1176,9 @@ void EnumerateDrafts(
} else if (key.isLocal() } else if (key.isLocal()
&& (!supportMode || key.topicRootId())) { && (!supportMode || key.topicRootId())) {
const auto i = map.find( 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; const auto cloud = (i != end(map)) ? i->second.get() : nullptr;
if (Data::DraftsAreEqual(draft.get(), cloud)) { if (Data::DraftsAreEqual(draft.get(), cloud)) {
continue; continue;
@ -1426,7 +1428,7 @@ void Account::readDraftCursors(PeerId peerId, Data::HistoryDrafts &map) {
? Data::DraftKey::FromSerialized(keyValue) ? Data::DraftKey::FromSerialized(keyValue)
: keysOld : keysOld
? Data::DraftKey::FromSerializedOld(keyValueOld) ? Data::DraftKey::FromSerializedOld(keyValueOld)
: Data::DraftKey::Local(0); : Data::DraftKey::Local(MsgId(), PeerId());
qint32 position = 0, anchor = 0, scroll = Ui::kQFixedMax; qint32 position = 0, anchor = 0, scroll = Ui::kQFixedMax;
draft.stream >> position >> anchor >> scroll; draft.stream >> position >> anchor >> scroll;
if (const auto i = map.find(key); i != end(map)) { if (const auto i = map.find(key); i != end(map)) {
@ -1453,13 +1455,14 @@ void Account::readDraftCursorsLegacy(
return; 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( i->second->cursor = MessageCursor(
localPosition, localPosition,
localAnchor, localAnchor,
localScroll); 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 != end(map)) {
i->second->cursor = MessageCursor( i->second->cursor = MessageCursor(
editPosition, editPosition,
@ -1472,7 +1475,7 @@ void Account::readDraftsWithCursors(not_null<History*> history) {
const auto guard = gsl::finally([&] { const auto guard = gsl::finally([&] {
if (const auto migrated = history->migrateFrom()) { if (const auto migrated = history->migrateFrom()) {
readDraftsWithCursors(migrated); readDraftsWithCursors(migrated);
migrated->clearLocalEditDraft({}); migrated->clearLocalEditDraft(MsgId(), PeerId());
history->takeLocalDraft(migrated); history->takeLocalDraft(migrated);
} }
}); });
@ -1643,10 +1646,11 @@ void Account::readDraftsWithCursorsLegacy(
editData.text.size()); editData.text.size());
const auto topicRootId = MsgId(); const auto topicRootId = MsgId();
const auto monoforumPeerId = PeerId();
auto map = base::flat_map<Data::DraftKey, std::unique_ptr<Data::Draft>>(); auto map = base::flat_map<Data::DraftKey, std::unique_ptr<Data::Draft>>();
if (!msgData.text.isEmpty() || msgReplyTo) { if (!msgData.text.isEmpty() || msgReplyTo) {
map.emplace( map.emplace(
Data::DraftKey::Local(topicRootId), Data::DraftKey::Local(topicRootId, monoforumPeerId),
std::make_unique<Data::Draft>( std::make_unique<Data::Draft>(
msgData, msgData,
FullReplyTo{ FullMsgId(peerId, MsgId(msgReplyTo)) }, FullReplyTo{ FullMsgId(peerId, MsgId(msgReplyTo)) },
@ -1657,7 +1661,7 @@ void Account::readDraftsWithCursorsLegacy(
} }
if (editMsgId) { if (editMsgId) {
map.emplace( map.emplace(
Data::DraftKey::LocalEdit(topicRootId), Data::DraftKey::LocalEdit(topicRootId, monoforumPeerId),
std::make_unique<Data::Draft>( std::make_unique<Data::Draft>(
editData, editData,
FullReplyTo{ FullMsgId(peerId, editMsgId) }, FullReplyTo{ FullMsgId(peerId, editMsgId) },

View file

@ -54,6 +54,7 @@ constexpr auto kOccupyFor = TimeId(60);
constexpr auto kReoccupyEach = 30 * crl::time(1000); constexpr auto kReoccupyEach = 30 * crl::time(1000);
constexpr auto kMaxSupportInfoLength = MaxMessageSize * 4; constexpr auto kMaxSupportInfoLength = MaxMessageSize * 4;
constexpr auto kTopicRootId = MsgId(0); constexpr auto kTopicRootId = MsgId(0);
constexpr auto kMonoforumPeerId = PeerId(0);
class EditInfoBox : public Ui::BoxContent { class EditInfoBox : public Ui::BoxContent {
public: public:
@ -183,7 +184,7 @@ uint32 ParseOccupationTag(History *history) {
if (!TrackHistoryOccupation(history)) { if (!TrackHistoryOccupation(history)) {
return 0; return 0;
} }
const auto draft = history->cloudDraft(kTopicRootId); const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId);
if (!draft) { if (!draft) {
return 0; return 0;
} }
@ -209,7 +210,7 @@ QString ParseOccupationName(History *history) {
if (!TrackHistoryOccupation(history)) { if (!TrackHistoryOccupation(history)) {
return QString(); return QString();
} }
const auto draft = history->cloudDraft(kTopicRootId); const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId);
if (!draft) { if (!draft) {
return QString(); return QString();
} }
@ -235,7 +236,7 @@ TimeId OccupiedBySomeoneTill(History *history) {
if (!TrackHistoryOccupation(history)) { if (!TrackHistoryOccupation(history)) {
return 0; return 0;
} }
const auto draft = history->cloudDraft(kTopicRootId); const auto draft = history->cloudDraft(kTopicRootId, kMonoforumPeerId);
if (!draft) { if (!draft) {
return 0; return 0;
} }
@ -353,7 +354,7 @@ void Helper::updateOccupiedHistory(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
History *history) { History *history) {
if (isOccupiedByMe(_occupiedHistory)) { if (isOccupiedByMe(_occupiedHistory)) {
_occupiedHistory->clearCloudDraft(kTopicRootId); _occupiedHistory->clearCloudDraft(kTopicRootId, kMonoforumPeerId);
_session->api().saveDraftToCloudDelayed(_occupiedHistory); _session->api().saveDraftToCloudDelayed(_occupiedHistory);
} }
_occupiedHistory = history; _occupiedHistory = history;
@ -377,7 +378,10 @@ void Helper::occupyInDraft() {
&& !isOccupiedBySomeone(_occupiedHistory) && !isOccupiedBySomeone(_occupiedHistory)
&& !_supportName.isEmpty()) { && !_supportName.isEmpty()) {
const auto draft = OccupiedDraft(_supportNameNormalized); const auto draft = OccupiedDraft(_supportNameNormalized);
_occupiedHistory->createCloudDraft(kTopicRootId, &draft); _occupiedHistory->createCloudDraft(
kTopicRootId,
kMonoforumPeerId,
&draft);
_session->api().saveDraftToCloudDelayed(_occupiedHistory); _session->api().saveDraftToCloudDelayed(_occupiedHistory);
_reoccupyTimer.callEach(kReoccupyEach); _reoccupyTimer.callEach(kReoccupyEach);
} }
@ -386,7 +390,10 @@ void Helper::occupyInDraft() {
void Helper::reoccupy() { void Helper::reoccupy() {
if (isOccupiedByMe(_occupiedHistory)) { if (isOccupiedByMe(_occupiedHistory)) {
const auto draft = OccupiedDraft(_supportNameNormalized); const auto draft = OccupiedDraft(_supportNameNormalized);
_occupiedHistory->createCloudDraft(kTopicRootId, &draft); _occupiedHistory->createCloudDraft(
kTopicRootId,
kMonoforumPeerId,
&draft);
_session->api().saveDraftToCloudDelayed(_occupiedHistory); _session->api().saveDraftToCloudDelayed(_occupiedHistory);
} }
} }

View file

@ -1802,8 +1802,10 @@ void PeerMenuCreatePoll(
peer->owner().history(peer), peer->owner().history(peer),
result.options); result.options);
action.replyTo = replyTo; action.replyTo = replyTo;
const auto topicRootId = replyTo.topicRootId; const auto local = action.history->localDraft(
if (const auto local = action.history->localDraft(topicRootId)) { replyTo.topicRootId,
replyTo.monoforumPeerId);
if (local) {
action.clearDraft = local->textWithTags.text.isEmpty(); action.clearDraft = local->textWithTags.text.isEmpty();
} else { } else {
action.clearDraft = false; action.clearDraft = false;

View file

@ -2150,8 +2150,9 @@ bool SessionController::switchInlineQuery(
params); params);
} else { } else {
const auto topicRootId = to.currentReplyTo.topicRootId; const auto topicRootId = to.currentReplyTo.topicRootId;
const auto monoforumPeerId = to.currentReplyTo.monoforumPeerId;
history->setLocalDraft(std::move(draft)); history->setLocalDraft(std::move(draft));
history->clearLocalEditDraft(topicRootId); history->clearLocalEditDraft(topicRootId, monoforumPeerId);
if (to.section == Section::Replies) { if (to.section == Section::Replies) {
const auto commentId = MsgId(); const auto commentId = MsgId();
showRepliesForMessage(history, topicRootId, commentId, params); showRepliesForMessage(history, topicRootId, commentId, params);