Add search button to info members header.

This commit is contained in:
John Preston 2017-12-08 12:14:30 +04:00
parent 8f87cfe29d
commit b501af0b8f
11 changed files with 122 additions and 76 deletions

View file

@ -236,10 +236,10 @@ rpl::producer<SelectedItems> ContentWidget::selectedListValue() const {
void ContentWidget::refreshSearchField(bool shown) { void ContentWidget::refreshSearchField(bool shown) {
auto search = _controller->searchFieldController(); auto search = _controller->searchFieldController();
if (search && shown) { if (search && shown) {
_searchField = search->createRowView( _searchWrap = search->createRowView(
this, this,
st::infoLayerMediaSearch); st::infoLayerMediaSearch);
auto field = _searchField.get(); auto field = _searchWrap.get();
widthValue() widthValue()
| rpl::start_with_next([field](int newWidth) { | rpl::start_with_next([field](int newWidth) {
field->resizeToWidth(newWidth); field->resizeToWidth(newWidth);
@ -250,7 +250,7 @@ void ContentWidget::refreshSearchField(bool shown) {
setScrollTopSkip(field->heightNoMargins() - st::lineWidth); setScrollTopSkip(field->heightNoMargins() - st::lineWidth);
} else { } else {
setFocus(); setFocus();
_searchField = nullptr; _searchWrap = nullptr;
setScrollTopSkip(0); setScrollTopSkip(0);
} }
} }

View file

@ -112,7 +112,7 @@ private:
rpl::event_stream<int> _scrollTillBottomChanges; rpl::event_stream<int> _scrollTillBottomChanges;
object_ptr<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
Ui::PaddingWrap<Ui::RpWidget> *_innerWrap = nullptr; Ui::PaddingWrap<Ui::RpWidget> *_innerWrap = nullptr;
base::unique_qptr<Ui::RpWidget> _searchField = nullptr; base::unique_qptr<Ui::RpWidget> _searchWrap = nullptr;
int _innerDesiredHeight = 0; int _innerDesiredHeight = 0;
// Saving here topDelta in setGeometryWithTopMoved() to get it passed to resizeEvent(). // Saving here topDelta in setGeometryWithTopMoved() to get it passed to resizeEvent().
@ -161,6 +161,12 @@ public:
bool searchEnabledByContent() const { bool searchEnabledByContent() const {
return _searchEnabledByContent; return _searchEnabledByContent;
} }
void setSearchStartsFocused(bool focused) {
_searchStartsFocused = focused;
}
bool searchStartsFocused() const {
return _searchStartsFocused;
}
private: private:
const PeerId _peerId = 0; const PeerId _peerId = 0;
@ -168,6 +174,7 @@ private:
int _scrollTop = 0; int _scrollTop = 0;
QString _searchFieldQuery; QString _searchFieldQuery;
bool _searchEnabledByContent = false; bool _searchEnabledByContent = false;
bool _searchStartsFocused = false;
}; };

View file

@ -137,6 +137,7 @@ void Controller::updateSearchControllers(
}, _searchFieldController->lifetime()); }, _searchFieldController->lifetime());
} }
_seachEnabledByContent = memento->searchEnabledByContent(); _seachEnabledByContent = memento->searchEnabledByContent();
_searchStartsFocused = memento->searchStartsFocused();
} else { } else {
_searchFieldController = nullptr; _searchFieldController = nullptr;
} }

View file

@ -112,6 +112,9 @@ public:
int limitBefore, int limitBefore,
int limitAfter) const; int limitAfter) const;
rpl::producer<QString> mediaSourceQueryValue() const; rpl::producer<QString> mediaSourceQueryValue() const;
bool takeSearchStartsFocused() {
return base::take(_searchStartsFocused);
}
void saveSearchState(not_null<ContentMemento*> memento); void saveSearchState(not_null<ContentMemento*> memento);
@ -147,6 +150,7 @@ private:
std::unique_ptr<Ui::SearchFieldController> _searchFieldController; std::unique_ptr<Ui::SearchFieldController> _searchFieldController;
std::unique_ptr<Api::DelayedSearchController> _searchController; std::unique_ptr<Api::DelayedSearchController> _searchController;
rpl::variable<bool> _seachEnabledByContent = false; rpl::variable<bool> _seachEnabledByContent = false;
bool _searchStartsFocused = false;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View file

@ -126,10 +126,20 @@ void TopBar::enableBackButton() {
void TopBar::createSearchView( void TopBar::createSearchView(
not_null<Ui::SearchFieldController*> controller, not_null<Ui::SearchFieldController*> controller,
rpl::producer<bool> &&shown) { rpl::producer<bool> &&shown,
bool startsFocused) {
setSearchField( setSearchField(
controller->createField(this, _st.searchRow.field), 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<Ui::RpWidget> *TopBar::pushButton( Ui::FadeWrap<Ui::RpWidget> *TopBar::pushButton(
@ -157,17 +167,20 @@ Ui::FadeWrap<Ui::RpWidget> *TopBar::pushButton(
void TopBar::setSearchField( void TopBar::setSearchField(
base::unique_qptr<Ui::InputField> field, base::unique_qptr<Ui::InputField> field,
rpl::producer<bool> &&shown) { rpl::producer<bool> &&shown,
if (auto value = field.release()) { bool startsFocused) {
createSearchView(value, std::move(shown)); Expects(field != nullptr);
} else { createSearchView(field.release(), std::move(shown), startsFocused);
_searchView = nullptr; }
}
void TopBar::clearSearchField() {
_searchView = nullptr;
} }
void TopBar::createSearchView( void TopBar::createSearchView(
not_null<Ui::InputField*> field, not_null<Ui::InputField*> field,
rpl::producer<bool> &&shown) { rpl::producer<bool> &&shown,
bool startsFocused) {
_searchView = base::make_unique_q<Ui::FixedHeightWidget>( _searchView = base::make_unique_q<Ui::FixedHeightWidget>(
this, this,
_st.searchRow.height); _st.searchRow.height);
@ -176,6 +189,7 @@ void TopBar::createSearchView(
wrap->setVisible(!selectionMode() && _searchModeAvailable); wrap->setVisible(!selectionMode() && _searchModeAvailable);
}); });
_searchField = field;
auto fieldWrap = Ui::CreateChild<Ui::FadeWrap<Ui::InputField>>( auto fieldWrap = Ui::CreateChild<Ui::FadeWrap<Ui::InputField>>(
wrap, wrap,
object_ptr<Ui::InputField>::fromRaw(field), object_ptr<Ui::InputField>::fromRaw(field),
@ -261,10 +275,10 @@ void TopBar::createSearchView(
| rpl::start_with_done([=] { | rpl::start_with_done([=] {
field->setParent(nullptr); field->setParent(nullptr);
removeButton(search); removeButton(search);
setSearchField(nullptr, rpl::never<bool>()); clearSearchField();
}, _searchView->lifetime()); }, _searchView->lifetime());
_searchModeEnabled = !field->getLastText().isEmpty(); _searchModeEnabled = !field->getLastText().isEmpty() || startsFocused;
updateControlsVisibility(anim::type::instant); updateControlsVisibility(anim::type::instant);
std::move(shown) std::move(shown)

View file

@ -70,7 +70,9 @@ public:
void createSearchView( void createSearchView(
not_null<Ui::SearchFieldController*> controller, not_null<Ui::SearchFieldController*> controller,
rpl::producer<bool> &&shown); rpl::producer<bool> &&shown,
bool startsFocused);
bool focusSearchField();
void setSelectedItems(SelectedItems &&items); void setSelectedItems(SelectedItems &&items);
SelectedItems takeSelectedItems(); SelectedItems takeSelectedItems();
@ -108,10 +110,13 @@ private:
void setSearchField( void setSearchField(
base::unique_qptr<Ui::InputField> field, base::unique_qptr<Ui::InputField> field,
rpl::producer<bool> &&shown); rpl::producer<bool> &&shown,
bool startsFocused);
void clearSearchField();
void createSearchView( void createSearchView(
not_null<Ui::InputField*> field, not_null<Ui::InputField*> field,
rpl::producer<bool> &&shown); rpl::producer<bool> &&shown,
bool startsFocused);
template <typename Callback> template <typename Callback>
void registerUpdateControlCallback(QObject *guard, Callback &&callback); void registerUpdateControlCallback(QObject *guard, Callback &&callback);
@ -129,6 +134,7 @@ private:
bool _searchModeEnabled = false; bool _searchModeEnabled = false;
bool _searchModeAvailable = false; bool _searchModeAvailable = false;
base::unique_qptr<Ui::RpWidget> _searchView; base::unique_qptr<Ui::RpWidget> _searchView;
QPointer<Ui::InputField> _searchField;
rpl::event_stream<> _backClicks; rpl::event_stream<> _backClicks;

View file

@ -347,7 +347,8 @@ void WrapWidget::createTopBar() {
Assert(search != nullptr); Assert(search != nullptr);
_topBar->createSearchView( _topBar->createSearchView(
search, search,
_controller->searchEnabledByContent()); _controller->searchEnabledByContent(),
_controller->takeSearchStartsFocused());
} }
if (_controller->section().type() == Section::Type::Profile if (_controller->section().type() == Section::Type::Profile
&& (wrapValue != Wrap::Side || hasStackHistory())) { && (wrapValue != Wrap::Side || hasStackHistory())) {
@ -669,7 +670,9 @@ void WrapWidget::showAnimatedHook(
} }
void WrapWidget::doSetInnerFocus() { void WrapWidget::doSetInnerFocus() {
_content->setInnerFocus(); if (!_topBar->focusSearchField()) {
_content->setInnerFocus();
}
} }
void WrapWidget::showFinishedHook() { void WrapWidget::showFinishedHook() {
@ -815,6 +818,9 @@ void WrapWidget::showNewContent(
showNewContent(memento); showNewContent(memento);
} }
if (animationParams) { if (animationParams) {
if (Ui::InFocusChain(this)) {
setFocus();
}
showAnimated( showAnimated(
saveToStack saveToStack
? SlideDirection::FromRight ? SlideDirection::FromRight

View file

@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "info/profile/info_profile_members.h" #include "info/profile/info_profile_members.h"
#include "info/info_controller.h" #include "info/info_controller.h"
#include "ui/search_field_controller.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "styles/style_info.h" #include "styles/style_info.h"

View file

@ -25,10 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
struct PeerListState; struct PeerListState;
namespace Ui {
class SearchFieldController;
} // namespace Ui
namespace Info { namespace Info {
namespace Profile { namespace Profile {
class Members; class Members;
@ -43,7 +39,7 @@ class Memento final : public ContentMemento {
public: public:
Memento(not_null<Controller*> controller); Memento(not_null<Controller*> controller);
Memento(PeerId peerId, PeerId migratedPeerId) Memento(PeerId peerId, PeerId migratedPeerId)
: ContentMemento(peerId, migratedPeerId) { : ContentMemento(peerId, migratedPeerId) {
} }
object_ptr<ContentWidget> createWidget( object_ptr<ContentWidget> createWidget(

View file

@ -70,6 +70,11 @@ Members::Members(
peerListScrollToTop(); peerListScrollToTop();
content()->searchQueryChanged(std::move(query)); content()->searchQueryChanged(std::move(query));
}, lifetime()); }, lifetime());
MembersCountValue(_peer)
| rpl::start_with_next([this](int count) {
const auto enabled = (count >= kEnableSearchMembersAfterCount);
_controller->setSearchEnabledByContent(enabled);
});
} }
int Members::desiredHeight() const { int Members::desiredHeight() const {
@ -109,7 +114,7 @@ void Members::restoreState(std::unique_ptr<MembersState> state) {
return; return;
} }
_listController->restoreState(std::move(state->list)); _listController->restoreState(std::move(state->list));
updateSearchEnabledByContent(); //updateSearchEnabledByContent();
//if (!_controller->searchFieldController()->query().isEmpty()) { //if (!_controller->searchFieldController()->query().isEmpty()) {
// if (!_searchShown) { // if (!_searchShown) {
// toggleSearch(anim::type::instant); // toggleSearch(anim::type::instant);
@ -145,9 +150,9 @@ void Members::setupHeader() {
//_searchField = _controller->searchFieldController()->createField( //_searchField = _controller->searchFieldController()->createField(
// parent, // parent,
// st::infoMembersSearchField); // st::infoMembersSearchField);
//_search = Ui::CreateChild<Ui::IconButton>( _search = Ui::CreateChild<Ui::IconButton>(
// parent, _openMembers,
// st::infoMembersSearch); st::infoMembersSearch);
//_cancelSearch = Ui::CreateChild<Ui::CrossButton>( //_cancelSearch = Ui::CreateChild<Ui::CrossButton>(
// parent, // parent,
// st::infoMembersCancelSearch); // st::infoMembersCancelSearch);
@ -182,13 +187,7 @@ void Members::setupButtons() {
using namespace rpl::mappers; using namespace rpl::mappers;
_openMembers->addClickHandler([this] { _openMembers->addClickHandler([this] {
auto contentMemento = std::make_unique<Info::Members::Memento>( showMembersWithSearch(false);
_controller);
contentMemento->setState(saveState());
auto mementoStack = std::vector<std::unique_ptr<ContentMemento>>();
mementoStack.push_back(std::move(contentMemento));
_controller->showSection(
Info::Memento(std::move(mementoStack)));
}); });
//_searchField->hide(); //_searchField->hide();
@ -201,22 +200,21 @@ void Members::setupButtons() {
this->addMember(); this->addMember();
}); });
//auto searchShown = MembersCountValue(_peer) auto searchShown = MembersCountValue(_peer)
// | rpl::map(_1 >= kEnableSearchMembersAfterCount) | rpl::map(_1 >= kEnableSearchMembersAfterCount)
// | rpl::distinct_until_changed() | rpl::distinct_until_changed()
// | rpl::start_spawning(lifetime()); | rpl::start_spawning(lifetime());
//_search->showOn(rpl::duplicate(searchShown)); _search->showOn(rpl::duplicate(searchShown));
//_search->addClickHandler([this] { _search->addClickHandler([this] { // TODO throttle(ripple duration)
// this->showSearch(); this->showMembersWithSearch(true);
//}); });
//_cancelSearch->addClickHandler([this] { //_cancelSearch->addClickHandler([this] {
// this->cancelSearch(); // this->cancelSearch();
//}); //});
//rpl::combine( rpl::combine(
// std::move(addMemberShown), std::move(addMemberShown),
// std::move(searchShown)) std::move(searchShown))
std::move(addMemberShown)
| rpl::start_with_next([this] { | rpl::start_with_next([this] {
updateHeaderControlsGeometry(width()); updateHeaderControlsGeometry(width());
}, lifetime()); }, lifetime());
@ -263,10 +261,10 @@ int Members::resizeGetHeight(int newWidth) {
return heightNoMargins(); return heightNoMargins();
} }
void Members::updateSearchEnabledByContent() { //void Members::updateSearchEnabledByContent() {
_controller->setSearchEnabledByContent( // _controller->setSearchEnabledByContent(
peerListFullRowsCount() >= kEnableSearchMembersAfterCount); // peerListFullRowsCount() >= kEnableSearchMembersAfterCount);
} //}
void Members::updateHeaderControlsGeometry(int newWidth) { void Members::updateHeaderControlsGeometry(int newWidth) {
_openMembers->setGeometry(0, st::infoProfileSkip, newWidth, st::infoMembersHeader - st::infoProfileSkip - st::infoMembersHeaderPaddingBottom); _openMembers->setGeometry(0, st::infoProfileSkip, newWidth, st::infoMembersHeader - st::infoProfileSkip - st::infoMembersHeaderPaddingBottom);
@ -298,6 +296,13 @@ void Members::updateHeaderControlsGeometry(int newWidth) {
availableWidth - _addMember->width(), availableWidth - _addMember->width(),
st::infoMembersButtonPosition.y(), st::infoMembersButtonPosition.y(),
newWidth); newWidth);
if (!_addMember->isHidden()) {
availableWidth -= st::infoMembersSearch.width;
}
_search->moveToLeft(
availableWidth - _search->width(),
st::infoMembersButtonPosition.y(),
newWidth);
//auto fieldLeft = anim::interpolate( //auto fieldLeft = anim::interpolate(
// cancelLeft, // cancelLeft,
@ -341,12 +346,20 @@ void Members::addMember() {
} }
} }
//void Members::showSearch() { void Members::showMembersWithSearch(bool withSearch) {
// if (!_searchShown) { //if (!_searchShown) {
// toggleSearch(); // toggleSearch();
// } //}
//} auto contentMemento = std::make_unique<Info::Members::Memento>(
// _controller);
contentMemento->setState(saveState());
contentMemento->setSearchStartsFocused(withSearch);
auto mementoStack = std::vector<std::unique_ptr<ContentMemento>>();
mementoStack.push_back(std::move(contentMemento));
_controller->showSection(
Info::Memento(std::move(mementoStack)));
}
//void Members::toggleSearch(anim::type animated) { //void Members::toggleSearch(anim::type animated) {
// _searchShown = !_searchShown; // _searchShown = !_searchShown;
// _cancelSearch->toggle(_searchShown, animated); // _cancelSearch->toggle(_searchShown, animated);

View file

@ -91,20 +91,20 @@ private:
void peerListSetDescription( void peerListSetDescription(
object_ptr<Ui::FlatLabel> description) override; object_ptr<Ui::FlatLabel> description) override;
void peerListAppendRow( //void peerListAppendRow(
std::unique_ptr<PeerListRow> row) override { // std::unique_ptr<PeerListRow> row) override {
PeerListContentDelegate::peerListAppendRow(std::move(row)); // PeerListContentDelegate::peerListAppendRow(std::move(row));
updateSearchEnabledByContent(); // updateSearchEnabledByContent();
} //}
void peerListPrependRow( //void peerListPrependRow(
std::unique_ptr<PeerListRow> row) override { // std::unique_ptr<PeerListRow> row) override {
PeerListContentDelegate::peerListPrependRow(std::move(row)); // PeerListContentDelegate::peerListPrependRow(std::move(row));
updateSearchEnabledByContent(); // updateSearchEnabledByContent();
} //}
void peerListRemoveRow(not_null<PeerListRow*> row) override { //void peerListRemoveRow(not_null<PeerListRow*> row) override {
PeerListContentDelegate::peerListRemoveRow(row); // PeerListContentDelegate::peerListRemoveRow(row);
updateSearchEnabledByContent(); // updateSearchEnabledByContent();
} //}
void setupHeader(); void setupHeader();
object_ptr<Ui::FlatLabel> setupTitle(); object_ptr<Ui::FlatLabel> setupTitle();
@ -114,12 +114,12 @@ private:
//void updateSearchOverrides(); //void updateSearchOverrides();
void addMember(); void addMember();
//void showSearch(); void showMembersWithSearch(bool withSearch);
//void toggleSearch(anim::type animated = anim::type::normal); //void toggleSearch(anim::type animated = anim::type::normal);
//void cancelSearch(); //void cancelSearch();
//void searchAnimationCallback(); //void searchAnimationCallback();
void updateHeaderControlsGeometry(int newWidth); void updateHeaderControlsGeometry(int newWidth);
void updateSearchEnabledByContent(); //void updateSearchEnabledByContent();
//Wrap _wrap; //Wrap _wrap;
not_null<Controller*> _controller; not_null<Controller*> _controller;
@ -133,7 +133,7 @@ private:
Ui::FlatLabel *_title = nullptr; Ui::FlatLabel *_title = nullptr;
Ui::IconButton *_addMember = nullptr; Ui::IconButton *_addMember = nullptr;
//base::unique_qptr<Ui::InputField> _searchField; //base::unique_qptr<Ui::InputField> _searchField;
//Ui::IconButton *_search = nullptr; Ui::IconButton *_search = nullptr;
//Ui::CrossButton *_cancelSearch = nullptr; //Ui::CrossButton *_cancelSearch = nullptr;
//Animation _searchShownAnimation; //Animation _searchShownAnimation;