From 583b0fa778af40503d6aaadd5f645ff549a29483 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 10 Oct 2017 21:39:44 +0100 Subject: [PATCH] Display common groups in Info profiles. --- Telegram/SourceFiles/boxes/peer_list_box.cpp | 14 +- Telegram/SourceFiles/boxes/peer_list_box.h | 4 +- .../boxes/peer_list_controllers.cpp | 4 +- .../SourceFiles/boxes/peer_list_controllers.h | 2 +- Telegram/SourceFiles/info/info.style | 16 ++ .../info/info_common_groups_inner_widget.cpp | 176 +++++++++++++++++- .../info/info_common_groups_inner_widget.h | 47 +++-- .../info/info_common_groups_widget.cpp | 5 +- .../info/profile/info_profile_members.cpp | 20 +- Telegram/SourceFiles/ui/widgets/widgets.style | 6 + 10 files changed, 253 insertions(+), 41 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 732b30ad6b..6cd58a2d44 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -340,11 +340,11 @@ void PeerListRow::refreshStatus() { } } -void PeerListRow::refreshName() { +void PeerListRow::refreshName(const style::PeerListItem &st) { if (!_initialized) { return; } - _name.setText(st::contactsNameStyle, peer()->name, _textNameOptions); + _name.setText(st.nameStyle, peer()->name, _textNameOptions); } PeerListRow::~PeerListRow() = default; @@ -457,12 +457,12 @@ float64 PeerListRow::checkedRatio() { return _checkbox ? _checkbox->checkedAnimationRatio() : 0.; } -void PeerListRow::lazyInitialize() { +void PeerListRow::lazyInitialize(const style::PeerListItem &st) { if (_initialized) { return; } _initialized = true; - refreshName(); + refreshName(st); refreshStatus(); } @@ -896,7 +896,7 @@ void PeerListContent::setPressed(Selected pressed) { void PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) { auto row = getRow(index); Assert(row != nullptr); - row->lazyInitialize(); + row->lazyInitialize(_st.item); auto peer = row->peer(); auto user = peer->asUser(); @@ -1066,7 +1066,7 @@ void PeerListContent::loadProfilePhotos() { } void PeerListContent::checkScrollForPreload() { - if (_visibleBottom + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) { + if (_visibleBottom + PreloadHeightsCount * (_visibleBottom - _visibleTop) >= height()) { _controller->loadMoreRows(); } } @@ -1295,7 +1295,7 @@ void PeerListContent::handleNameChanged(const Notify::PeerUpdate &update) { if (addingToSearchIndex()) { addToSearchIndex(row); } - row->refreshName(); + row->refreshName(_st.item); updateRow(row); } } diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index d98c7ded81..8a95fcdede 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -101,7 +101,7 @@ public: virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) { } - void refreshName(); + void refreshName(const style::PeerListItem &st); const Text &name() const { return _name; } @@ -166,7 +166,7 @@ public: return _nameFirstChars; } - virtual void lazyInitialize(); + virtual void lazyInitialize(const style::PeerListItem &st); virtual void paintStatusText( Painter &p, const style::PeerListItem &st, diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 83113261ac..c5e8420958 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -118,8 +118,8 @@ void PeerListRowWithLink::refreshActionLink() { _actionWidth = _action.isEmpty() ? 0 : st::normalFont->width(_action); } -void PeerListRowWithLink::lazyInitialize() { - PeerListRow::lazyInitialize(); +void PeerListRowWithLink::lazyInitialize(const style::PeerListItem &st) { + PeerListRow::lazyInitialize(st); refreshActionLink(); } diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h index de09525809..dc5bc33c1f 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.h +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h @@ -47,7 +47,7 @@ public: void setActionLink(const QString &action); - void lazyInitialize() override; + void lazyInitialize(const style::PeerListItem &st) override; private: void refreshActionLink(); diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 0094646674..9694cbd251 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -352,3 +352,19 @@ infoMediaHeaderPosition: point(14px, 6px); infoMediaSkip: 6px; infoMediaMargin: margins(0px, 6px, 0px, 2px); infoMediaMinGridSize: minPhotoSize; + +infoCommonGroupsMargin: margins(0px, 13px, 0px, 2px); +infoCommonGroupsList: PeerList(infoMembersList) { + item: PeerListItem(defaultPeerListItem) { + height: 52px; + photoSize: 40px; + photoPosition: point(16px, 6px); + namePosition: point(71px, 15px); + nameStyle: TextStyle(defaultTextStyle) { + font: font(14px semibold); + linkFont: font(14px semibold); + linkFontOver: font(14px semibold); + } + statusPosition: point(79px, 31px); + } +} diff --git a/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp b/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp index d46a69e9d9..5a2daf79a6 100644 --- a/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp +++ b/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp @@ -23,20 +23,110 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "info/info_common_groups_widget.h" #include "lang/lang_keys.h" #include "styles/style_info.h" +#include "styles/style_widgets.h" +#include "mtproto/sender.h" +#include "window/window_controller.h" +#include "ui/widgets/scroll_area.h" +#include "apiwrap.h" namespace Info { namespace CommonGroups { +namespace { -InnerWidget::InnerWidget(QWidget *parent, not_null user) -: RpWidget(parent) +constexpr int kCommonGroupsPerPage = 40; + +class Controller + : public PeerListController + , private base::Subscriber + , private MTP::Sender { +public: + Controller( + not_null window, + not_null user); + + void prepare() override; + void rowClicked(not_null row) override; + void loadMoreRows() override; + +private: + not_null _window; + not_null _user; + mtpRequestId _preloadRequestId = 0; + bool _allLoaded = false; + int32 _preloadGroupId = 0; + +}; + +Controller::Controller( + not_null window, + not_null user) +: PeerListController() +, _window(window) , _user(user) { } +void Controller::prepare() { + setSearchNoResultsText(lang(lng_blocked_list_not_found)); + delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled); + delegate()->peerListSetTitle(langFactory(lng_profile_common_groups_section)); +} + +void Controller::loadMoreRows() { + if (_preloadRequestId || _allLoaded) { + return; + } + _preloadRequestId = request(MTPmessages_GetCommonChats( + _user->inputUser, + MTP_int(_preloadGroupId), + MTP_int(kCommonGroupsPerPage) + )).done([this](const MTPmessages_Chats &result) { + _preloadRequestId = 0; + _preloadGroupId = 0; + _allLoaded = true; + if (auto chats = Api::getChatsFromMessagesChats(result)) { + auto &list = chats->v; + if (!list.empty()) { + for_const (auto &chatData, list) { + if (auto chat = App::feedChat(chatData)) { + if (!chat->migrateTo()) { + auto row = std::make_unique(chat); + row->setCustomStatus(QString()); + delegate()->peerListAppendRow(std::move(row)); + } + _preloadGroupId = chat->bareId(); + _allLoaded = false; + } + } + delegate()->peerListRefreshRows(); + } + } + }).send(); +} + +void Controller::rowClicked(not_null row) { + _window->showPeerHistory( + row->peer(), + Window::SectionShow::Way::Forward); +} + +} // namespace + +InnerWidget::InnerWidget( + QWidget *parent, + not_null controller, + not_null user) +: RpWidget(parent) +, _user(user) +, _listController(std::make_unique(controller, _user)) +, _list(setupList(this, _listController.get())) { + setContent(_list.data()); + _listController->setDelegate(static_cast(this)); +} + void InnerWidget::visibleTopBottomUpdated( int visibleTop, int visibleBottom) { - _visibleTop = visibleTop; - _visibleBottom = visibleBottom; + setChildVisibleTopBottom(_list, visibleTop, visibleBottom); } void InnerWidget::saveState(not_null memento) { @@ -45,9 +135,81 @@ void InnerWidget::saveState(not_null memento) { void InnerWidget::restoreState(not_null memento) { } -int InnerWidget::resizeGetHeight(int newWidth) { - auto rowsHeight = _rowsHeightFake; - return qMax(rowsHeight, _minHeight); +int InnerWidget::desiredHeight() const { + auto desired = 0; + auto count = qMax(_user->commonChatsCount(), 1); + desired += qMax(count, _list->fullRowsCount()) + * st::infoCommonGroupsList.item.height; + return qMax(height(), desired); +} + +object_ptr InnerWidget::setupList( + RpWidget *parent, + not_null controller) const { + auto result = object_ptr( + parent, + controller, + st::infoCommonGroupsList); + result->scrollToRequests() + | rpl::start_with_next([this](Ui::ScrollToRequest request) { + auto addmin = (request.ymin < 0) + ? 0 + : st::infoCommonGroupsMargin.top(); + auto addmax = (request.ymax < 0) + ? 0 + : st::infoCommonGroupsMargin.top(); + _scrollToRequests.fire({ + request.ymin + addmin, + request.ymax + addmax }); + }, result->lifetime()); + result->moveToLeft(0, st::infoCommonGroupsMargin.top()); + parent->widthValue() + | rpl::start_with_next([list = result.data()](int newWidth) { + list->resizeToWidth(newWidth); + }, result->lifetime()); + result->heightValue() + | rpl::start_with_next([parent](int listHeight) { + auto newHeight = st::infoCommonGroupsMargin.top() + + listHeight + + st::infoCommonGroupsMargin.bottom(); + parent->resize(parent->width(), newHeight); + }, result->lifetime()); + return result; +} + +void InnerWidget::peerListSetTitle(base::lambda title) { +} + +void InnerWidget::peerListSetAdditionalTitle( + base::lambda title) { +} + +bool InnerWidget::peerListIsRowSelected(not_null peer) { + return false; +} + +int InnerWidget::peerListSelectedRowsCount() { + return 0; +} + +std::vector> InnerWidget::peerListCollectSelectedRows() { + return {}; +} + +void InnerWidget::peerListScrollToTop() { + _scrollToRequests.fire({ -1, -1 }); +} + +void InnerWidget::peerListAddSelectedRowInBunch(not_null peer) { + Unexpected("Item selection in Info::Profile::Members."); +} + +void InnerWidget::peerListFinishSelectedRowsBunch() { +} + +void InnerWidget::peerListSetDescription( + object_ptr description) { + description.destroy(); } } // namespace CommonGroups diff --git a/Telegram/SourceFiles/info/info_common_groups_inner_widget.h b/Telegram/SourceFiles/info/info_common_groups_inner_widget.h index f868ba23a5..f12d835be8 100644 --- a/Telegram/SourceFiles/info/info_common_groups_inner_widget.h +++ b/Telegram/SourceFiles/info/info_common_groups_inner_widget.h @@ -22,41 +22,66 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include #include "ui/rp_widget.h" +#include "boxes/peer_list_box.h" namespace Info { namespace CommonGroups { class Memento; -class InnerWidget final : public Ui::RpWidget { +class InnerWidget final + : public Ui::RpWidget + , private PeerListContentDelegate { public: - InnerWidget(QWidget *parent, not_null user); + InnerWidget( + QWidget *parent, + not_null controller, + not_null user); not_null user() const { return _user; } - void resizeToWidth(int newWidth, int minHeight) { - _minHeight = minHeight; - return RpWidget::resizeToWidth(newWidth); + rpl::producer scrollToRequests() const { + return _scrollToRequests.events(); } + int desiredHeight() const; + void saveState(not_null memento); void restoreState(not_null memento); protected: - int resizeGetHeight(int newWidth) override; void visibleTopBottomUpdated( int visibleTop, int visibleBottom) override; private: - not_null _user; + using ListWidget = PeerListContent; - int _rowsHeightFake = 0; - int _visibleTop = 0; - int _visibleBottom = 0; - int _minHeight = 0; + // PeerListContentDelegate interface. + void peerListSetTitle(base::lambda title) override; + void peerListSetAdditionalTitle( + base::lambda title) override; + bool peerListIsRowSelected(not_null peer) override; + int peerListSelectedRowsCount() override; + std::vector> peerListCollectSelectedRows() override; + void peerListScrollToTop() override; + void peerListAddSelectedRowInBunch( + not_null peer) override; + void peerListFinishSelectedRowsBunch() override; + void peerListSetDescription( + object_ptr description) override; + + object_ptr setupList( + RpWidget *parent, + not_null controller) const; + + not_null _user; + std::unique_ptr _listController; + object_ptr _list; + + rpl::event_stream _scrollToRequests; }; diff --git a/Telegram/SourceFiles/info/info_common_groups_widget.cpp b/Telegram/SourceFiles/info/info_common_groups_widget.cpp index 52e3d137df..eb7a249311 100644 --- a/Telegram/SourceFiles/info/info_common_groups_widget.cpp +++ b/Telegram/SourceFiles/info/info_common_groups_widget.cpp @@ -46,7 +46,10 @@ Widget::Widget( not_null controller, not_null user) : ContentWidget(parent, wrap, controller, user) { - _inner = setInnerWidget(object_ptr(this, user)); + _inner = setInnerWidget(object_ptr( + this, + controller, + user)); } not_null Widget::user() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index d4d739cb0f..6f28edcc7a 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -144,6 +144,16 @@ void Members::setupButtons() { this, st::infoIconMembers, st::infoIconPosition)->lower(); + + connect(_searchField, &Ui::FlatInput::cancelled, this, [this] { + cancelSearch(); + }); + connect(_searchField, &Ui::FlatInput::changed, this, [this] { + applySearch(); + }); + connect(_searchField, &Ui::FlatInput::submitted, this, [this] { + forceSearchSubmit(); + }); } object_ptr Members::setupList( @@ -213,15 +223,6 @@ int Members::resizeGetHeight(int newWidth) { st::infoMembersSearchTop, cancelLeft - fieldLeft, _searchField->height()); - connect(_searchField, &Ui::FlatInput::cancelled, this, [this] { - cancelSearch(); - }); - connect(_searchField, &Ui::FlatInput::changed, this, [this] { - applySearch(); - }); - connect(_searchField, &Ui::FlatInput::submitted, this, [this] { - forceSearchSubmit(); - }); _labelWrap->resize( searchCurrentLeft - st::infoBlockHeaderPosition.x(), @@ -356,7 +357,6 @@ void Members::peerListSetDescription( description.destroy(); } - } // namespace Profile } // namespace Info diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index cc7a845109..44ca33e19f 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -1058,6 +1058,7 @@ PeerListItem { height: pixels; photoPosition: point; namePosition: point; + nameStyle: TextStyle; statusPosition: point; photoSize: pixels; maximalWidth: pixels; @@ -1092,6 +1093,11 @@ defaultPeerListItem: PeerListItem { height: 58px; photoPosition: point(12px, 6px); namePosition: point(68px, 11px); + nameStyle: TextStyle(defaultTextStyle) { + font: semiboldFont; + linkFont: semiboldFont; + linkFontOver: semiboldFont; + } statusPosition: point(68px, 31px); photoSize: 46px; button: defaultPeerListButton;