From 99c686e3e1dfbc47f71e818d84307313691875e6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 7 Feb 2018 15:40:37 +0300 Subject: [PATCH] Display feed channels list in feed info. --- Telegram/Resources/langs/lang.strings | 2 + .../info/feed/info_feed_channels.cpp | 28 ++--- .../feed/info_feed_channels_controllers.cpp | 110 ++++++++++++++++++ .../feed/info_feed_channels_controllers.h | 51 ++++++++ .../SourceFiles/info/feed/info_feed_cover.cpp | 3 +- .../feed/info_feed_profile_inner_widget.cpp | 45 ++++--- .../info/profile/info_profile_actions.cpp | 75 ++++++++++++ .../info/profile/info_profile_actions.h | 11 +- .../info/profile/info_profile_values.cpp | 20 ++++ .../info/profile/info_profile_values.h | 3 + Telegram/gyp/telegram_sources.txt | 2 + 11 files changed, 310 insertions(+), 40 deletions(-) create mode 100644 Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp create mode 100644 Telegram/SourceFiles/info/feed/info_feed_channels_controllers.h diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index b40cc45d5..e78a4f89b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1429,6 +1429,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_feed_channels#other" = "{count} channels"; "lng_info_feed_title" = "Feed Info"; +"lng_info_feed_is_default" = "Group new channels"; +"lng_info_feed_channels" = "Channels"; // Wnd specific diff --git a/Telegram/SourceFiles/info/feed/info_feed_channels.cpp b/Telegram/SourceFiles/info/feed/info_feed_channels.cpp index a03b93c77..bde6ea775 100644 --- a/Telegram/SourceFiles/info/feed/info_feed_channels.cpp +++ b/Telegram/SourceFiles/info/feed/info_feed_channels.cpp @@ -7,8 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/feed/info_feed_channels.h" +#include "info/feed/info_feed_channels_controllers.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_values.h" #include "info/info_controller.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" @@ -16,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/padding_wrap.h" #include "ui/search_field_controller.h" #include "boxes/peer_list_controllers.h" +#include "lang/lang_keys.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -33,7 +36,7 @@ Channels::Channels( : RpWidget(parent) , _controller(controller) , _feed(_controller->key().feed()) -, _listController(std::make_unique()) { +, _listController(std::make_unique(_controller)) { setupHeader(); setupList(); setContent(_list.data()); @@ -44,12 +47,12 @@ Channels::Channels( peerListScrollToTop(); content()->searchQueryChanged(std::move(query)); }, lifetime()); - //MembersCountValue( - // _peer - //) | rpl::start_with_next([this](int count) { - // const auto enabled = (count >= kEnableSearchChannelsAfterCount); - // _controller->setSearchEnabledByContent(enabled); - //}, lifetime()); + Profile::FeedChannelsCountValue( + _feed + ) | rpl::start_with_next([this](int count) { + const auto enabled = (count >= kEnableSearchChannelsAfterCount); + _controller->setSearchEnabledByContent(enabled); + }, lifetime()); } int Channels::desiredHeight() const { @@ -122,12 +125,11 @@ void Channels::setupHeader() { object_ptr Channels::setupTitle() { auto result = object_ptr( _titleWrap, - rpl::single(QString("Contacts")), - //MembersCountValue( - // _peer - //) | rpl::map([](int count) { - // return lng_chat_status_members(lt_count, count); - //}) | ToUpperValue(), + Profile::FeedChannelsCountValue( + _feed + ) | rpl::map([](int count) { + return lng_feed_channels(lt_count, count); + }) | Profile::ToUpperValue(), st::infoBlockHeaderLabel); result->setAttribute(Qt::WA_TransparentForMouseEvents); return result; diff --git a/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp new file mode 100644 index 000000000..24bca2949 --- /dev/null +++ b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp @@ -0,0 +1,110 @@ +/* +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/feed/info_feed_channels_controllers.h" + +#include "data/data_feed.h" +#include "data/data_session.h" +#include "info/info_controller.h" +#include "lang/lang_keys.h" +#include "auth_session.h" +#include "history/history.h" + +namespace Info { +namespace FeedProfile { + +ChannelsController::ChannelsController(not_null controller) +: PeerListController() +, _controller(controller) +, _feed(_controller->key().feed()) { + _controller->setSearchEnabledByContent(false); +} + +std::unique_ptr ChannelsController::createRow( + not_null peer) { + auto result = std::make_unique(peer); + result->setCustomStatus(QString()); + return result; +} + +std::unique_ptr ChannelsController::createRestoredRow( + not_null peer) { + return createRow(peer); +} + +void ChannelsController::prepare() { + setSearchNoResultsText(lang(lng_bot_groups_not_found)); + delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled); + delegate()->peerListSetTitle(langFactory(lng_info_feed_channels)); + + rebuildRows(); + using Flag = Data::FeedUpdateFlag; + rpl::single( + Data::FeedUpdate{ _feed, Flag::Channels } + ) | rpl::then( + Auth().data().feedUpdated() + ) | rpl::filter([=](const Data::FeedUpdate &update) { + return (update.feed == _feed) && (update.flag == Flag::Channels); + }) | rpl::filter([=] { + return _feed->channelsLoaded(); + }) | rpl::start_with_next([=] { + rebuildRows(); + }, lifetime()); +} + +void ChannelsController::rebuildRows() { + if (!_feed->channelsLoaded()) { + return; + } + const auto &channels = _feed->channels(); + auto count = delegate()->peerListFullRowsCount(); + for (auto i = 0; i != count;) { + const auto row = delegate()->peerListRowAt(i); + const auto peer = row->peer(); + if (ranges::find_if(channels, [=](not_null history) { + return (history->peer == peer); + }) != end(channels)) { + ++i; + } else { + delegate()->peerListRemoveRow(row); + --count; + } + } + for (const auto history : channels) { + if (auto row = createRow(history->peer)) { + delegate()->peerListAppendRow(std::move(row)); + } + } +} + +std::unique_ptr ChannelsController::saveState() const { + auto result = PeerListController::saveState(); + auto my = std::make_unique(); + using Flag = Data::FeedUpdateFlag; + Auth().data().feedUpdated( + ) | rpl::filter([=](const Data::FeedUpdate &update) { + return (update.feed == _feed) && (update.flag == Flag::Channels); + }) | rpl::start_with_next([state = result.get()] { + state->controllerState = nullptr; + }, my->lifetime); + result->controllerState = std::move(my); + return result; +} + +void ChannelsController::restoreState( + std::unique_ptr state) { + PeerListController::restoreState(std::move(state)); +} + +void ChannelsController::rowClicked(not_null row) { + _controller->parentController()->showPeerHistory( + row->peer(), + Window::SectionShow::Way::Forward); +} + +} // namespace FeedProfile +} // namespace Info diff --git a/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.h b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.h new file mode 100644 index 000000000..32b3e9490 --- /dev/null +++ b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.h @@ -0,0 +1,51 @@ +/* +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 +*/ +#pragma once + +#include "boxes/peer_list_box.h" + +namespace Data { +class Feed; +} // namespace Data + +namespace Info { + +class Controller; + +namespace FeedProfile { + +class ChannelsController + : public PeerListController + , private base::Subscriber { +public: + ChannelsController(not_null controller); + + void prepare() override; + void rowClicked(not_null row) override; + + std::unique_ptr createRestoredRow( + not_null peer) override; + + std::unique_ptr saveState() const override; + void restoreState(std::unique_ptr state) override; + +private: + struct SavedState : SavedStateBase { + rpl::lifetime lifetime; + }; + + void rebuildRows(); + std::unique_ptr createRow(not_null peer); + + const not_null _controller; + not_null _feed; + +}; + +} // namespace FeedProfile +} // namespace Info diff --git a/Telegram/SourceFiles/info/feed/info_feed_cover.cpp b/Telegram/SourceFiles/info/feed/info_feed_cover.cpp index e06d23e04..0690d380e 100644 --- a/Telegram/SourceFiles/info/feed/info_feed_cover.cpp +++ b/Telegram/SourceFiles/info/feed/info_feed_cover.cpp @@ -42,6 +42,7 @@ Cover::Cover( _name->setSelectable(true); _name->setContextCopyText(lang(lng_profile_copy_fullname)); refreshNameText(); + refreshStatusText(); initViewers(); setupChildGeometry(); @@ -62,7 +63,7 @@ void Cover::setupChildGeometry() { void Cover::initViewers() { Auth().data().feedUpdated( ) | rpl::filter([](const Data::FeedUpdate &update) { - return update.flag == Data::FeedUpdateFlag::Channels; + return (update.flag == Data::FeedUpdateFlag::Channels); }) | rpl::start_with_next( [=] { refreshStatusText(); }, lifetime()); diff --git a/Telegram/SourceFiles/info/feed/info_feed_profile_inner_widget.cpp b/Telegram/SourceFiles/info/feed/info_feed_profile_inner_widget.cpp index 6f3b813fd..2fee32e9b 100644 --- a/Telegram/SourceFiles/info/feed/info_feed_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/feed/info_feed_profile_inner_widget.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/feed/info_feed_profile_widget.h" #include "info/feed/info_feed_cover.h" #include "info/feed/info_feed_channels.h" +#include "info/profile/info_profile_actions.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/vertical_layout.h" @@ -39,32 +40,26 @@ object_ptr InnerWidget::setupContent( _cover = result->add(object_ptr( result, _controller)); - //auto details = SetupDetails(_controller, parent, _peer); - //result->add(std::move(details)); - //if (auto members = SetupChannelMembers(_controller, result.data(), _peer)) { - // result->add(std::move(members)); - //} - //result->add(object_ptr(result)); - //if (auto actions = SetupActions(_controller, result.data(), _peer)) { - // result->add(std::move(actions)); - //} + auto details = Profile::SetupFeedDetails(_controller, parent, _feed); + result->add(std::move(details)); + result->add(object_ptr(result)); - //_channels = result->add(object_ptr( - // result, - // _controller) - //); - //_channels->scrollToRequests( - //) | rpl::start_with_next([this](Ui::ScrollToRequest request) { - // auto min = (request.ymin < 0) - // ? request.ymin - // : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymin })).y(); - // auto max = (request.ymin < 0) - // ? mapFromGlobal(_channels->mapToGlobal({ 0, 0 })).y() - // : (request.ymax < 0) - // ? request.ymax - // : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymax })).y(); - // _scrollToRequests.fire({ min, max }); - //}, _channels->lifetime()); + _channels = result->add(object_ptr( + result, + _controller) + ); + _channels->scrollToRequests( + ) | rpl::start_with_next([this](Ui::ScrollToRequest request) { + auto min = (request.ymin < 0) + ? request.ymin + : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymin })).y(); + auto max = (request.ymin < 0) + ? mapFromGlobal(_channels->mapToGlobal({ 0, 0 })).y() + : (request.ymax < 0) + ? request.ymax + : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymax })).y(); + _scrollToRequests.fire({ min, max }); + }, _channels->lifetime()); return std::move(result); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 49291a7ae..fa4ac4ec7 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -164,6 +164,37 @@ private: }; +class FeedDetailsFiller { +public: + FeedDetailsFiller( + not_null controller, + not_null parent, + not_null feed); + + object_ptr fill(); + +private: + object_ptr setupDefaultToggle(); + + template < + typename Widget, + typename = std::enable_if_t< + std::is_base_of_v>> + Widget *add( + object_ptr &&child, + const style::margins &margin = style::margins()) { + return _wrap->add( + std::move(child), + margin); + } + + not_null _controller; + not_null _parent; + not_null _feed; + object_ptr _wrap; + +}; + DetailsFiller::DetailsFiller( not_null controller, not_null parent, @@ -650,6 +681,42 @@ object_ptr ActionsFiller::fill() { return { nullptr }; } +FeedDetailsFiller::FeedDetailsFiller( + not_null controller, + not_null parent, + not_null feed) +: _controller(controller) +, _parent(parent) +, _feed(feed) +, _wrap(_parent) { +} + +object_ptr FeedDetailsFiller::fill() { + add(object_ptr(_wrap)); + add(CreateSkipWidget(_wrap)); + add(setupDefaultToggle()); + add(CreateSkipWidget(_wrap)); + return std::move(_wrap); +} + +object_ptr FeedDetailsFiller::setupDefaultToggle() { + const auto feed = _feed; + auto result = object_ptr