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;
constexpr auto kMaxFilterTitleLength = 20;
constexpr auto kMaxFilterTitleLength = 12;
using Flag = Data::ChatFilter::Flag;
using Flags = Data::ChatFilter::Flags;

View File

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

View File

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

View File

@ -74,6 +74,9 @@ void PeerListBox::createMultiSelect() {
searchQueryChanged(query);
});
_select->entity()->setItemRemovedCallback([=](uint64 itemId) {
if (_controller->handleDeselectForeignRow(itemId)) {
return;
}
if (const auto peer = _controller->session().data().peerLoaded(itemId)) {
if (const auto row = peerListFindRow(peer->id)) {
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() {
onScrollToY(0);
}
@ -364,7 +381,9 @@ auto PeerListBox::peerListCollectSelectedRows()
if (!items.empty()) {
result.reserve(items.size());
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;

View File

@ -271,6 +271,7 @@ public:
virtual void peerListConvertRowToSearchResult(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 peerListSetForeignRowChecked(not_null<PeerListRow*> row, bool checked) = 0;
virtual not_null<PeerListRow*> peerListRowAt(int index) = 0;
virtual void peerListRefreshRows() = 0;
virtual void peerListScrollToTop() = 0;
@ -378,6 +379,12 @@ public:
}
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(
QWidget *parent,
not_null<PeerListRow*> row);
@ -715,6 +722,10 @@ public:
bool checked) override {
_content->changeCheckState(row, checked, anim::type::normal);
}
void peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked) override {
}
int peerListFullRowsCount() override {
return _content->fullRowsCount();
}
@ -803,6 +814,9 @@ public:
void peerListSetRowChecked(
not_null<PeerListRow*> row,
bool checked) override;
void peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked) override;
bool peerListIsRowChecked(not_null<PeerListRow*> row) override;
int peerListSelectedRowsCount() override;
std::vector<not_null<PeerData*>> peerListCollectSelectedRows() override;