Support forwarding to monoforums.

This commit is contained in:
John Preston
2025-05-13 18:18:24 +04:00
parent e17bf18350
commit 76db55ff19
36 changed files with 516 additions and 78 deletions
+79 -7
View File
@@ -45,6 +45,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h"
#include "data/data_user.h"
#include "data/data_peer_values.h"
#include "data/data_saved_messages.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "data/data_folder.h"
#include "data/data_forum.h"
@@ -114,7 +116,9 @@ private:
not_null<History*> history;
not_null<PeerData*> peer;
Data::ForumTopic *topic = nullptr;
Data::SavedSublist *sublist = nullptr;
rpl::lifetime topicLifetime;
rpl::lifetime sublistLifetime;
Ui::RoundImageCheckbox checkbox;
Ui::Text::String name;
Ui::Animations::Simple nameActive;
@@ -143,6 +147,7 @@ private:
void preloadUserpic(not_null<Dialogs::Entry*> entry);
void changeCheckState(Chat *chat);
void chooseForumTopic(not_null<Data::Forum*> forum);
void chooseMonoforumSublist(not_null<Data::SavedMessages*> monoforum);
enum class ChangeStateWay {
Default,
SkipCallback,
@@ -638,15 +643,18 @@ void ShareBox::addPeerToMultiSelect(not_null<Data::Thread*> thread) {
auto addItemWay = Ui::MultiSelect::AddItemWay::Default;
const auto peer = thread->peer();
const auto topic = thread->asTopic();
const auto sublist = thread->asSublist();
_select->addItem(
peer->id.value,
(topic
? topic->title()
: sublist
? sublist->sublistPeer()->shortName()
: peer->isSelf()
? tr::lng_saved_short(tr::now)
: peer->shortName()),
st::activeButtonBg,
(topic
((topic || sublist)
? ForceRoundUserpicCallback(peer)
: PaintUserpicCallback(peer, true)),
addItemWay);
@@ -970,6 +978,8 @@ void ShareBox::Inner::updateChatName(not_null<Chat*> chat) {
const auto peer = chat->peer;
const auto text = chat->topic
? chat->topic->title()
: chat->sublist
? chat->sublist->sublistPeer()->name()
: peer->isSelf()
? tr::lng_saved_messages(tr::now)
: peer->isRepliesChat()
@@ -1209,7 +1219,7 @@ ShareBox::Inner::Chat::Chat(
st.checkbox,
updateCallback,
PaintUserpicCallback(peer, true),
[=](int size) { return peer->isForum()
[=](int size) { return (peer->isForum() || peer->isMonoforum())
? int(size * Ui::ForumUserpicRadiusMultiplier())
: std::optional<int>(); })
, name(st.checkbox.imageRadius * 2) {
@@ -1350,10 +1360,13 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
const auto checked = chat->checkbox.checked();
const auto forum = chat->peer->forum();
if (checked || !forum) {
const auto monoforum = chat->peer->monoforum();
if (checked || (!forum && !monoforum)) {
changePeerCheckState(chat, !checked);
} else {
chooseForumTopic(chat->peer->forum());
} else if (forum) {
chooseForumTopic(forum);
} else if (monoforum) {
chooseMonoforumSublist(monoforum);
}
}
@@ -1404,6 +1417,54 @@ void ShareBox::Inner::chooseForumTopic(not_null<Data::Forum*> forum) {
_show->showBox(std::move(box));
}
void ShareBox::Inner::chooseMonoforumSublist(
not_null<Data::SavedMessages*> monoforum) {
const auto guard = Ui::MakeWeak(this);
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
auto chosen = [=](not_null<Data::SavedSublist*> sublist) {
if (const auto strong = *weak) {
strong->closeBox();
}
if (!guard) {
return;
}
const auto row = _chatsIndexed->getRow(sublist->owningHistory());
if (!row) {
return;
}
const auto chat = getChat(row);
Assert(!chat->sublist);
chat->sublist = sublist;
chat->sublist->destroyed(
) | rpl::start_with_next([=] {
changePeerCheckState(chat, false);
}, chat->sublistLifetime);
updateChatName(chat);
changePeerCheckState(chat, true);
};
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
monoforum->destroyed(
) | rpl::start_with_next([=] {
box->closeBox();
}, box->lifetime());
};
auto filter = [=](not_null<Data::SavedSublist*> sublist) {
return guard && _descriptor.filterCallback(sublist);
};
auto box = Box<PeerListBox>(
std::make_unique<ChooseSublistBoxController>(
monoforum,
std::move(chosen),
std::move(filter)),
std::move(initBox));
*weak = box.data();
_show->showBox(std::move(box));
}
void ShareBox::Inner::peerUnselected(not_null<PeerData*> peer) {
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
changePeerCheckState(
@@ -1434,6 +1495,11 @@ void ShareBox::Inner::changePeerCheckState(
chat->topic = nullptr;
updateChatName(chat);
}
if (chat->sublist) {
chat->sublistLifetime.destroy();
chat->sublist = nullptr;
updateChatName(chat);
}
}
if (useCallback != ChangeStateWay::SkipCallback
&& _peerSelectedChangedCallback) {
@@ -1565,6 +1631,8 @@ not_null<Data::Thread*> ShareBox::Inner::chatThread(
not_null<Chat*> chat) const {
return chat->topic
? (Data::Thread*)chat->topic
: chat->sublist
? (Data::Thread*)chat->sublist
: chat->peer->owner().history(chat->peer).get();
}
@@ -1675,6 +1743,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
api.sendMessage(std::move(message));
}
const auto topicRootId = thread->topicRootId();
const auto sublistPeer = thread->maybeSublistPeer();
const auto kGeneralId = Data::ForumTopic::kGeneralId;
const auto topMsgId = (topicRootId == kGeneralId)
? MsgId(0)
@@ -1699,7 +1768,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
| (options.shortcutId
? Flag::f_quick_reply_shortcut
: Flag(0))
| (starsPaid ? Flag::f_allow_paid_stars : Flag());
| (starsPaid ? Flag::f_allow_paid_stars : Flag())
| (sublistPeer ? Flag::f_reply_to : Flag());
threadHistory->sendRequestId = api.request(
MTPmessages_ForwardMessages(
MTP_flags(sendFlags),
@@ -1708,7 +1778,9 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
MTP_vector<MTPlong>(generateRandom()),
peer->input,
MTP_int(topMsgId),
MTPInputReplyTo(),
(sublistPeer
? MTP_inputReplyToMonoForum(sublistPeer->input)
: MTPInputReplyTo()),
MTP_int(options.scheduled),
MTP_inputPeerEmpty(), // send_as
Data::ShortcutIdToMTP(session, options.shortcutId),