void PeerListContent::removeRow(not_null<PeerListRow*> row) {
	auto index = row->absoluteIndex();
	auto isSearchResult = row->isSearchResult();
	auto &eraseFrom = isSearchResult ? _searchRows : _rows;

	Assert(index >= 0 && index < eraseFrom.size());
	Assert(eraseFrom[index].get() == row);

	auto pressedData = saveSelectedData(_pressed);
	auto contextedData = saveSelectedData(_contexted);
	setSelected(Selected());
	setPressed(Selected());
	setContexted(Selected());

	_rowsById.erase(row->id());
	auto &byPeer = _rowsByPeer[row->peer()];
	byPeer.erase(ranges::remove(byPeer, row), end(byPeer));
	removeFromSearchIndex(row);
	_filterResults.erase(
		ranges::remove(_filterResults, row),
		end(_filterResults));
	removeRowAtIndex(eraseFrom, index);

	restoreSelection();
	setPressed(restoreSelectedData(pressedData));
	setContexted(restoreSelectedData(contextedData));
}
void PeerListContent::convertRowToSearchResult(not_null<PeerListRow*> row) {
	if (row->isSearchResult()) {
		return;
	} else if (!showingSearch() || !_controller->hasComplexSearch()) {
		return removeRow(row);
	}
	auto index = row->absoluteIndex();
	Assert(index >= 0 && index < _rows.size());
	Assert(_rows[index].get() == row);

	removeFromSearchIndex(row);
	row->setIsSearchResult(true);
	row->setAbsoluteIndex(_searchRows.size());
	_searchRows.push_back(std::move(_rows[index]));
	removeRowAtIndex(_rows, index);
}
void PeerListContent::prependRowFromSearchResult(not_null<PeerListRow*> row) {
	if (!row->isSearchResult()) {
		return;
	}
	Assert(_rowsById.find(row->id()) != _rowsById.cend());
	auto index = row->absoluteIndex();
	Assert(index >= 0 && index < _searchRows.size());
	Assert(_searchRows[index].get() == row);

	row->setIsSearchResult(false);
	_rows.insert(_rows.begin(), std::move(_searchRows[index]));
	refreshIndices();
	removeRowAtIndex(_searchRows, index);

	if (addingToSearchIndex()) {
		addToSearchIndex(row);
	}
}