Better mentions highlighting in PeerListBox.

This commit is contained in:
John Preston 2017-06-16 18:26:19 +03:00
parent 240ced395b
commit b35d2505a4
4 changed files with 48 additions and 52 deletions

View file

@ -317,7 +317,12 @@ std::vector<gsl::not_null<PeerData*>> PeerListBox::peerListCollectSelectedRows()
PeerListRow::PeerListRow(gsl::not_null<PeerData*> peer) : PeerListRow(peer, peer->id) {
}
PeerListRow::PeerListRow(gsl::not_null<PeerData*> peer, PeerListRowId id) : _id(id), _peer(peer) {
PeerListRow::PeerListRow(gsl::not_null<PeerData*> peer, PeerListRowId id)
: _id(id)
, _peer(peer)
, _initialized(false)
, _disabled(false)
, _isSearchResult(false) {
}
bool PeerListRow::checked() const {
@ -591,8 +596,8 @@ PeerListRow *PeerListBox::Inner::findRow(PeerListRowId id) {
void PeerListBox::Inner::removeRow(gsl::not_null<PeerListRow*> row) {
auto index = row->absoluteIndex();
auto isGlobalSearchResult = row->isSearchResult();
auto &eraseFrom = isGlobalSearchResult ? _searchRows : _rows;
auto isSearchResult = row->isSearchResult();
auto &eraseFrom = isSearchResult ? _searchRows : _rows;
t_assert(index >= 0 && index < eraseFrom.size());
t_assert(eraseFrom[index].get() == row);
@ -838,34 +843,25 @@ void PeerListBox::Inner::paintRow(Painter &p, TimeMs ms, RowIndex index) {
}
p.setFont(st::contactsStatusFont);
if (row->isSearchResult() && !peer->userName().isEmpty()) {
if (row->isSearchResult() && !_mentionHighlight.isEmpty() && peer->userName().startsWith(_mentionHighlight, Qt::CaseInsensitive)) {
auto username = peer->userName();
auto mentionHighlight = _searchQuery;
if (mentionHighlight.startsWith('@')) {
mentionHighlight = mentionHighlight.mid(1);
}
if (!mentionHighlight.isEmpty() && username.startsWith(mentionHighlight, Qt::CaseInsensitive)) {
auto availableWidth = width() - namex - st::contactsPadding.right();
auto highlightedPart = '@' + username.mid(0, mentionHighlight.size());
auto grayedPart = username.mid(mentionHighlight.size());
auto highlightedWidth = st::contactsStatusFont->width(highlightedPart);
if (highlightedWidth >= availableWidth || grayedPart.isEmpty()) {
if (highlightedWidth > availableWidth) {
highlightedPart = st::contactsStatusFont->elided(highlightedPart, availableWidth);
}
p.setPen(st::contactsStatusFgOnline);
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), highlightedPart);
} else {
grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth);
auto grayedWidth = st::contactsStatusFont->width(grayedPart);
p.setPen(st::contactsStatusFgOnline);
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), highlightedPart);
p.setPen(selected ? st::contactsStatusFgOver : st::contactsStatusFg);
p.drawTextLeft(namex + highlightedWidth, st::contactsPadding.top() + st::contactsStatusTop, width(), grayedPart);
auto availableWidth = width() - namex - st::contactsPadding.right();
auto highlightedPart = '@' + username.mid(0, _mentionHighlight.size());
auto grayedPart = username.mid(_mentionHighlight.size());
auto highlightedWidth = st::contactsStatusFont->width(highlightedPart);
if (highlightedWidth >= availableWidth || grayedPart.isEmpty()) {
if (highlightedWidth > availableWidth) {
highlightedPart = st::contactsStatusFont->elided(highlightedPart, availableWidth);
}
} else {
p.setPen(st::contactsStatusFgOnline);
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), '@' + username);
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), highlightedPart);
} else {
grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth);
auto grayedWidth = st::contactsStatusFont->width(grayedPart);
p.setPen(st::contactsStatusFgOnline);
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), highlightedPart);
p.setPen(selected ? st::contactsStatusFgOver : st::contactsStatusFg);
p.drawTextLeft(namex + highlightedWidth, st::contactsPadding.top() + st::contactsStatusTop, width(), grayedPart);
}
} else {
row->paintStatusText(p, namex, st::contactsPadding.top() + st::contactsStatusTop, width(), selected);
@ -976,16 +972,9 @@ void PeerListBox::Inner::checkScrollForPreload() {
void PeerListBox::Inner::searchQueryChanged(QString query) {
auto searchWordsList = query.isEmpty() ? QStringList() : query.split(cWordSplit(), QString::SkipEmptyParts);
if (!searchWordsList.isEmpty()) {
query = searchWordsList.join(' ');
}
if (_searchQuery != query) {
setSelected(Selected());
setPressed(Selected());
_searchQuery = query;
_filterResults.clear();
clearSearchRows();
auto normalizedQuery = searchWordsList.isEmpty() ? QString() : searchWordsList.join(' ');
if (_normalizedSearchQuery != normalizedQuery) {
setSearchQuery(query, normalizedQuery);
if (_controller->searchInLocal() && !searchWordsList.isEmpty()) {
auto minimalList = (const std::vector<gsl::not_null<PeerListRow*>>*)nullptr;
for_const (auto &searchWord, searchWordsList) {
@ -1033,6 +1022,16 @@ void PeerListBox::Inner::searchQueryChanged(QString query) {
}
}
void PeerListBox::Inner::setSearchQuery(const QString &query, const QString &normalizedQuery) {
setSelected(Selected());
setPressed(Selected());
_searchQuery = query;
_normalizedSearchQuery = normalizedQuery;
_mentionHighlight = _searchQuery.startsWith('@') ? _searchQuery.mid(1) : _searchQuery;
_filterResults.clear();
clearSearchRows();
}
void PeerListBox::Inner::submitted() {
if (auto row = getRow(_selected.index)) {
_controller->rowClicked(row);

View file

@ -148,16 +148,16 @@ private:
PeerListRowId _id = 0;
gsl::not_null<PeerData*> _peer;
bool _initialized = false;
std::unique_ptr<Ui::RippleAnimation> _ripple;
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
Text _name;
QString _status;
StatusType _statusType = StatusType::Online;
bool _disabled = false;
int _absoluteIndex = -1;
OrderedSet<QChar> _nameFirstChars;
bool _isSearchResult = false;
int _absoluteIndex = -1;
bool _initialized : 1;
bool _disabled : 1;
bool _isSearchResult : 1;
};
@ -476,6 +476,7 @@ private:
void addToSearchIndex(gsl::not_null<PeerListRow*> row);
bool addingToSearchIndex() const;
void removeFromSearchIndex(gsl::not_null<PeerListRow*> row);
void setSearchQuery(const QString &query, const QString &normalizedQuery);
bool showingSearch() const {
return !_searchQuery.isEmpty();
}
@ -508,6 +509,8 @@ private:
std::map<QChar, std::vector<gsl::not_null<PeerListRow*>>> _searchIndex;
QString _searchQuery;
QString _normalizedSearchQuery;
QString _mentionHighlight;
std::vector<gsl::not_null<PeerListRow*>> _filterResults;
object_ptr<Ui::FlatLabel> _description = { nullptr };

View file

@ -502,16 +502,11 @@ AddParticipantBoxController::AddParticipantBoxController(gsl::not_null<ChannelDa
}
}
void AddParticipantBoxController::peerListSearchAddRow(gsl::not_null<PeerData*> peer) {
if (peer->isSelf()) {
return;
}
PeerListController::peerListSearchAddRow(peer);
}
std::unique_ptr<PeerListRow> AddParticipantBoxController::createSearchRow(gsl::not_null<PeerData*> peer) {
if (auto user = peer->asUser()) {
return createRow(user);
if (!peer->isSelf()) {
if (auto user = peer->asUser()) {
return createRow(user);
}
}
return std::unique_ptr<PeerListRow>();
}

View file

@ -139,7 +139,6 @@ public:
void rowClicked(gsl::not_null<PeerListRow*> row) override;
void loadMoreRows() override;
void peerListSearchAddRow(gsl::not_null<PeerData*> peer) override;
std::unique_ptr<PeerListRow> createSearchRow(gsl::not_null<PeerData*> peer) override;
// Callback(gsl::not_null<UserData*>)