| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "info/info_controller.h"
- #include "ui/search_field_controller.h"
- #include "data/data_shared_media.h"
- #include "info/info_content_widget.h"
- #include "info/info_memento.h"
- #include "info/global_media/info_global_media_widget.h"
- #include "info/media/info_media_widget.h"
- #include "core/application.h"
- #include "data/data_changes.h"
- #include "data/data_peer.h"
- #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"
- #include "history/history_item.h"
- #include "main/main_session.h"
- #include "window/window_session_controller.h"
- namespace Info {
- Key::Key(not_null<PeerData*> peer) : _value(peer) {
- }
- Key::Key(not_null<Data::ForumTopic*> topic) : _value(topic) {
- }
- Key::Key(Settings::Tag settings) : _value(settings) {
- }
- Key::Key(Downloads::Tag downloads) : _value(downloads) {
- }
- Key::Key(Stories::Tag stories) : _value(stories) {
- }
- Key::Key(Statistics::Tag statistics) : _value(statistics) {
- }
- Key::Key(BotStarRef::Tag starref) : _value(starref) {
- }
- Key::Key(GlobalMedia::Tag global) : _value(global) {
- }
- Key::Key(not_null<PollData*> poll, FullMsgId contextId)
- : _value(PollKey{ poll, contextId }) {
- }
- Key::Key(
- std::shared_ptr<Api::WhoReadList> whoReadIds,
- Data::ReactionId selected,
- FullMsgId contextId)
- : _value(ReactionsKey{ whoReadIds, selected, contextId }) {
- }
- PeerData *Key::peer() const {
- if (const auto peer = std::get_if<not_null<PeerData*>>(&_value)) {
- return *peer;
- } else if (const auto topic = this->topic()) {
- return topic->channel();
- }
- return nullptr;
- }
- Data::ForumTopic *Key::topic() const {
- if (const auto topic = std::get_if<not_null<Data::ForumTopic*>>(
- &_value)) {
- return *topic;
- }
- return nullptr;
- }
- UserData *Key::settingsSelf() const {
- if (const auto tag = std::get_if<Settings::Tag>(&_value)) {
- return tag->self;
- }
- return nullptr;
- }
- bool Key::isDownloads() const {
- return v::is<Downloads::Tag>(_value);
- }
- bool Key::isGlobalMedia() const {
- return v::is<GlobalMedia::Tag>(_value);
- }
- PeerData *Key::storiesPeer() const {
- if (const auto tag = std::get_if<Stories::Tag>(&_value)) {
- return tag->peer;
- }
- return nullptr;
- }
- Stories::Tab Key::storiesTab() const {
- if (const auto tag = std::get_if<Stories::Tag>(&_value)) {
- return tag->tab;
- }
- return Stories::Tab();
- }
- Statistics::Tag Key::statisticsTag() const {
- if (const auto tag = std::get_if<Statistics::Tag>(&_value)) {
- return *tag;
- }
- return Statistics::Tag();
- }
- PeerData *Key::starrefPeer() const {
- if (const auto tag = std::get_if<BotStarRef::Tag>(&_value)) {
- return tag->peer;
- }
- return nullptr;
- }
- BotStarRef::Type Key::starrefType() const {
- if (const auto tag = std::get_if<BotStarRef::Tag>(&_value)) {
- return tag->type;
- }
- return BotStarRef::Type();
- }
- PollData *Key::poll() const {
- if (const auto data = std::get_if<PollKey>(&_value)) {
- return data->poll;
- }
- return nullptr;
- }
- FullMsgId Key::pollContextId() const {
- if (const auto data = std::get_if<PollKey>(&_value)) {
- return data->contextId;
- }
- return FullMsgId();
- }
- std::shared_ptr<Api::WhoReadList> Key::reactionsWhoReadIds() const {
- if (const auto data = std::get_if<ReactionsKey>(&_value)) {
- return data->whoReadIds;
- }
- return nullptr;
- }
- Data::ReactionId Key::reactionsSelected() const {
- if (const auto data = std::get_if<ReactionsKey>(&_value)) {
- return data->selected;
- }
- return Data::ReactionId();
- }
- FullMsgId Key::reactionsContextId() const {
- if (const auto data = std::get_if<ReactionsKey>(&_value)) {
- return data->contextId;
- }
- return FullMsgId();
- }
- rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource(
- SparseIdsMergedSlice::UniversalMsgId aroundId,
- int limitBefore,
- int limitAfter) const {
- Expects(peer() != nullptr);
- const auto isScheduled = [&] {
- const auto peerId = peer()->id;
- if (const auto item = session().data().message(peerId, aroundId)) {
- return item->isScheduled();
- }
- return false;
- }();
- const auto mediaViewer = isScheduled
- ? SharedScheduledMediaViewer
- : SharedMediaMergedViewer;
- const auto topicId = isScheduled
- ? SparseIdsMergedSlice::kScheduledTopicId
- : topic()
- ? topic()->rootId()
- : MsgId(0);
- return mediaViewer(
- &session(),
- SharedMediaMergedKey(
- SparseIdsMergedSlice::Key(
- peer()->id,
- topicId,
- migratedPeerId(),
- aroundId),
- section().mediaType()),
- limitBefore,
- limitAfter);
- }
- rpl::producer<QString> AbstractController::mediaSourceQueryValue() const {
- return rpl::single(QString());
- }
- rpl::producer<QString> AbstractController::searchQueryValue() const {
- return rpl::single(QString());
- }
- AbstractController::AbstractController(
- not_null<Window::SessionController*> parent)
- : SessionNavigation(&parent->session())
- , _parent(parent) {
- }
- PeerData *AbstractController::peer() const {
- return key().peer();
- }
- PeerId AbstractController::migratedPeerId() const {
- if (const auto peer = migrated()) {
- return peer->id;
- }
- return PeerId(0);
- }
- PollData *AbstractController::poll() const {
- if (const auto item = session().data().message(pollContextId())) {
- if (const auto media = item->media()) {
- return media->poll();
- }
- }
- return nullptr;
- }
- auto AbstractController::reactionsWhoReadIds() const
- -> std::shared_ptr<Api::WhoReadList> {
- return key().reactionsWhoReadIds();
- }
- Data::ReactionId AbstractController::reactionsSelected() const {
- return key().reactionsSelected();
- }
- FullMsgId AbstractController::reactionsContextId() const {
- return key().reactionsContextId();
- }
- void AbstractController::showSection(
- std::shared_ptr<Window::SectionMemento> memento,
- const Window::SectionShow ¶ms) {
- return parentController()->showSection(std::move(memento), params);
- }
- void AbstractController::showBackFromStack(
- const Window::SectionShow ¶ms) {
- return parentController()->showBackFromStack(params);
- }
- void AbstractController::showPeerHistory(
- PeerId peerId,
- const Window::SectionShow ¶ms,
- MsgId msgId) {
- return parentController()->showPeerHistory(peerId, params, msgId);
- }
- Controller::Controller(
- not_null<WrapWidget*> widget,
- not_null<Window::SessionController*> window,
- not_null<ContentMemento*> memento)
- : AbstractController(window)
- , _widget(widget)
- , _key(memento->key())
- , _migrated(memento->migratedPeerId()
- ? window->session().data().peer(memento->migratedPeerId()).get()
- : nullptr)
- , _section(memento->section()) {
- updateSearchControllers(memento);
- setupMigrationViewer();
- setupTopicViewer();
- }
- void Controller::setupMigrationViewer() {
- const auto peer = _key.peer();
- if (_key.topic()
- || !peer
- || (!peer->isChat() && !peer->isChannel())
- || _migrated) {
- return;
- }
- peer->session().changes().peerFlagsValue(
- peer,
- Data::PeerUpdate::Flag::Migration
- ) | rpl::filter([=] {
- return peer->migrateTo() || (peer->migrateFrom() != _migrated);
- }) | rpl::start_with_next([=] {
- replaceWith(std::make_shared<Memento>(peer, _section));
- }, lifetime());
- }
- void Controller::replaceWith(std::shared_ptr<Memento> memento) {
- const auto window = parentController();
- auto params = Window::SectionShow(
- Window::SectionShow::Way::Backward,
- anim::type::instant,
- anim::activation::background);
- if (wrap() == Wrap::Side) {
- params.thirdColumn = true;
- }
- InvokeQueued(_widget, [=, memento = std::move(memento)]() mutable {
- window->showSection(std::move(memento), params);
- });
- }
- 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
- || (topic->peer()->id == change.newId.peer
- && topic->rootId() == change.newId.msg)) {
- const auto now = topic->forum()->topicFor(change.newId.msg);
- _key = Key(now);
- replaceWith(std::make_shared<Memento>(now, _section));
- }
- }
- }, _lifetime);
- }
- Wrap Controller::wrap() const {
- return _widget->wrap();
- }
- rpl::producer<Wrap> Controller::wrapValue() const {
- return _widget->wrapValue();
- }
- not_null<Ui::RpWidget*> Controller::wrapWidget() const {
- return _widget;
- }
- bool Controller::validateMementoPeer(
- not_null<ContentMemento*> memento) const {
- return memento->peer() == peer()
- && memento->migratedPeerId() == migratedPeerId()
- && memento->settingsSelf() == settingsSelf()
- && memento->storiesPeer() == storiesPeer()
- && memento->statisticsTag().peer == statisticsTag().peer
- && memento->starrefPeer() == starrefPeer()
- && memento->starrefType() == starrefType();
- }
- void Controller::setSection(not_null<ContentMemento*> memento) {
- _section = memento->section();
- updateSearchControllers(memento);
- }
- bool Controller::hasBackButton() const {
- return _widget->hasBackButton();
- }
- void Controller::updateSearchControllers(
- not_null<ContentMemento*> memento) {
- using Type = Section::Type;
- const auto type = _section.type();
- const auto isMedia = (type == Type::Media)
- || (type == Type::GlobalMedia);
- const auto mediaType = isMedia
- ? _section.mediaType()
- : Section::MediaType::kCount;
- const auto hasMediaSearch = isMedia
- && SharedMediaAllowSearch(mediaType);
- const auto hasRequestsListSearch = (type == Type::RequestsList);
- const auto hasCommonGroupsSearch = (type == Type::CommonGroups);
- const auto hasDownloadsSearch = (type == Type::Downloads);
- const auto hasMembersSearch = (type == Type::Members)
- || (type == Type::Profile);
- const auto searchQuery = memento->searchFieldQuery();
- if (type == Type::Media) {
- _searchController
- = std::make_unique<Api::DelayedSearchController>(&session());
- auto mediaMemento = dynamic_cast<Media::Memento*>(memento.get());
- Assert(mediaMemento != nullptr);
- _searchController->restoreState(mediaMemento->searchState());
- } else {
- _searchController = nullptr;
- }
- if (hasMediaSearch
- || hasRequestsListSearch
- || hasCommonGroupsSearch
- || hasDownloadsSearch
- || hasMembersSearch) {
- _searchFieldController
- = std::make_unique<Ui::SearchFieldController>(
- searchQuery);
- if (_searchController) {
- _searchFieldController->queryValue(
- ) | rpl::start_with_next([=](QString &&query) {
- _searchController->setQuery(
- produceSearchQuery(std::move(query)));
- }, _searchFieldController->lifetime());
- }
- _seachEnabledByContent = memento->searchEnabledByContent();
- _searchStartsFocused = memento->searchStartsFocused();
- } else {
- _searchFieldController = nullptr;
- }
- }
- void Controller::saveSearchState(not_null<ContentMemento*> memento) {
- if (_searchFieldController) {
- memento->setSearchFieldQuery(
- _searchFieldController->query());
- memento->setSearchEnabledByContent(
- _seachEnabledByContent.current());
- }
- if (_searchController) {
- auto mediaMemento = dynamic_cast<Media::Memento*>(
- memento.get());
- Assert(mediaMemento != nullptr);
- mediaMemento->setSearchState(_searchController->saveState());
- }
- }
- void Controller::showSection(
- std::shared_ptr<Window::SectionMemento> memento,
- const Window::SectionShow ¶ms) {
- if (!_widget->showInternal(memento.get(), params)) {
- AbstractController::showSection(std::move(memento), params);
- }
- }
- void Controller::showBackFromStack(const Window::SectionShow ¶ms) {
- if (!_widget->showBackFromStackInternal(params)) {
- AbstractController::showBackFromStack(params);
- }
- }
- void Controller::removeFromStack(const std::vector<Section> §ions) const {
- _widget->removeFromStack(sections);
- }
- auto Controller::produceSearchQuery(
- const QString &query) const -> SearchQuery {
- Expects(_key.peer() != nullptr);
- auto result = SearchQuery();
- result.type = _section.mediaType();
- result.peerId = _key.peer()->id;
- result.topicRootId = _key.topic() ? _key.topic()->rootId() : 0;
- result.query = query;
- result.migratedPeerId = _migrated ? _migrated->id : PeerId(0);
- return result;
- }
- rpl::producer<bool> Controller::searchEnabledByContent() const {
- return _seachEnabledByContent.value();
- }
- rpl::producer<QString> Controller::mediaSourceQueryValue() const {
- return _searchController->currentQueryValue();
- }
- rpl::producer<QString> Controller::searchQueryValue() const {
- const auto controller = searchFieldController();
- return controller ? controller->queryValue() : rpl::single(QString());
- }
- rpl::producer<SparseIdsMergedSlice> Controller::mediaSource(
- SparseIdsMergedSlice::UniversalMsgId aroundId,
- int limitBefore,
- int limitAfter) const {
- auto query = _searchController->currentQuery();
- if (!query.query.isEmpty()) {
- return _searchController->idsSlice(
- aroundId,
- limitBefore,
- limitAfter);
- }
- return SharedMediaMergedViewer(
- &session(),
- SharedMediaMergedKey(
- SparseIdsMergedSlice::Key(
- query.peerId,
- query.topicRootId,
- query.migratedPeerId,
- aroundId),
- query.type),
- limitBefore,
- limitAfter);
- }
- std::any &Controller::stepDataReference() {
- return _stepData;
- }
- void Controller::takeStepData(not_null<Controller*> another) {
- _stepData = base::take(another->_stepData);
- }
- Controller::~Controller() = default;
- } // namespace Info
|