mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 06:26:18 +00:00
Support forwarding to monoforums.
This commit is contained in:
@@ -23,6 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/ui_utility.h"
|
||||
#include "main/main_session.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_stories.h"
|
||||
#include "data/data_channel.h"
|
||||
@@ -867,6 +869,45 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
*weak = owned.data();
|
||||
delegate()->peerListUiShow()->showBox(std::move(owned));
|
||||
return;
|
||||
} else if (const auto monoforum = peer->monoforum()) {
|
||||
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||
auto callback = [=](not_null<Data::SavedSublist*> sublist) {
|
||||
const auto exists = guard.get();
|
||||
if (!exists) {
|
||||
if (*weak) {
|
||||
(*weak)->closeBox();
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto onstack = std::move(_callback);
|
||||
onstack(sublist);
|
||||
if (guard) {
|
||||
_callback = std::move(onstack);
|
||||
} else if (*weak) {
|
||||
(*weak)->closeBox();
|
||||
}
|
||||
};
|
||||
const auto filter = [=](not_null<Data::SavedSublist*> sublist) {
|
||||
return guard && (!_filter || _filter(sublist));
|
||||
};
|
||||
auto owned = Box<PeerListBox>(
|
||||
std::make_unique<ChooseSublistBoxController>(
|
||||
monoforum,
|
||||
std::move(callback),
|
||||
filter),
|
||||
[=](not_null<PeerListBox*> box) {
|
||||
box->addButton(tr::lng_cancel(), [=] {
|
||||
box->closeBox();
|
||||
});
|
||||
|
||||
monoforum->destroyed(
|
||||
) | rpl::start_with_next([=] {
|
||||
box->closeBox();
|
||||
}, box->lifetime());
|
||||
});
|
||||
*weak = owned.data();
|
||||
delegate()->peerListUiShow()->showBox(std::move(owned));
|
||||
return;
|
||||
}
|
||||
const auto history = peer->owner().history(peer);
|
||||
auto callback = std::move(_callback);
|
||||
@@ -1137,6 +1178,111 @@ auto ChooseTopicBoxController::createRow(not_null<Data::ForumTopic*> topic)
|
||||
return skip ? nullptr : std::make_unique<Row>(topic);
|
||||
};
|
||||
|
||||
ChooseSublistBoxController::ChooseSublistBoxController(
|
||||
not_null<Data::SavedMessages*> monoforum,
|
||||
FnMut<void(not_null<Data::SavedSublist*>)> callback,
|
||||
Fn<bool(not_null<Data::SavedSublist*>)> filter)
|
||||
: _monoforum(monoforum)
|
||||
, _callback(std::move(callback))
|
||||
, _filter(std::move(filter)) {
|
||||
setStyleOverrides(&st::chooseTopicList);
|
||||
|
||||
_monoforum->chatsListChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshRows();
|
||||
}, lifetime());
|
||||
|
||||
_monoforum->sublistDestroyed(
|
||||
) | rpl::start_with_next([=](not_null<Data::SavedSublist*> sublist) {
|
||||
const auto id = sublist->sublistPeer()->id.value;
|
||||
if (const auto row = delegate()->peerListFindRow(id)) {
|
||||
delegate()->peerListRemoveRow(row);
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
Main::Session &ChooseSublistBoxController::session() const {
|
||||
return _monoforum->session();
|
||||
}
|
||||
|
||||
void ChooseSublistBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto weak = base::make_weak(this);
|
||||
auto onstack = base::take(_callback);
|
||||
onstack(_monoforum->sublist(row->peer()));
|
||||
if (weak) {
|
||||
_callback = std::move(onstack);
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseSublistBoxController::prepare() {
|
||||
delegate()->peerListSetTitle(tr::lng_forward_choose());
|
||||
setSearchNoResultsText(tr::lng_topics_not_found(tr::now));
|
||||
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
|
||||
refreshRows(true);
|
||||
|
||||
session().changes().entryUpdates(
|
||||
Data::EntryUpdate::Flag::Repaint
|
||||
) | rpl::start_with_next([=](const Data::EntryUpdate &update) {
|
||||
if (const auto sublist = update.entry->asSublist()) {
|
||||
if (sublist->parent() == _monoforum) {
|
||||
const auto id = sublist->sublistPeer()->id.value;
|
||||
if (const auto row = delegate()->peerListFindRow(id)) {
|
||||
delegate()->peerListUpdateRow(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void ChooseSublistBoxController::refreshRows(bool initial) {
|
||||
auto added = false;
|
||||
for (const auto &row : _monoforum->chatsList()->indexed()->all()) {
|
||||
if (const auto sublist = row->sublist()) {
|
||||
const auto id = sublist->sublistPeer()->id.value;
|
||||
auto already = delegate()->peerListFindRow(id);
|
||||
if (initial || !already) {
|
||||
if (auto created = createRow(sublist)) {
|
||||
delegate()->peerListAppendRow(std::move(created));
|
||||
added = true;
|
||||
}
|
||||
} else if (already->isSearchResult()) {
|
||||
delegate()->peerListAppendFoundRow(already);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseSublistBoxController::loadMoreRows() {
|
||||
_monoforum->loadMore();
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> ChooseSublistBoxController::createSearchRow(
|
||||
PeerListRowId id) {
|
||||
const auto peer = session().data().peer(PeerId(id));
|
||||
if (const auto sublist = _monoforum->sublistLoaded(peer)) {
|
||||
auto result = std::make_unique<PeerListRow>(sublist->sublistPeer());
|
||||
result->setCustomStatus(QString());
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ChooseSublistBoxController::createRow(
|
||||
not_null<Data::SavedSublist*> sublist)
|
||||
-> std::unique_ptr<PeerListRow> {
|
||||
if (const auto skip = _filter && !_filter(sublist)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto result = std::make_unique<PeerListRow>(sublist->sublistPeer());
|
||||
result->setCustomStatus(QString());
|
||||
return result;
|
||||
};
|
||||
|
||||
void PaintRestrictionBadge(
|
||||
Painter &p,
|
||||
not_null<const style::PeerListItem*> st,
|
||||
|
@@ -27,6 +27,8 @@ namespace Data {
|
||||
class Thread;
|
||||
class Forum;
|
||||
class ForumTopic;
|
||||
class SavedSublist;
|
||||
class SavedMessages;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
@@ -393,3 +395,30 @@ private:
|
||||
Fn<bool(not_null<Data::ForumTopic*>)> _filter;
|
||||
|
||||
};
|
||||
|
||||
class ChooseSublistBoxController final
|
||||
: public PeerListController
|
||||
, public base::has_weak_ptr {
|
||||
public:
|
||||
ChooseSublistBoxController(
|
||||
not_null<Data::SavedMessages*> monoforum,
|
||||
FnMut<void(not_null<Data::SavedSublist*>)> callback,
|
||||
Fn<bool(not_null<Data::SavedSublist*>)> filter = nullptr);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
|
||||
void prepare() override;
|
||||
void loadMoreRows() override;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(PeerListRowId id) override;
|
||||
|
||||
private:
|
||||
void refreshRows(bool initial = false);
|
||||
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(
|
||||
not_null<Data::SavedSublist*> sublist);
|
||||
|
||||
const not_null<Data::SavedMessages*> _monoforum;
|
||||
FnMut<void(not_null<Data::SavedSublist*>)> _callback;
|
||||
Fn<bool(not_null<Data::SavedSublist*>)> _filter;
|
||||
|
||||
};
|
||||
|
@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
@@ -1163,8 +1164,11 @@ void SingleRowController::prepare() {
|
||||
return;
|
||||
}
|
||||
const auto topic = strong->asTopic();
|
||||
const auto sublist = strong->asSublist();
|
||||
auto row = topic
|
||||
? ChooseTopicBoxController::MakeRow(topic)
|
||||
: sublist
|
||||
? std::make_unique<PeerListRow>(sublist->sublistPeer())
|
||||
: std::make_unique<PeerListRow>(strong->peer());
|
||||
const auto raw = row.get();
|
||||
if (_status) {
|
||||
|
@@ -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),
|
||||
|
Reference in New Issue
Block a user