Show selected chats types in search input.

This commit is contained in:
John Preston 2020-03-13 18:44:25 +04:00
parent b88f0108ad
commit 9636617798
5 changed files with 87 additions and 10 deletions

View File

@ -30,7 +30,7 @@ namespace {
using namespace Settings; using namespace Settings;
constexpr auto kMaxFilterTitleLength = 20; constexpr auto kMaxFilterTitleLength = 12;
using Flag = Data::ChatFilter::Flag; using Flag = Data::ChatFilter::Flag;
using Flags = Data::ChatFilter::Flags; using Flags = Data::ChatFilter::Flags;

View File

@ -33,6 +33,11 @@ constexpr auto kAllTypes = {
Flag::NoRead Flag::NoRead
}; };
struct RowSelectionChange {
not_null<PeerListRow*> row;
bool checked = false;
};
class TypeRow final : public PeerListRow { class TypeRow final : public PeerListRow {
public: public:
explicit TypeRow(Flag flag); explicit TypeRow(Flag flag);
@ -79,7 +84,9 @@ public:
void prepare() override; void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
[[nodiscard]] rpl::producer<Flags> selectedOptions() const; [[nodiscard]] rpl::producer<Flags> selectedChanges() const;
[[nodiscard]] auto rowSelectionChanges() const
-> rpl::producer<RowSelectionChange>;
private: private:
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(Flag flag) const; [[nodiscard]] std::unique_ptr<PeerListRow> createRow(Flag flag) const;
@ -89,6 +96,7 @@ private:
Flags _options; Flags _options;
rpl::event_stream<> _selectionChanged; rpl::event_stream<> _selectionChanged;
rpl::event_stream<RowSelectionChange> _rowSelectionChanges;
}; };
@ -221,22 +229,27 @@ Flags TypeController::collectSelectedOptions() const {
} }
void TypeController::rowClicked(not_null<PeerListRow*> row) { void TypeController::rowClicked(not_null<PeerListRow*> row) {
delegate()->peerListSetRowChecked(row, !row->checked()); const auto checked = !row->checked();
_selectionChanged.fire({}); delegate()->peerListSetRowChecked(row, checked);
_rowSelectionChanges.fire({ row, checked });
} }
std::unique_ptr<PeerListRow> TypeController::createRow(Flag flag) const { std::unique_ptr<PeerListRow> TypeController::createRow(Flag flag) const {
return std::make_unique<TypeRow>(flag); return std::make_unique<TypeRow>(flag);
} }
rpl::producer<Flags> TypeController::selectedOptions() const { rpl::producer<Flags> TypeController::selectedChanges() const {
return _selectionChanged.events_starting_with( return _rowSelectionChanges.events(
{}
) | rpl::map([=] { ) | rpl::map([=] {
return collectSelectedOptions(); return collectSelectedOptions();
}); });
} }
auto TypeController::rowSelectionChanges() const
-> rpl::producer<RowSelectionChange> {
return _rowSelectionChanges.events();
}
} // namespace } // namespace
[[nodiscard]] QString FilterChatsTypeName(Flag flag) { [[nodiscard]] QString FilterChatsTypeName(Flag flag) {
@ -326,11 +339,24 @@ void EditFilterChatsListController::itemDeselectedHook(
updateTitle(); updateTitle();
} }
bool EditFilterChatsListController::isForeignRow(PeerListRowId itemId) {
return ranges::contains(kAllTypes, itemId, TypeId);
}
bool EditFilterChatsListController::handleDeselectForeignRow(
PeerListRowId itemId) {
if (isForeignRow(itemId)) {
_deselectOption(itemId);
return true;
}
return false;
}
void EditFilterChatsListController::prepareViewHook() { void EditFilterChatsListController::prepareViewHook() {
delegate()->peerListSetTitle(std::move(_title)); delegate()->peerListSetTitle(std::move(_title));
delegate()->peerListSetAboveWidget(prepareTypesList());
delegate()->peerListAddSelectedPeers( delegate()->peerListAddSelectedPeers(
_peers | ranges::view::transform(&History::peer)); _peers | ranges::view::transform(&History::peer));
delegate()->peerListSetAboveWidget(prepareTypesList());
} }
object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() { object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
@ -354,6 +380,7 @@ object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
if (_selected & flag) { if (_selected & flag) {
if (const auto row = delegate->peerListFindRow(TypeId(flag))) { if (const auto row = delegate->peerListFindRow(TypeId(flag))) {
content->changeCheckState(row, true, anim::type::instant); content->changeCheckState(row, true, anim::type::instant);
this->delegate()->peerListSetForeignRowChecked(row, true);
} }
} }
} }
@ -361,11 +388,24 @@ object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
container, container,
tr::lng_filters_edit_chats())); tr::lng_filters_edit_chats()));
controller->selectedOptions( controller->selectedChanges(
) | rpl::start_with_next([=](Flags selected) { ) | rpl::start_with_next([=](Flags selected) {
_selected = selected; _selected = selected;
}, _lifetime); }, _lifetime);
controller->rowSelectionChanges(
) | rpl::start_with_next([=](RowSelectionChange update) {
this->delegate()->peerListSetForeignRowChecked(
update.row,
update.checked);
}, _lifetime);
_deselectOption = [=](PeerListRowId itemId) {
if (const auto row = delegate->peerListFindRow(itemId)) {
delegate->peerListSetRowChecked(row, false);
}
};
return result; return result;
} }

View File

@ -54,6 +54,8 @@ public:
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
void itemDeselectedHook(not_null<PeerData*> peer) override; void itemDeselectedHook(not_null<PeerData*> peer) override;
bool isForeignRow(PeerListRowId itemId) override;
bool handleDeselectForeignRow(PeerListRowId itemId) override;
private: private:
void prepareViewHook() override; void prepareViewHook() override;
@ -68,6 +70,8 @@ private:
Flags _options; Flags _options;
Flags _selected; Flags _selected;
Fn<void(PeerListRowId)> _deselectOption;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };

View File

@ -74,6 +74,9 @@ void PeerListBox::createMultiSelect() {
searchQueryChanged(query); searchQueryChanged(query);
}); });
_select->entity()->setItemRemovedCallback([=](uint64 itemId) { _select->entity()->setItemRemovedCallback([=](uint64 itemId) {
if (_controller->handleDeselectForeignRow(itemId)) {
return;
}
if (const auto peer = _controller->session().data().peerLoaded(itemId)) { if (const auto peer = _controller->session().data().peerLoaded(itemId)) {
if (const auto row = peerListFindRow(peer->id)) { if (const auto row = peerListFindRow(peer->id)) {
content()->changeCheckState(row, false, anim::type::normal); content()->changeCheckState(row, false, anim::type::normal);
@ -198,6 +201,20 @@ void PeerListBox::peerListSetRowChecked(
} }
} }
void PeerListBox::peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked) {
if (checked) {
addSelectItem(row, anim::type::normal);
// This call deletes row from _searchRows.
_select->entity()->clearQuery();
} else {
// The itemRemovedCallback will call changeCheckState() here.
_select->entity()->removeItem(row->id());
}
}
void PeerListBox::peerListScrollToTop() { void PeerListBox::peerListScrollToTop() {
onScrollToY(0); onScrollToY(0);
} }
@ -364,7 +381,9 @@ auto PeerListBox::peerListCollectSelectedRows()
if (!items.empty()) { if (!items.empty()) {
result.reserve(items.size()); result.reserve(items.size());
for (const auto itemId : items) { for (const auto itemId : items) {
result.push_back(_controller->session().data().peer(itemId)); if (!_controller->isForeignRow(itemId)) {
result.push_back(_controller->session().data().peer(itemId));
}
} }
} }
return result; return result;

View File

@ -271,6 +271,7 @@ public:
virtual void peerListConvertRowToSearchResult(not_null<PeerListRow*> row) = 0; virtual void peerListConvertRowToSearchResult(not_null<PeerListRow*> row) = 0;
virtual bool peerListIsRowChecked(not_null<PeerListRow*> row) = 0; virtual bool peerListIsRowChecked(not_null<PeerListRow*> row) = 0;
virtual void peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) = 0; virtual void peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) = 0;
virtual void peerListSetForeignRowChecked(not_null<PeerListRow*> row, bool checked) = 0;
virtual not_null<PeerListRow*> peerListRowAt(int index) = 0; virtual not_null<PeerListRow*> peerListRowAt(int index) = 0;
virtual void peerListRefreshRows() = 0; virtual void peerListRefreshRows() = 0;
virtual void peerListScrollToTop() = 0; virtual void peerListScrollToTop() = 0;
@ -378,6 +379,12 @@ public:
} }
virtual void itemDeselectedHook(not_null<PeerData*> peer) { virtual void itemDeselectedHook(not_null<PeerData*> peer) {
} }
virtual bool isForeignRow(PeerListRowId itemId) {
return false;
}
virtual bool handleDeselectForeignRow(PeerListRowId itemId) {
return false;
}
virtual base::unique_qptr<Ui::PopupMenu> rowContextMenu( virtual base::unique_qptr<Ui::PopupMenu> rowContextMenu(
QWidget *parent, QWidget *parent,
not_null<PeerListRow*> row); not_null<PeerListRow*> row);
@ -715,6 +722,10 @@ public:
bool checked) override { bool checked) override {
_content->changeCheckState(row, checked, anim::type::normal); _content->changeCheckState(row, checked, anim::type::normal);
} }
void peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked) override {
}
int peerListFullRowsCount() override { int peerListFullRowsCount() override {
return _content->fullRowsCount(); return _content->fullRowsCount();
} }
@ -803,6 +814,9 @@ public:
void peerListSetRowChecked( void peerListSetRowChecked(
not_null<PeerListRow*> row, not_null<PeerListRow*> row,
bool checked) override; bool checked) override;
void peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked) override;
bool peerListIsRowChecked(not_null<PeerListRow*> row) override; bool peerListIsRowChecked(not_null<PeerListRow*> row) override;
int peerListSelectedRowsCount() override; int peerListSelectedRowsCount() override;
std::vector<not_null<PeerData*>> peerListCollectSelectedRows() override; std::vector<not_null<PeerData*>> peerListCollectSelectedRows() override;