mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Support topic on-the-fly creation.
This commit is contained in:
parent
065d2e2ac9
commit
3722e55b67
32 changed files with 447 additions and 130 deletions
|
@ -71,10 +71,10 @@ void Polls::create(
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
PollDataToInputMedia(&data),
|
||||
MTP_string(),
|
||||
MTP_long(randomId),
|
||||
|
|
|
@ -148,10 +148,10 @@ void SendExistingMedia(
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
inputMedia(),
|
||||
MTP_string(captionText),
|
||||
MTP_long(randomId),
|
||||
|
@ -314,10 +314,10 @@ bool SendDice(MessageToSend &message) {
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
MTP_inputMediaDice(MTP_string(emoji)),
|
||||
MTP_string(),
|
||||
MTP_long(randomId),
|
||||
|
@ -347,9 +347,9 @@ void SendConfirmedFile(
|
|||
&& (file->to.replaceMediaOf != 0);
|
||||
const auto newId = FullMsgId(
|
||||
file->to.peer,
|
||||
isEditing
|
||||
(isEditing
|
||||
? file->to.replaceMediaOf
|
||||
: session->data().nextLocalMessageId());
|
||||
: session->data().nextLocalMessageId()));
|
||||
const auto groupId = file->album ? file->album->groupId : uint64(0);
|
||||
if (file->album) {
|
||||
const auto proj = [](const SendingAlbum::Item &item) {
|
||||
|
@ -360,15 +360,21 @@ void SendConfirmedFile(
|
|||
|
||||
it->msgId = newId;
|
||||
}
|
||||
session->uploader().upload(newId, file);
|
||||
|
||||
const auto itemToEdit = isEditing
|
||||
? session->data().message(newId)
|
||||
: nullptr;
|
||||
|
||||
const auto history = session->data().history(file->to.peer);
|
||||
const auto peer = history->peer;
|
||||
|
||||
if (!isEditing) {
|
||||
file->to.replyTo = session->data().histories().convertTopicReplyTo(
|
||||
history,
|
||||
file->to.replyTo);
|
||||
}
|
||||
|
||||
session->uploader().upload(newId, file);
|
||||
|
||||
auto action = SendAction(history, file->to.options);
|
||||
action.clearDraft = false;
|
||||
action.replyTo = file->to.replyTo;
|
||||
|
|
|
@ -1534,7 +1534,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
const auto randomId = d.vrandom_id().v;
|
||||
if (const auto id = session().data().messageIdByRandomId(randomId)) {
|
||||
const auto newId = d.vid().v;
|
||||
if (const auto local = session().data().message(id)) {
|
||||
auto &owner = session().data();
|
||||
if (const auto local = owner.message(id)) {
|
||||
if (local->isScheduled()) {
|
||||
session().data().scheduledMessages().apply(d, local);
|
||||
} else {
|
||||
|
@ -1552,6 +1553,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
local->setRealId(d.vid().v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
owner.histories().checkTopicCreated(id, newId);
|
||||
}
|
||||
session().data().unregisterMessageRandomId(randomId);
|
||||
}
|
||||
|
|
|
@ -3494,10 +3494,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMessage(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMessage>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
msgText,
|
||||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
|
@ -3637,10 +3637,10 @@ void ApiWrap::sendInlineResult(
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendInlineBotResult(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendInlineBotResult>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
MTP_long(randomId),
|
||||
MTP_long(data->getQueryId()),
|
||||
MTP_string(data->getId()),
|
||||
|
@ -3784,10 +3784,10 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(flags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
media,
|
||||
MTP_string(caption.text),
|
||||
MTP_long(randomId),
|
||||
|
@ -3889,10 +3889,10 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
|
|||
history,
|
||||
replyTo,
|
||||
uint64(0), // randomId
|
||||
MTPmessages_SendMultiMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMultiMedia>(
|
||||
MTP_flags(flags),
|
||||
peer->input,
|
||||
MTP_int(replyTo),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
MTP_vector<MTPInputSingleMedia>(medias),
|
||||
MTP_int(album->options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
|
|
|
@ -69,10 +69,10 @@ void ShareBotGame(
|
|||
history,
|
||||
replyTo,
|
||||
randomId,
|
||||
MTPmessages_SendMedia(
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(0),
|
||||
chat->input,
|
||||
MTP_int(0),
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
MTP_inputMediaGame(
|
||||
MTP_inputGameShortName(
|
||||
bot->inputUser,
|
||||
|
|
|
@ -139,7 +139,8 @@ void EditForumTopicBox(
|
|||
|
||||
const auto requestId = std::make_shared<mtpRequestId>();
|
||||
const auto create = [=] {
|
||||
if (!forum->peer->isForum()) {
|
||||
const auto channel = forum->peer->asChannel();
|
||||
if (!channel || !channel->isForum()) {
|
||||
box->closeBox();
|
||||
return;
|
||||
} else if (title->getLastText().trimmed().isEmpty()) {
|
||||
|
@ -149,30 +150,10 @@ void EditForumTopicBox(
|
|||
controller->showSection(
|
||||
std::make_shared<HistoryView::RepliesMemento>(
|
||||
forum,
|
||||
forum->peer->forum()->reserveCreatingId(
|
||||
channel->forum()->reserveCreatingId(
|
||||
title->getLastText().trimmed(),
|
||||
state->iconId)),
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
#if 0 // #TODO forum create
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
const auto api = &forum->session().api();
|
||||
api->request(MTPchannels_CreateForumTopic(
|
||||
MTP_flags(0),
|
||||
forum->inputChannel,
|
||||
MTP_string(title->getLastText().trimmed()),
|
||||
MTPlong(), // icon_emoji_id
|
||||
MTPInputMedia(),
|
||||
MTP_string(message->getLastText().trimmed()),
|
||||
MTP_long(randomId),
|
||||
MTPVector<MTPMessageEntity>(),
|
||||
MTPInputPeer() // send_as
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
api->applyUpdates(result, randomId);
|
||||
box->closeBox();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
api->sendMessageFail(error, forum, randomId);
|
||||
}).send();
|
||||
#endif
|
||||
};
|
||||
|
||||
const auto save = [=] {
|
||||
|
|
|
@ -124,20 +124,18 @@ void Forum::applyTopicAdded(
|
|||
MsgId rootId,
|
||||
const QString &title,
|
||||
DocumentId iconId) {
|
||||
if (const auto i = _topics.find(rootId); i != end(_topics)) {
|
||||
i->second->applyTitle(title);
|
||||
i->second->applyIconId(iconId);
|
||||
} else {
|
||||
const auto raw = _topics.emplace(
|
||||
const auto i = _topics.find(rootId);
|
||||
const auto raw = (i != end(_topics))
|
||||
? i->second.get()
|
||||
: _topics.emplace(
|
||||
rootId,
|
||||
std::make_unique<ForumTopic>(_history, rootId)
|
||||
).first->second.get();
|
||||
raw->applyTitle(title);
|
||||
raw->applyIconId(iconId);
|
||||
if (!creating(rootId)) {
|
||||
raw->addToChatList(FilterId(), topicsList());
|
||||
_chatsListChanges.fire({});
|
||||
}
|
||||
raw->applyTitle(title);
|
||||
raw->applyIconId(iconId);
|
||||
if (!creating(rootId)) {
|
||||
raw->addToChatList(FilterId(), topicsList());
|
||||
_chatsListChanges.fire({});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,6 +169,25 @@ bool Forum::creating(MsgId rootId) const {
|
|||
return _creatingRootIds.contains(rootId);
|
||||
}
|
||||
|
||||
void Forum::created(MsgId rootId, MsgId realId) {
|
||||
if (rootId == realId) {
|
||||
return;
|
||||
}
|
||||
_creatingRootIds.remove(rootId);
|
||||
const auto i = _topics.find(rootId);
|
||||
Assert(i != end(_topics));
|
||||
auto topic = std::move(i->second);
|
||||
_topics.erase(i);
|
||||
const auto id = FullMsgId(_history->peer->id, realId);
|
||||
if (!_topics.contains(realId)) {
|
||||
_topics.emplace(
|
||||
realId,
|
||||
std::move(topic)
|
||||
).first->second->setRealRootId(realId);
|
||||
}
|
||||
_history->owner().notifyItemIdChange({ id, rootId });
|
||||
}
|
||||
|
||||
ForumTopic *Forum::topicFor(not_null<HistoryItem*> item) {
|
||||
const auto maybe = topicFor(item->replyToTop());
|
||||
return maybe ? maybe : topicFor(item->topicRootId());
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
const QString &title,
|
||||
DocumentId iconId);
|
||||
void applyTopicRemoved(MsgId rootId);
|
||||
void applyTopicCreated(MsgId rootId, MsgId realId);
|
||||
[[nodiscard]] ForumTopic *topicFor(not_null<HistoryItem*> item);
|
||||
[[nodiscard]] ForumTopic *topicFor(MsgId rootId);
|
||||
|
||||
|
@ -46,6 +47,7 @@ public:
|
|||
DocumentId iconId);
|
||||
void discardCreatingId(MsgId rootId);
|
||||
[[nodiscard]] bool creating(MsgId rootId) const;
|
||||
void created(MsgId rootId, MsgId realId);
|
||||
|
||||
private:
|
||||
void applyReceivedTopics(
|
||||
|
|
|
@ -29,6 +29,8 @@ ForumTopic::ForumTopic(not_null<History*> history, MsgId rootId)
|
|||
, _rootId(rootId) {
|
||||
}
|
||||
|
||||
ForumTopic::~ForumTopic() = default;
|
||||
|
||||
not_null<ChannelData*> ForumTopic::channel() const {
|
||||
return _history->peer->asChannel();
|
||||
}
|
||||
|
@ -45,6 +47,10 @@ MsgId ForumTopic::rootId() const {
|
|||
return _rootId;
|
||||
}
|
||||
|
||||
void ForumTopic::setRealRootId(MsgId realId) {
|
||||
_rootId = realId;
|
||||
}
|
||||
|
||||
void ForumTopic::applyTopic(const MTPForumTopic &topic) {
|
||||
Expects(_rootId == topic.data().vid().v);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
static constexpr auto kGeneralId = 1;
|
||||
|
||||
ForumTopic(not_null<History*> history, MsgId rootId);
|
||||
~ForumTopic();
|
||||
|
||||
ForumTopic(const ForumTopic &) = delete;
|
||||
ForumTopic &operator=(const ForumTopic &) = delete;
|
||||
|
@ -42,6 +43,8 @@ public:
|
|||
return (_rootId == kGeneralId);
|
||||
}
|
||||
|
||||
void setRealRootId(MsgId realId);
|
||||
|
||||
void applyTopic(const MTPForumTopic &topic);
|
||||
|
||||
TimeId adjustedChatListTimeId() const override;
|
||||
|
@ -109,7 +112,7 @@ private:
|
|||
|
||||
const not_null<History*> _history;
|
||||
const not_null<Dialogs::MainList*> _list;
|
||||
const MsgId _rootId = 0;
|
||||
MsgId _rootId = 0;
|
||||
|
||||
QString _title;
|
||||
DocumentId _iconId = 0;
|
||||
|
|
|
@ -11,8 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/random.h"
|
||||
#include "main/main_session.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "history/history.h"
|
||||
|
@ -841,14 +844,74 @@ int Histories::sendRequest(
|
|||
return id;
|
||||
}
|
||||
|
||||
void Histories::sendCreateTopicRequest(
|
||||
not_null<History*> history,
|
||||
MsgId rootId) {
|
||||
Expects(history->peer->isChannel());
|
||||
|
||||
const auto forum = history->peer->forum();
|
||||
Assert(forum != nullptr);
|
||||
const auto topic = forum->topicFor(rootId);
|
||||
Assert(topic != nullptr);
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
session().data().registerMessageRandomId(
|
||||
randomId,
|
||||
{ history->peer->id, rootId });
|
||||
const auto api = &session().api();
|
||||
using Flag = MTPchannels_CreateForumTopic::Flag;
|
||||
api->request(MTPchannels_CreateForumTopic(
|
||||
MTP_flags(topic->iconId() ? Flag::f_icon_emoji_id : Flag(0)),
|
||||
history->peer->asChannel()->inputChannel,
|
||||
MTP_string(topic->title()),
|
||||
MTP_long(topic->iconId()),
|
||||
MTP_long(randomId),
|
||||
MTPInputPeer() // send_as
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
//AssertIsDebug();
|
||||
//const auto id = result.c_updates().vupdates().v.front().c_updateMessageID().vrandom_id().v;
|
||||
//session().data().registerMessageRandomId(
|
||||
// id,
|
||||
// { history->peer->id, rootId });
|
||||
api->applyUpdates(result, randomId);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
api->sendMessageFail(error, history->peer, randomId);
|
||||
}).send();
|
||||
}
|
||||
|
||||
bool Histories::isCreatingTopic(
|
||||
not_null<History*> history,
|
||||
MsgId rootId) const {
|
||||
const auto forum = history->peer->forum();
|
||||
return forum && forum->creating(rootId);
|
||||
}
|
||||
|
||||
int Histories::sendPreparedMessage(
|
||||
not_null<History*> history,
|
||||
MsgId replyTo,
|
||||
uint64 randomId,
|
||||
PreparedMessage message,
|
||||
Fn<PreparedMessage(MsgId replyTo)> message,
|
||||
Fn<void(const MTPUpdates&, const MTP::Response&)> done,
|
||||
Fn<void(const MTP::Error&, const MTP::Response&)> fail) {
|
||||
return v::match(message, [&](const auto &request) {
|
||||
if (isCreatingTopic(history, replyTo)) {
|
||||
const auto id = ++_requestAutoincrement;
|
||||
const auto creatingId = FullMsgId(history->peer->id, replyTo);
|
||||
auto i = _creatingTopics.find(creatingId);
|
||||
if (i == end(_creatingTopics)) {
|
||||
sendCreateTopicRequest(history, replyTo);
|
||||
i = _creatingTopics.emplace(creatingId).first;
|
||||
}
|
||||
i->second.push_back({
|
||||
.randomId = randomId,
|
||||
.message = std::move(message),
|
||||
.done = std::move(done),
|
||||
.fail = std::move(fail),
|
||||
.requestId = id,
|
||||
});
|
||||
_creatingTopicRequests.emplace(id);
|
||||
return id;
|
||||
}
|
||||
const auto realTo = convertTopicReplyTo(history, replyTo);
|
||||
return v::match(message(realTo), [&](const auto &request) {
|
||||
const auto type = RequestType::Send;
|
||||
return sendRequest(history, type, [=](Fn<void()> finish) {
|
||||
const auto session = &_owner->session();
|
||||
|
@ -874,6 +937,54 @@ int Histories::sendPreparedMessage(
|
|||
});
|
||||
}
|
||||
|
||||
void Histories::checkTopicCreated(FullMsgId rootId, MsgId realId) {
|
||||
const auto i = _creatingTopics.find(rootId);
|
||||
if (i != end(_creatingTopics)) {
|
||||
auto scheduled = base::take(i->second);
|
||||
_creatingTopics.erase(i);
|
||||
|
||||
_createdTopicIds.emplace(rootId, realId);
|
||||
|
||||
if (const auto forum = _owner->peer(rootId.peer)->forum()) {
|
||||
forum->created(rootId.msg, realId);
|
||||
}
|
||||
|
||||
const auto history = _owner->history(rootId.peer);
|
||||
for (auto &entry : scheduled) {
|
||||
_creatingTopicRequests.erase(entry.requestId);
|
||||
//AssertIsDebug();
|
||||
sendPreparedMessage(
|
||||
history,
|
||||
realId,
|
||||
entry.randomId,
|
||||
std::move(entry.message),
|
||||
std::move(entry.done),
|
||||
std::move(entry.fail));
|
||||
}
|
||||
for (const auto &item : history->clientSideMessages()) {
|
||||
const auto replace = [&](MsgId nowId) {
|
||||
return (nowId == rootId.msg) ? realId : nowId;
|
||||
};
|
||||
if (item->replyToTop() == rootId.msg) {
|
||||
item->setReplyFields(
|
||||
replace(item->replyToId()),
|
||||
realId,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MsgId Histories::convertTopicReplyTo(
|
||||
not_null<History*> history,
|
||||
MsgId replyTo) const {
|
||||
if (!replyTo) {
|
||||
return {};
|
||||
}
|
||||
const auto i = _createdTopicIds.find({ history->peer->id, replyTo });
|
||||
return (i != end(_createdTopicIds)) ? i->second : replyTo;
|
||||
}
|
||||
|
||||
void Histories::checkPostponed(not_null<History*> history, int id) {
|
||||
if (const auto state = lookup(history)) {
|
||||
finishSentRequest(history, state, id);
|
||||
|
@ -883,6 +994,9 @@ void Histories::checkPostponed(not_null<History*> history, int id) {
|
|||
void Histories::cancelRequest(int id) {
|
||||
if (!id) {
|
||||
return;
|
||||
} else if (_creatingTopicRequests.contains(id)) {
|
||||
cancelDelayedByTopicRequest(id);
|
||||
return;
|
||||
}
|
||||
const auto history = _historyByRequest.take(id);
|
||||
if (!history) {
|
||||
|
@ -896,6 +1010,15 @@ void Histories::cancelRequest(int id) {
|
|||
finishSentRequest(*history, state, id);
|
||||
}
|
||||
|
||||
void Histories::cancelDelayedByTopicRequest(int id) {
|
||||
for (auto &[rootId, messages] : _creatingTopics) {
|
||||
messages.erase(
|
||||
ranges::remove(messages, id, &DelayedByTopicMessage::requestId),
|
||||
end(messages));
|
||||
}
|
||||
_creatingTopicRequests.remove(id);
|
||||
}
|
||||
|
||||
void Histories::finishSentRequest(
|
||||
not_null<History*> history,
|
||||
not_null<State*> state,
|
||||
|
|
|
@ -104,10 +104,25 @@ public:
|
|||
not_null<History*> history,
|
||||
MsgId replyTo,
|
||||
uint64 randomId,
|
||||
PreparedMessage message,
|
||||
Fn<void(const MTPUpdates&, const MTP::Response &)> done,
|
||||
Fn<PreparedMessage(MsgId replyTo)> message,
|
||||
Fn<void(const MTPUpdates&, const MTP::Response&)> done,
|
||||
Fn<void(const MTP::Error&, const MTP::Response&)> fail);
|
||||
|
||||
struct ReplyToPlaceholder {
|
||||
};
|
||||
template <typename RequestType, typename ...Args>
|
||||
static Fn<Histories::PreparedMessage(MsgId)> PrepareMessage(
|
||||
const Args &...args) {
|
||||
return [=](MsgId replyTo) {
|
||||
return RequestType(ReplaceReplyTo(args, replyTo)...);
|
||||
};
|
||||
}
|
||||
|
||||
void checkTopicCreated(FullMsgId rootId, MsgId realId);
|
||||
[[nodiscard]] MsgId convertTopicReplyTo(
|
||||
not_null<History*> history,
|
||||
MsgId replyTo) const;
|
||||
|
||||
private:
|
||||
struct PostponedHistoryRequest {
|
||||
Fn<mtpRequestId(Fn<void()> finish)> generator;
|
||||
|
@ -130,6 +145,22 @@ private:
|
|||
MsgId aroundId = 0;
|
||||
mtpRequestId requestId = 0;
|
||||
};
|
||||
struct DelayedByTopicMessage {
|
||||
uint64 randomId = 0;
|
||||
Fn<PreparedMessage(MsgId replyTo)> message;
|
||||
Fn<void(const MTPUpdates&, const MTP::Response&)> done;
|
||||
Fn<void(const MTP::Error&, const MTP::Response&)> fail;
|
||||
int requestId = 0;
|
||||
};
|
||||
|
||||
template <typename Arg>
|
||||
static auto ReplaceReplyTo(Arg arg, MsgId replyTo) {
|
||||
return arg;
|
||||
}
|
||||
template <>
|
||||
static auto ReplaceReplyTo(ReplyToPlaceholder, MsgId replyTo) {
|
||||
return MTP_int(replyTo);
|
||||
}
|
||||
|
||||
void readInboxTill(not_null<History*> history, MsgId tillId, bool force);
|
||||
void sendReadRequests();
|
||||
|
@ -147,6 +178,12 @@ private:
|
|||
|
||||
void sendDialogRequests();
|
||||
|
||||
[[nodiscard]] bool isCreatingTopic(
|
||||
not_null<History*> history,
|
||||
MsgId rootId) const;
|
||||
void sendCreateTopicRequest(not_null<History*> history, MsgId rootId);
|
||||
void cancelDelayedByTopicRequest(int id);
|
||||
|
||||
const not_null<Session*> _owner;
|
||||
|
||||
std::unordered_map<PeerId, std::unique_ptr<History>> _map;
|
||||
|
@ -169,6 +206,12 @@ private:
|
|||
not_null<History*>,
|
||||
ChatListGroupRequest> _chatListGroupRequests;
|
||||
|
||||
base::flat_map<
|
||||
FullMsgId,
|
||||
std::vector<DelayedByTopicMessage>> _creatingTopics;
|
||||
base::flat_map<FullMsgId, MsgId> _createdTopicIds;
|
||||
base::flat_set<mtpRequestId> _creatingTopicRequests;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -137,9 +137,6 @@ void RepliesList::appendClientSideMessages(MessagesSlice &slice) {
|
|||
}
|
||||
slice.ids.reserve(messages.size());
|
||||
for (const auto &item : messages) {
|
||||
const auto checkId = (_rootId == ForumTopic::kGeneralId)
|
||||
? item->topicRootId()
|
||||
: item->replyToTop();
|
||||
if (!item->inThread(_rootId)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1407,10 +1407,12 @@ rpl::producer<not_null<HistoryItem*>> Session::newItemAdded() const {
|
|||
return _newItemAdded.events();
|
||||
}
|
||||
|
||||
void Session::changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId) {
|
||||
HistoryItem *Session::changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId) {
|
||||
const auto list = messagesListForInsert(peerId);
|
||||
auto i = list->find(wasId);
|
||||
Assert(i != list->end());
|
||||
const auto i = list->find(wasId);
|
||||
if (i == list->end()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto item = i->second;
|
||||
list->erase(i);
|
||||
const auto [j, ok] = list->emplace(nowId, item);
|
||||
|
@ -1427,6 +1429,7 @@ void Session::changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId) {
|
|||
}
|
||||
|
||||
Ensures(ok);
|
||||
return item;
|
||||
}
|
||||
|
||||
bool Session::queryItemVisibility(not_null<HistoryItem*> item) const {
|
||||
|
@ -1448,19 +1451,23 @@ void Session::itemVisibilitiesUpdated() {
|
|||
}
|
||||
|
||||
void Session::notifyItemIdChange(IdChange event) {
|
||||
const auto item = event.item;
|
||||
changeMessageId(item->history()->peer->id, event.oldId, item->id);
|
||||
const auto item = changeMessageId(
|
||||
event.newId.peer,
|
||||
event.oldId,
|
||||
event.newId.msg);
|
||||
|
||||
_itemIdChanges.fire_copy(event);
|
||||
|
||||
const auto refreshViewDataId = [](not_null<ViewElement*> view) {
|
||||
view->refreshDataId();
|
||||
};
|
||||
enumerateItemViews(item, refreshViewDataId);
|
||||
if (const auto group = groups().find(item)) {
|
||||
const auto leader = group->items.front();
|
||||
if (leader != item) {
|
||||
enumerateItemViews(leader, refreshViewDataId);
|
||||
if (item) {
|
||||
const auto refreshViewDataId = [](not_null<ViewElement*> view) {
|
||||
view->refreshDataId();
|
||||
};
|
||||
enumerateItemViews(item, refreshViewDataId);
|
||||
if (const auto group = groups().find(item)) {
|
||||
const auto leader = group->items.front();
|
||||
if (leader != item) {
|
||||
enumerateItemViews(leader, refreshViewDataId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ public:
|
|||
void itemVisibilitiesUpdated();
|
||||
|
||||
struct IdChange {
|
||||
not_null<HistoryItem*> item;
|
||||
FullMsgId newId;
|
||||
MsgId oldId = 0;
|
||||
};
|
||||
void notifyItemIdChange(IdChange event);
|
||||
|
@ -728,7 +728,7 @@ private:
|
|||
not_null<Messages*> messagesListForInsert(PeerId peerId);
|
||||
not_null<HistoryItem*> registerMessage(
|
||||
std::unique_ptr<HistoryItem> item);
|
||||
void changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId);
|
||||
HistoryItem *changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId);
|
||||
void removeDependencyMessage(not_null<HistoryItem*> item);
|
||||
|
||||
void photoApplyFields(
|
||||
|
|
|
@ -660,9 +660,11 @@ void HistoryItem::applySentMessage(const MTPDmessage &data) {
|
|||
setForwardsCount(data.vforwards().value_or(-1));
|
||||
if (const auto reply = data.vreply_to()) {
|
||||
reply->match([&](const MTPDmessageReplyHeader &data) {
|
||||
setReplyToTop(
|
||||
setReplyFields(
|
||||
data.vreply_to_msg_id().v,
|
||||
data.vreply_to_top_id().value_or(
|
||||
data.vreply_to_msg_id().v));
|
||||
data.vreply_to_msg_id().v),
|
||||
data.is_forum_topic());
|
||||
});
|
||||
}
|
||||
setPostAuthor(data.vpost_author().value_or_empty());
|
||||
|
@ -715,7 +717,7 @@ void HistoryItem::setRealId(MsgId newId) {
|
|||
if (isRegular()) {
|
||||
_history->unregisterClientSideMessage(this);
|
||||
}
|
||||
_history->owner().notifyItemIdChange({ this, oldId });
|
||||
_history->owner().notifyItemIdChange({ fullId(), oldId });
|
||||
|
||||
// We don't fire MessageUpdate::Flag::ReplyMarkup and update keyboard
|
||||
// in history widget, because it can't exist for an outgoing message.
|
||||
|
|
|
@ -341,7 +341,10 @@ public:
|
|||
PeerId replier,
|
||||
std::optional<bool> unread) {
|
||||
}
|
||||
virtual void setReplyToTop(MsgId replyToTop) = 0;
|
||||
virtual void setReplyFields(
|
||||
MsgId replyTo,
|
||||
MsgId replyToTop,
|
||||
bool isForumPost) = 0;
|
||||
virtual void setPostAuthor(const QString &author) {
|
||||
}
|
||||
virtual void setRealId(MsgId newId);
|
||||
|
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_media_types.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "data/data_sponsored_messages.h"
|
||||
|
@ -173,6 +174,9 @@ void RequestDependentMessageData(
|
|||
not_null<HistoryItem*> item,
|
||||
PeerId peerId,
|
||||
MsgId msgId) {
|
||||
if (!IsServerMsgId(msgId)) {
|
||||
return;
|
||||
}
|
||||
const auto fullId = item->fullId();
|
||||
const auto history = item->history();
|
||||
const auto session = &history->session();
|
||||
|
@ -332,6 +336,7 @@ HistoryMessage::HistoryMessage(
|
|||
: id;
|
||||
config.replyToTop = data.vreply_to_top_id().value_or(
|
||||
data.vreply_to_msg_id().v);
|
||||
config.replyIsTopicPost = data.is_forum_topic();
|
||||
});
|
||||
}
|
||||
config.viaBotId = data.vvia_bot_id().value_or_empty();
|
||||
|
@ -654,8 +659,10 @@ void HistoryMessage::createComponentsHelper(
|
|||
const auto to = LookupReplyTo(history(), replyTo);
|
||||
const auto replyToTop = LookupReplyToTop(to);
|
||||
config.replyToTop = replyToTop ? replyToTop : replyTo;
|
||||
const auto forum = history()->peer->forum();
|
||||
config.replyIsTopicPost = LookupReplyIsTopicPost(to)
|
||||
|| to->Has<HistoryServiceTopicInfo>();
|
||||
|| (to && to->Has<HistoryServiceTopicInfo>())
|
||||
|| (forum && forum->creating(replyToTop));
|
||||
}
|
||||
config.markup = std::move(markup);
|
||||
if (flags & MessageFlag::HasPostAuthor) config.author = postAuthor;
|
||||
|
@ -1811,16 +1818,30 @@ void HistoryMessage::setSponsoredFrom(const Data::SponsoredFrom &from) {
|
|||
: Type::Group;
|
||||
}
|
||||
|
||||
void HistoryMessage::setReplyToTop(MsgId replyToTop) {
|
||||
void HistoryMessage::setReplyFields(
|
||||
MsgId replyTo,
|
||||
MsgId replyToTop,
|
||||
bool isForumPost) {
|
||||
const auto reply = Get<HistoryMessageReply>();
|
||||
if (!reply
|
||||
|| (reply->replyToMsgTop == replyToTop)
|
||||
|| (reply->replyToMsgTop != 0)
|
||||
|| isScheduled()) {
|
||||
if (!reply || isScheduled()) {
|
||||
return;
|
||||
}
|
||||
reply->replyToMsgTop = replyToTop;
|
||||
changeReplyToTopCounter(reply, 1);
|
||||
reply->topicPost = isForumPost;
|
||||
if ((reply->replyToMsgId != replyTo)
|
||||
&& !IsServerMsgId(reply->replyToMsgId)) {
|
||||
reply->replyToMsgId = replyTo;
|
||||
if (!reply->updateData(this)) {
|
||||
RequestDependentMessageData(
|
||||
this,
|
||||
reply->replyToPeerId,
|
||||
reply->replyToMsgId);
|
||||
}
|
||||
}
|
||||
if ((reply->replyToMsgTop != replyToTop)
|
||||
&& !IsServerMsgId(reply->replyToMsgTop)) {
|
||||
reply->replyToMsgTop = replyToTop;
|
||||
changeReplyToTopCounter(reply, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryMessage::setRealId(MsgId newId) {
|
||||
|
|
|
@ -146,7 +146,10 @@ public:
|
|||
int delta,
|
||||
PeerId replier,
|
||||
std::optional<bool> unread) override;
|
||||
void setReplyToTop(MsgId replyToTop) override;
|
||||
void setReplyFields(
|
||||
MsgId replyTo,
|
||||
MsgId replyToTop,
|
||||
bool isForumPost) override;
|
||||
void setPostAuthor(const QString &author) override;
|
||||
void setRealId(MsgId newId) override;
|
||||
void incrementReplyToTopCounter() override;
|
||||
|
|
|
@ -1318,12 +1318,12 @@ MsgId HistoryService::topicRootId() const {
|
|||
return Data::ForumTopic::kGeneralId;
|
||||
}
|
||||
|
||||
void HistoryService::setReplyToTop(MsgId replyToTop) {
|
||||
void HistoryService::setReplyFields(
|
||||
MsgId replyTo,
|
||||
MsgId replyToTop,
|
||||
bool isForumPost) {
|
||||
const auto data = GetDependentData();
|
||||
if (!data
|
||||
|| (data->topId == replyToTop)
|
||||
|| (data->topId != 0)
|
||||
|| isScheduled()) {
|
||||
if (!data || IsServerMsgId(data->topId) || isScheduled()) {
|
||||
return;
|
||||
}
|
||||
data->topId = replyToTop;
|
||||
|
|
|
@ -139,7 +139,10 @@ public:
|
|||
MsgId replyToId() const override;
|
||||
MsgId replyToTop() const override;
|
||||
MsgId topicRootId() const override;
|
||||
void setReplyToTop(MsgId replyToTop) override;
|
||||
void setReplyFields(
|
||||
MsgId replyTo,
|
||||
MsgId replyToTop,
|
||||
bool isForumPost) override;
|
||||
|
||||
std::unique_ptr<HistoryView::Element> createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
|
|
|
@ -154,6 +154,16 @@ object_ptr<Window::SectionWidget> RepliesMemento::createWidget(
|
|||
return result;
|
||||
}
|
||||
|
||||
void RepliesMemento::setupTopicViewer() {
|
||||
_history->owner().itemIdChanged(
|
||||
) | rpl::start_with_next([=](const Data::Session::IdChange &change) {
|
||||
if (_rootId == change.oldId) {
|
||||
_rootId = change.newId.msg;
|
||||
_replies = nullptr;
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
RepliesWidget::RepliesWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
@ -199,6 +209,7 @@ RepliesWidget::RepliesWidget(
|
|||
|
||||
setupRoot();
|
||||
setupRootView();
|
||||
setupTopicViewer();
|
||||
|
||||
session().api().requestFullPeer(_history->peer);
|
||||
|
||||
|
@ -442,6 +453,27 @@ void RepliesWidget::setupRootView() {
|
|||
}, _rootView->lifetime());
|
||||
}
|
||||
|
||||
void RepliesWidget::setupTopicViewer() {
|
||||
_history->owner().itemIdChanged(
|
||||
) | rpl::start_with_next([=](const Data::Session::IdChange &change) {
|
||||
if (_rootId == change.oldId) {
|
||||
_rootId = change.newId.msg;
|
||||
_root = lookupRoot();
|
||||
createReplies();
|
||||
if (_topic && _topic->rootId() == change.oldId) {
|
||||
setTopic(_topic->forum()->topicFor(change.newId.msg));
|
||||
}
|
||||
_inner->update();
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void RepliesWidget::setTopic(Data::ForumTopic *topic) {
|
||||
if ((_topic = topic)) {
|
||||
refreshTopBarActiveChat();
|
||||
}
|
||||
}
|
||||
|
||||
HistoryItem *RepliesWidget::lookupRoot() const {
|
||||
return _history->owner().message(_history->peer, _rootId);
|
||||
}
|
||||
|
@ -458,9 +490,7 @@ Data::ForumTopic *RepliesWidget::lookupTopic() {
|
|||
).done([=](const MTPmessages_ForumTopics &result) {
|
||||
if (const auto forum = _history->peer->forum()) {
|
||||
forum->applyReceivedTopics(result);
|
||||
if ((_topic = forum->topicFor(_rootId))) {
|
||||
refreshTopBarActiveChat();
|
||||
}
|
||||
setTopic(forum->topicFor(_rootId));
|
||||
}
|
||||
_resolveTopicRequestId = 0;
|
||||
}).fail([=] {
|
||||
|
@ -1699,32 +1729,44 @@ void RepliesWidget::saveState(not_null<RepliesMemento*> memento) {
|
|||
_inner->saveState(memento->list());
|
||||
}
|
||||
|
||||
void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
|
||||
const auto setReplies = [&](std::shared_ptr<Data::RepliesList> replies) {
|
||||
_replies = std::move(replies);
|
||||
void RepliesWidget::createReplies() {
|
||||
auto old = base::take(_replies);
|
||||
setReplies(std::make_shared<Data::RepliesList>(_history, _rootId));
|
||||
if (old) {
|
||||
_inner->showAroundPosition(Data::UnreadMessagePosition, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
rpl::combine(
|
||||
rpl::single(0) | rpl::then(_replies->fullCount()),
|
||||
_areComments.value()
|
||||
) | rpl::map([=](int count, bool areComments) {
|
||||
return count
|
||||
? (areComments
|
||||
? tr::lng_comments_header
|
||||
: tr::lng_replies_header)(
|
||||
lt_count_decimal,
|
||||
rpl::single(count) | tr::to_count())
|
||||
: (areComments
|
||||
? tr::lng_comments_header_none
|
||||
: tr::lng_replies_header_none)();
|
||||
}) | rpl::flatten_latest(
|
||||
) | rpl::start_with_next([=](const QString &text) {
|
||||
_topBar->setCustomTitle(text);
|
||||
}, lifetime());
|
||||
};
|
||||
void RepliesWidget::setReplies(std::shared_ptr<Data::RepliesList> replies) {
|
||||
_replies = std::move(replies);
|
||||
_repliesLifetime.destroy();
|
||||
if (_topic) {
|
||||
return;
|
||||
}
|
||||
rpl::combine(
|
||||
rpl::single(0) | rpl::then(_replies->fullCount()),
|
||||
_areComments.value()
|
||||
) | rpl::map([=](int count, bool areComments) {
|
||||
return count
|
||||
? (areComments
|
||||
? tr::lng_comments_header
|
||||
: tr::lng_replies_header)(
|
||||
lt_count_decimal,
|
||||
rpl::single(count) | tr::to_count())
|
||||
: (areComments
|
||||
? tr::lng_comments_header_none
|
||||
: tr::lng_replies_header_none)();
|
||||
}) | rpl::flatten_latest(
|
||||
) | rpl::start_with_next([=](const QString &text) {
|
||||
_topBar->setCustomTitle(text);
|
||||
}, _repliesLifetime);
|
||||
}
|
||||
|
||||
void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
|
||||
if (auto replies = memento->getReplies()) {
|
||||
setReplies(std::move(replies));
|
||||
} else if (!_replies) {
|
||||
setReplies(std::make_shared<Data::RepliesList>(_history, _rootId));
|
||||
createReplies();
|
||||
}
|
||||
restoreReplyReturns(memento->replyReturns());
|
||||
_inner->restoreState(memento->list());
|
||||
|
|
|
@ -163,6 +163,8 @@ private:
|
|||
void updateAdaptiveLayout();
|
||||
void saveState(not_null<RepliesMemento*> memento);
|
||||
void restoreState(not_null<RepliesMemento*> memento);
|
||||
void setReplies(std::shared_ptr<Data::RepliesList> replies);
|
||||
void createReplies();
|
||||
void showAtStart();
|
||||
void showAtEnd();
|
||||
void showAtPosition(
|
||||
|
@ -178,6 +180,8 @@ private:
|
|||
|
||||
void setupRoot();
|
||||
void setupRootView();
|
||||
void setupTopicViewer();
|
||||
void setTopic(Data::ForumTopic *topic);
|
||||
void setupDragArea();
|
||||
void sendReadTillRequest();
|
||||
void readTill(not_null<HistoryItem*> item);
|
||||
|
@ -276,6 +280,7 @@ private:
|
|||
mutable bool _newTopicDiscarded = false;
|
||||
|
||||
std::shared_ptr<Data::RepliesList> _replies;
|
||||
rpl::lifetime _repliesLifetime;
|
||||
rpl::variable<bool> _areComments = false;
|
||||
std::shared_ptr<SendActionPainter> _sendAction;
|
||||
QPointer<ListWidget> _inner;
|
||||
|
@ -363,13 +368,17 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void setupTopicViewer();
|
||||
|
||||
const not_null<History*> _history;
|
||||
const MsgId _rootId = 0;
|
||||
MsgId _rootId = 0;
|
||||
const MsgId _highlightId = 0;
|
||||
ListMemento _list;
|
||||
std::shared_ptr<Data::RepliesList> _replies;
|
||||
std::vector<MsgId> _replyReturns;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_info.h"
|
||||
#include "styles/style_profile.h"
|
||||
|
@ -340,6 +341,12 @@ ContentMemento::ContentMemento(not_null<Data::ForumTopic*> topic)
|
|||
: _peer(topic->channel())
|
||||
, _migratedPeerId(_peer->migrateFrom() ? _peer->migrateFrom()->id : 0)
|
||||
, _topic(topic) {
|
||||
_peer->owner().itemIdChanged(
|
||||
) | rpl::start_with_next([=](const Data::Session::IdChange &change) {
|
||||
if (_topic->rootId() == change.oldId) {
|
||||
_topic = _topic->forum()->topicFor(change.newId.msg);
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
ContentMemento::ContentMemento(Settings::Tag settings)
|
||||
|
|
|
@ -213,7 +213,7 @@ public:
|
|||
private:
|
||||
PeerData * const _peer = nullptr;
|
||||
const PeerId _migratedPeerId = 0;
|
||||
Data::ForumTopic * const _topic = nullptr;
|
||||
Data::ForumTopic *_topic = nullptr;
|
||||
UserData * const _settingsSelf = nullptr;
|
||||
PollData * const _poll = nullptr;
|
||||
const FullMsgId _pollContextId;
|
||||
|
@ -223,6 +223,8 @@ private:
|
|||
bool _searchEnabledByContent = false;
|
||||
bool _searchStartsFocused = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Info
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_download_manager.h"
|
||||
|
@ -180,6 +181,7 @@ Controller::Controller(
|
|||
, _section(memento->section()) {
|
||||
updateSearchControllers(memento);
|
||||
setupMigrationViewer();
|
||||
setupTopicViewer();
|
||||
}
|
||||
|
||||
void Controller::setupMigrationViewer() {
|
||||
|
@ -210,6 +212,17 @@ void Controller::setupMigrationViewer() {
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
void Controller::setupTopicViewer() {
|
||||
session().data().itemIdChanged(
|
||||
) | rpl::start_with_next([=](const Data::Session::IdChange &change) {
|
||||
if (const auto topic = _key.topic()) {
|
||||
if (topic->rootId() == change.oldId) {
|
||||
_key = Key(topic->forum()->topicFor(change.newId.msg));
|
||||
}
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
Wrap Controller::wrap() const {
|
||||
return _widget->wrap();
|
||||
}
|
||||
|
|
|
@ -235,6 +235,7 @@ private:
|
|||
void updateSearchControllers(not_null<ContentMemento*> memento);
|
||||
SearchQuery produceSearchQuery(const QString &query) const;
|
||||
void setupMigrationViewer();
|
||||
void setupTopicViewer();
|
||||
|
||||
not_null<WrapWidget*> _widget;
|
||||
Key _key;
|
||||
|
|
|
@ -28,7 +28,7 @@ class Memento final : public ContentMemento {
|
|||
public:
|
||||
explicit Memento(not_null<Controller*> controller);
|
||||
Memento(not_null<PeerData*> peer, PeerId migratedPeerId, Type type);
|
||||
Memento(not_null<Data::ForumTopic*> peer, Type type);
|
||||
Memento(not_null<Data::ForumTopic*> topic, Type type);
|
||||
|
||||
using SearchState = Api::DelayedSearchController::SavedState;
|
||||
|
||||
|
|
|
@ -702,8 +702,8 @@ void OverlayWidget::documentUpdated(not_null<DocumentData*> document) {
|
|||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::changingMsgId(not_null<HistoryItem*> row, MsgId oldId) {
|
||||
if (row == _message) {
|
||||
void OverlayWidget::changingMsgId(FullMsgId newId, MsgId oldId) {
|
||||
if (_message && _message->fullId() == newId) {
|
||||
refreshMediaViewer();
|
||||
}
|
||||
}
|
||||
|
@ -4181,7 +4181,7 @@ void OverlayWidget::setSession(not_null<Main::Session*> session) {
|
|||
|
||||
session->data().itemIdChanged(
|
||||
) | rpl::start_with_next([=](const Data::Session::IdChange &change) {
|
||||
changingMsgId(change.item, change.oldId);
|
||||
changingMsgId(change.newId, change.oldId);
|
||||
}, _sessionLifetime);
|
||||
|
||||
session->data().itemRemoved(
|
||||
|
|
|
@ -330,7 +330,7 @@ private:
|
|||
void updateThemePreviewGeometry();
|
||||
|
||||
void documentUpdated(not_null<DocumentData*> document);
|
||||
void changingMsgId(not_null<HistoryItem*> row, MsgId oldId);
|
||||
void changingMsgId(FullMsgId newId, MsgId oldId);
|
||||
|
||||
[[nodiscard]] int finalContentRotation() const;
|
||||
[[nodiscard]] QRect finalContentRect() const;
|
||||
|
|
|
@ -68,7 +68,7 @@ AlbumThumbnail::AlbumThumbnail(
|
|||
|
||||
const auto availableFileWidth = st::sendMediaPreviewSize
|
||||
- st.thumbSize
|
||||
- st.padding.right()
|
||||
- st.thumbSkip
|
||||
// Right buttons.
|
||||
- st::sendBoxAlbumGroupButtonFile.width * 2
|
||||
- st::sendBoxAlbumGroupEditInternalSkip * 2
|
||||
|
@ -392,7 +392,7 @@ void AlbumThumbnail::paintFile(
|
|||
int top,
|
||||
int outerWidth) {
|
||||
const auto &st = st::attachPreviewThumbLayout;
|
||||
const auto textLeft = left + st.thumbSize + st.padding.right();
|
||||
const auto textLeft = left + st.thumbSize + st.thumbSkip;
|
||||
|
||||
p.drawPixmap(left, top, _fileThumb);
|
||||
p.setFont(st::semiboldFont);
|
||||
|
|
|
@ -39,6 +39,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_document_resolver.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_group_call.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "passport/passport_form_controller.h"
|
||||
|
@ -674,6 +676,27 @@ SessionController::SessionController(
|
|||
});
|
||||
}, lifetime());
|
||||
|
||||
session->data().itemIdChanged(
|
||||
) | rpl::start_with_next([=](Data::Session::IdChange change) {
|
||||
const auto current = _activeChatEntry.current();
|
||||
if (const auto topic = current.key.topic()) {
|
||||
if (topic->rootId() == change.oldId) {
|
||||
setActiveChatEntry({
|
||||
Dialogs::Key(topic->forum()->topicFor(change.newId.msg)),
|
||||
current.fullId,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (auto &entry : _chatEntryHistory) {
|
||||
if (const auto topic = entry.key.topic()) {
|
||||
if (topic->rootId() == change.oldId) {
|
||||
entry.key = Dialogs::Key(
|
||||
topic->forum()->topicFor(change.newId.msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
session->api().globalPrivacy().suggestArchiveAndMute(
|
||||
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||
session->api().globalPrivacy().reload(crl::guard(this, [=] {
|
||||
|
|
Loading…
Add table
Reference in a new issue