From b501af0b8f0f38b92ad6ea126c5bca308a3ec47e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 8 Dec 2017 12:14:30 +0400 Subject: [PATCH] Add search button to info members header. --- .../SourceFiles/info/info_content_widget.cpp | 6 +- .../SourceFiles/info/info_content_widget.h | 9 ++- Telegram/SourceFiles/info/info_controller.cpp | 1 + Telegram/SourceFiles/info/info_controller.h | 4 + Telegram/SourceFiles/info/info_top_bar.cpp | 36 ++++++--- Telegram/SourceFiles/info/info_top_bar.h | 12 ++- .../SourceFiles/info/info_wrap_widget.cpp | 10 ++- .../info/members/info_members_widget.cpp | 1 - .../info/members/info_members_widget.h | 6 +- .../info/profile/info_profile_members.cpp | 79 +++++++++++-------- .../info/profile/info_profile_members.h | 34 ++++---- 11 files changed, 122 insertions(+), 76 deletions(-) diff --git a/Telegram/SourceFiles/info/info_content_widget.cpp b/Telegram/SourceFiles/info/info_content_widget.cpp index 52df946d9..6ceb39de6 100644 --- a/Telegram/SourceFiles/info/info_content_widget.cpp +++ b/Telegram/SourceFiles/info/info_content_widget.cpp @@ -236,10 +236,10 @@ rpl::producer ContentWidget::selectedListValue() const { void ContentWidget::refreshSearchField(bool shown) { auto search = _controller->searchFieldController(); if (search && shown) { - _searchField = search->createRowView( + _searchWrap = search->createRowView( this, st::infoLayerMediaSearch); - auto field = _searchField.get(); + auto field = _searchWrap.get(); widthValue() | rpl::start_with_next([field](int newWidth) { field->resizeToWidth(newWidth); @@ -250,7 +250,7 @@ void ContentWidget::refreshSearchField(bool shown) { setScrollTopSkip(field->heightNoMargins() - st::lineWidth); } else { setFocus(); - _searchField = nullptr; + _searchWrap = nullptr; setScrollTopSkip(0); } } diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index e37855733..15578bc95 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -112,7 +112,7 @@ private: rpl::event_stream _scrollTillBottomChanges; object_ptr _scroll; Ui::PaddingWrap *_innerWrap = nullptr; - base::unique_qptr _searchField = nullptr; + base::unique_qptr _searchWrap = nullptr; int _innerDesiredHeight = 0; // Saving here topDelta in setGeometryWithTopMoved() to get it passed to resizeEvent(). @@ -161,6 +161,12 @@ public: bool searchEnabledByContent() const { return _searchEnabledByContent; } + void setSearchStartsFocused(bool focused) { + _searchStartsFocused = focused; + } + bool searchStartsFocused() const { + return _searchStartsFocused; + } private: const PeerId _peerId = 0; @@ -168,6 +174,7 @@ private: int _scrollTop = 0; QString _searchFieldQuery; bool _searchEnabledByContent = false; + bool _searchStartsFocused = false; }; diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index aafd96a96..823b0f4ef 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -137,6 +137,7 @@ void Controller::updateSearchControllers( }, _searchFieldController->lifetime()); } _seachEnabledByContent = memento->searchEnabledByContent(); + _searchStartsFocused = memento->searchStartsFocused(); } else { _searchFieldController = nullptr; } diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index 9998b4e42..1973eca8a 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -112,6 +112,9 @@ public: int limitBefore, int limitAfter) const; rpl::producer mediaSourceQueryValue() const; + bool takeSearchStartsFocused() { + return base::take(_searchStartsFocused); + } void saveSearchState(not_null memento); @@ -147,6 +150,7 @@ private: std::unique_ptr _searchFieldController; std::unique_ptr _searchController; rpl::variable _seachEnabledByContent = false; + bool _searchStartsFocused = false; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/info/info_top_bar.cpp b/Telegram/SourceFiles/info/info_top_bar.cpp index acbcd03e0..f42a58b85 100644 --- a/Telegram/SourceFiles/info/info_top_bar.cpp +++ b/Telegram/SourceFiles/info/info_top_bar.cpp @@ -126,10 +126,20 @@ void TopBar::enableBackButton() { void TopBar::createSearchView( not_null controller, - rpl::producer &&shown) { + rpl::producer &&shown, + bool startsFocused) { setSearchField( controller->createField(this, _st.searchRow.field), - std::move(shown)); + std::move(shown), + startsFocused); +} + +bool TopBar::focusSearchField() { + if (_searchField && _searchField->isVisible()) { + _searchField->setFocus(); + return true; + } + return false; } Ui::FadeWrap *TopBar::pushButton( @@ -157,17 +167,20 @@ Ui::FadeWrap *TopBar::pushButton( void TopBar::setSearchField( base::unique_qptr field, - rpl::producer &&shown) { - if (auto value = field.release()) { - createSearchView(value, std::move(shown)); - } else { - _searchView = nullptr; - } + rpl::producer &&shown, + bool startsFocused) { + Expects(field != nullptr); + createSearchView(field.release(), std::move(shown), startsFocused); +} + +void TopBar::clearSearchField() { + _searchView = nullptr; } void TopBar::createSearchView( not_null field, - rpl::producer &&shown) { + rpl::producer &&shown, + bool startsFocused) { _searchView = base::make_unique_q( this, _st.searchRow.height); @@ -176,6 +189,7 @@ void TopBar::createSearchView( wrap->setVisible(!selectionMode() && _searchModeAvailable); }); + _searchField = field; auto fieldWrap = Ui::CreateChild>( wrap, object_ptr::fromRaw(field), @@ -261,10 +275,10 @@ void TopBar::createSearchView( | rpl::start_with_done([=] { field->setParent(nullptr); removeButton(search); - setSearchField(nullptr, rpl::never()); + clearSearchField(); }, _searchView->lifetime()); - _searchModeEnabled = !field->getLastText().isEmpty(); + _searchModeEnabled = !field->getLastText().isEmpty() || startsFocused; updateControlsVisibility(anim::type::instant); std::move(shown) diff --git a/Telegram/SourceFiles/info/info_top_bar.h b/Telegram/SourceFiles/info/info_top_bar.h index 4c9c714cb..fd9d24614 100644 --- a/Telegram/SourceFiles/info/info_top_bar.h +++ b/Telegram/SourceFiles/info/info_top_bar.h @@ -70,7 +70,9 @@ public: void createSearchView( not_null controller, - rpl::producer &&shown); + rpl::producer &&shown, + bool startsFocused); + bool focusSearchField(); void setSelectedItems(SelectedItems &&items); SelectedItems takeSelectedItems(); @@ -108,10 +110,13 @@ private: void setSearchField( base::unique_qptr field, - rpl::producer &&shown); + rpl::producer &&shown, + bool startsFocused); + void clearSearchField(); void createSearchView( not_null field, - rpl::producer &&shown); + rpl::producer &&shown, + bool startsFocused); template void registerUpdateControlCallback(QObject *guard, Callback &&callback); @@ -129,6 +134,7 @@ private: bool _searchModeEnabled = false; bool _searchModeAvailable = false; base::unique_qptr _searchView; + QPointer _searchField; rpl::event_stream<> _backClicks; diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index d54001226..887c12b80 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -347,7 +347,8 @@ void WrapWidget::createTopBar() { Assert(search != nullptr); _topBar->createSearchView( search, - _controller->searchEnabledByContent()); + _controller->searchEnabledByContent(), + _controller->takeSearchStartsFocused()); } if (_controller->section().type() == Section::Type::Profile && (wrapValue != Wrap::Side || hasStackHistory())) { @@ -669,7 +670,9 @@ void WrapWidget::showAnimatedHook( } void WrapWidget::doSetInnerFocus() { - _content->setInnerFocus(); + if (!_topBar->focusSearchField()) { + _content->setInnerFocus(); + } } void WrapWidget::showFinishedHook() { @@ -815,6 +818,9 @@ void WrapWidget::showNewContent( showNewContent(memento); } if (animationParams) { + if (Ui::InFocusChain(this)) { + setFocus(); + } showAnimated( saveToStack ? SlideDirection::FromRight diff --git a/Telegram/SourceFiles/info/members/info_members_widget.cpp b/Telegram/SourceFiles/info/members/info_members_widget.cpp index 8d763b218..e0a22def0 100644 --- a/Telegram/SourceFiles/info/members/info_members_widget.cpp +++ b/Telegram/SourceFiles/info/members/info_members_widget.cpp @@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "info/profile/info_profile_members.h" #include "info/info_controller.h" -#include "ui/search_field_controller.h" #include "ui/widgets/scroll_area.h" #include "styles/style_info.h" diff --git a/Telegram/SourceFiles/info/members/info_members_widget.h b/Telegram/SourceFiles/info/members/info_members_widget.h index 8be617029..4e301bc42 100644 --- a/Telegram/SourceFiles/info/members/info_members_widget.h +++ b/Telegram/SourceFiles/info/members/info_members_widget.h @@ -25,10 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org struct PeerListState; -namespace Ui { -class SearchFieldController; -} // namespace Ui - namespace Info { namespace Profile { class Members; @@ -43,7 +39,7 @@ class Memento final : public ContentMemento { public: Memento(not_null controller); Memento(PeerId peerId, PeerId migratedPeerId) - : ContentMemento(peerId, migratedPeerId) { + : ContentMemento(peerId, migratedPeerId) { } object_ptr createWidget( diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index 11a0d3bb7..b358c9d31 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -70,6 +70,11 @@ Members::Members( peerListScrollToTop(); content()->searchQueryChanged(std::move(query)); }, lifetime()); + MembersCountValue(_peer) + | rpl::start_with_next([this](int count) { + const auto enabled = (count >= kEnableSearchMembersAfterCount); + _controller->setSearchEnabledByContent(enabled); + }); } int Members::desiredHeight() const { @@ -109,7 +114,7 @@ void Members::restoreState(std::unique_ptr state) { return; } _listController->restoreState(std::move(state->list)); - updateSearchEnabledByContent(); + //updateSearchEnabledByContent(); //if (!_controller->searchFieldController()->query().isEmpty()) { // if (!_searchShown) { // toggleSearch(anim::type::instant); @@ -145,9 +150,9 @@ void Members::setupHeader() { //_searchField = _controller->searchFieldController()->createField( // parent, // st::infoMembersSearchField); - //_search = Ui::CreateChild( - // parent, - // st::infoMembersSearch); + _search = Ui::CreateChild( + _openMembers, + st::infoMembersSearch); //_cancelSearch = Ui::CreateChild( // parent, // st::infoMembersCancelSearch); @@ -182,13 +187,7 @@ void Members::setupButtons() { using namespace rpl::mappers; _openMembers->addClickHandler([this] { - auto contentMemento = std::make_unique( - _controller); - contentMemento->setState(saveState()); - auto mementoStack = std::vector>(); - mementoStack.push_back(std::move(contentMemento)); - _controller->showSection( - Info::Memento(std::move(mementoStack))); + showMembersWithSearch(false); }); //_searchField->hide(); @@ -201,22 +200,21 @@ void Members::setupButtons() { this->addMember(); }); - //auto searchShown = MembersCountValue(_peer) - // | rpl::map(_1 >= kEnableSearchMembersAfterCount) - // | rpl::distinct_until_changed() - // | rpl::start_spawning(lifetime()); - //_search->showOn(rpl::duplicate(searchShown)); - //_search->addClickHandler([this] { - // this->showSearch(); - //}); + auto searchShown = MembersCountValue(_peer) + | rpl::map(_1 >= kEnableSearchMembersAfterCount) + | rpl::distinct_until_changed() + | rpl::start_spawning(lifetime()); + _search->showOn(rpl::duplicate(searchShown)); + _search->addClickHandler([this] { // TODO throttle(ripple duration) + this->showMembersWithSearch(true); + }); //_cancelSearch->addClickHandler([this] { // this->cancelSearch(); //}); - //rpl::combine( - // std::move(addMemberShown), - // std::move(searchShown)) - std::move(addMemberShown) + rpl::combine( + std::move(addMemberShown), + std::move(searchShown)) | rpl::start_with_next([this] { updateHeaderControlsGeometry(width()); }, lifetime()); @@ -263,10 +261,10 @@ int Members::resizeGetHeight(int newWidth) { return heightNoMargins(); } -void Members::updateSearchEnabledByContent() { - _controller->setSearchEnabledByContent( - peerListFullRowsCount() >= kEnableSearchMembersAfterCount); -} +//void Members::updateSearchEnabledByContent() { +// _controller->setSearchEnabledByContent( +// peerListFullRowsCount() >= kEnableSearchMembersAfterCount); +//} void Members::updateHeaderControlsGeometry(int newWidth) { _openMembers->setGeometry(0, st::infoProfileSkip, newWidth, st::infoMembersHeader - st::infoProfileSkip - st::infoMembersHeaderPaddingBottom); @@ -298,6 +296,13 @@ void Members::updateHeaderControlsGeometry(int newWidth) { availableWidth - _addMember->width(), st::infoMembersButtonPosition.y(), newWidth); + if (!_addMember->isHidden()) { + availableWidth -= st::infoMembersSearch.width; + } + _search->moveToLeft( + availableWidth - _search->width(), + st::infoMembersButtonPosition.y(), + newWidth); //auto fieldLeft = anim::interpolate( // cancelLeft, @@ -341,12 +346,20 @@ void Members::addMember() { } } -//void Members::showSearch() { -// if (!_searchShown) { -// toggleSearch(); -// } -//} -// +void Members::showMembersWithSearch(bool withSearch) { + //if (!_searchShown) { + // toggleSearch(); + //} + auto contentMemento = std::make_unique( + _controller); + contentMemento->setState(saveState()); + contentMemento->setSearchStartsFocused(withSearch); + auto mementoStack = std::vector>(); + mementoStack.push_back(std::move(contentMemento)); + _controller->showSection( + Info::Memento(std::move(mementoStack))); +} + //void Members::toggleSearch(anim::type animated) { // _searchShown = !_searchShown; // _cancelSearch->toggle(_searchShown, animated); diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.h b/Telegram/SourceFiles/info/profile/info_profile_members.h index 197f2eaa5..64acdd048 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.h +++ b/Telegram/SourceFiles/info/profile/info_profile_members.h @@ -91,20 +91,20 @@ private: void peerListSetDescription( object_ptr description) override; - void peerListAppendRow( - std::unique_ptr row) override { - PeerListContentDelegate::peerListAppendRow(std::move(row)); - updateSearchEnabledByContent(); - } - void peerListPrependRow( - std::unique_ptr row) override { - PeerListContentDelegate::peerListPrependRow(std::move(row)); - updateSearchEnabledByContent(); - } - void peerListRemoveRow(not_null row) override { - PeerListContentDelegate::peerListRemoveRow(row); - updateSearchEnabledByContent(); - } + //void peerListAppendRow( + // std::unique_ptr row) override { + // PeerListContentDelegate::peerListAppendRow(std::move(row)); + // updateSearchEnabledByContent(); + //} + //void peerListPrependRow( + // std::unique_ptr row) override { + // PeerListContentDelegate::peerListPrependRow(std::move(row)); + // updateSearchEnabledByContent(); + //} + //void peerListRemoveRow(not_null row) override { + // PeerListContentDelegate::peerListRemoveRow(row); + // updateSearchEnabledByContent(); + //} void setupHeader(); object_ptr setupTitle(); @@ -114,12 +114,12 @@ private: //void updateSearchOverrides(); void addMember(); - //void showSearch(); + void showMembersWithSearch(bool withSearch); //void toggleSearch(anim::type animated = anim::type::normal); //void cancelSearch(); //void searchAnimationCallback(); void updateHeaderControlsGeometry(int newWidth); - void updateSearchEnabledByContent(); + //void updateSearchEnabledByContent(); //Wrap _wrap; not_null _controller; @@ -133,7 +133,7 @@ private: Ui::FlatLabel *_title = nullptr; Ui::IconButton *_addMember = nullptr; //base::unique_qptr _searchField; - //Ui::IconButton *_search = nullptr; + Ui::IconButton *_search = nullptr; //Ui::CrossButton *_cancelSearch = nullptr; //Animation _searchShownAnimation;