mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
ShareBox: keyboard handle, animated scroll, chosen items jump to top.
This commit is contained in:
parent
52a7ed77ba
commit
34331f558f
7 changed files with 174 additions and 90 deletions
|
@ -109,3 +109,4 @@ shareNameTop: 6px;
|
||||||
shareColumnSkip: 6px;
|
shareColumnSkip: 6px;
|
||||||
shareSelectDuration: 150;
|
shareSelectDuration: 150;
|
||||||
shareActivateDuration: 150;
|
shareActivateDuration: 150;
|
||||||
|
shareScrollDuration: 300;
|
||||||
|
|
|
@ -42,13 +42,14 @@ ShareBox::ShareBox(SubmitCallback &&callback) : ItemListBox(st::boxScroll)
|
||||||
init(_inner, bottomSkip, topSkip);
|
init(_inner, bottomSkip, topSkip);
|
||||||
|
|
||||||
connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged()));
|
connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged()));
|
||||||
|
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
|
||||||
connect(_share, SIGNAL(clicked()), this, SLOT(onShare()));
|
connect(_share, SIGNAL(clicked()), this, SLOT(onShare()));
|
||||||
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
|
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||||
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
|
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
|
||||||
// connect(_filter, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
connect(_filter, SIGNAL(submitted(bool)), _inner, SLOT(onSelectActive()));
|
||||||
connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
|
connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
|
||||||
connect(_inner, SIGNAL(selectAllQuery()), _filter, SLOT(selectAll()));
|
connect(_inner, SIGNAL(filterCancel()), this, SLOT(onFilterCancel()));
|
||||||
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||||
|
|
||||||
_filterCancel->setAttribute(Qt::WA_OpaquePaintEvent);
|
_filterCancel->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
@ -149,6 +150,24 @@ void ShareBox::resizeEvent(QResizeEvent *e) {
|
||||||
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
|
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShareBox::keyPressEvent(QKeyEvent *e) {
|
||||||
|
if (_filter->hasFocus()) {
|
||||||
|
if (e->key() == Qt::Key_Up) {
|
||||||
|
_inner->activateSkipColumn(-1);
|
||||||
|
} else if (e->key() == Qt::Key_Down) {
|
||||||
|
_inner->activateSkipColumn(1);
|
||||||
|
} else if (e->key() == Qt::Key_PageUp) {
|
||||||
|
_inner->activateSkipPage(scrollArea()->height(), -1);
|
||||||
|
} else if (e->key() == Qt::Key_PageDown) {
|
||||||
|
_inner->activateSkipPage(scrollArea()->height(), 1);
|
||||||
|
} else {
|
||||||
|
ItemListBox::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ItemListBox::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShareBox::moveButtons() {
|
void ShareBox::moveButtons() {
|
||||||
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height());
|
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height());
|
||||||
auto cancelRight = st::boxButtonPadding.right();
|
auto cancelRight = st::boxButtonPadding.right();
|
||||||
|
@ -163,7 +182,6 @@ void ShareBox::onFilterCancel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onFilterUpdate() {
|
void ShareBox::onFilterUpdate() {
|
||||||
scrollArea()->scrollToY(0);
|
|
||||||
_filterCancel->setVisible(!_filter->getLastText().isEmpty());
|
_filterCancel->setVisible(!_filter->getLastText().isEmpty());
|
||||||
_inner->updateFilter(_filter->getLastText());
|
_inner->updateFilter(_filter->getLastText());
|
||||||
}
|
}
|
||||||
|
@ -180,6 +198,21 @@ void ShareBox::onSelectedChanged() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShareBox::onMustScrollTo(int top, int bottom) {
|
||||||
|
auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
|
||||||
|
auto from = scrollTop, to = scrollTop;
|
||||||
|
if (scrollTop > top) {
|
||||||
|
to = top;
|
||||||
|
} else if (scrollBottom < bottom) {
|
||||||
|
to = bottom - (scrollBottom - scrollTop);
|
||||||
|
}
|
||||||
|
if (from != to) {
|
||||||
|
START_ANIMATION(_scrollAnimation, func([this]() {
|
||||||
|
scrollArea()->scrollToY(_scrollAnimation.current(scrollArea()->scrollTop()));
|
||||||
|
}), from, to, st::shareScrollDuration, anim::sineInOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShareBox::onScroll() {
|
void ShareBox::onScroll() {
|
||||||
auto scroll = scrollArea();
|
auto scroll = scrollArea();
|
||||||
auto scrollTop = scroll->scrollTop();
|
auto scrollTop = scroll->scrollTop();
|
||||||
|
@ -218,6 +251,36 @@ void ShareInner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||||
loadProfilePhotos(visibleTop);
|
loadProfilePhotos(visibleTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShareInner::activateSkipRow(int direction) {
|
||||||
|
activateSkipColumn(direction * _columnCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ShareInner::displayedChatsCount() const {
|
||||||
|
return _filter.isEmpty() ? _chatsIndexed->size() : (_filtered.size() + d_byUsernameFiltered.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShareInner::activateSkipColumn(int direction) {
|
||||||
|
if (_active < 0) {
|
||||||
|
if (direction > 0) {
|
||||||
|
setActive(0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto count = displayedChatsCount();
|
||||||
|
auto active = _active + direction;
|
||||||
|
if (active < 0) {
|
||||||
|
active = (_active > 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
if (active >= count) {
|
||||||
|
active = count - 1;
|
||||||
|
}
|
||||||
|
setActive(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShareInner::activateSkipPage(int pageHeight, int direction) {
|
||||||
|
activateSkipRow(direction * (pageHeight / _rowHeight));
|
||||||
|
}
|
||||||
|
|
||||||
void ShareInner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
void ShareInner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
||||||
if (update.flags & Notify::PeerUpdate::Flag::NameChanged) {
|
if (update.flags & Notify::PeerUpdate::Flag::NameChanged) {
|
||||||
_chatsIndexed->peerNameChanged(update.peer, update.oldNames, update.oldNameFirstChars);
|
_chatsIndexed->peerNameChanged(update.peer, update.oldNames, update.oldNameFirstChars);
|
||||||
|
@ -247,12 +310,22 @@ void ShareInner::repaintChatAtIndex(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareInner::Chat *ShareInner::getChatAtIndex(int index) {
|
ShareInner::Chat *ShareInner::getChatAtIndex(int index) {
|
||||||
|
if (index < 0) return nullptr;
|
||||||
auto row = ([this, index]() -> Dialogs::Row* {
|
auto row = ([this, index]() -> Dialogs::Row* {
|
||||||
if (index < 0) return nullptr;
|
|
||||||
if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1);
|
if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1);
|
||||||
return (index < _filtered.size()) ? _filtered[index] : nullptr;
|
return (index < _filtered.size()) ? _filtered[index] : nullptr;
|
||||||
})();
|
})();
|
||||||
return row ? static_cast<Chat*>(row->attached) : nullptr;
|
if (row) {
|
||||||
|
return static_cast<Chat*>(row->attached);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_filter.isEmpty()) {
|
||||||
|
index -= _filtered.size();
|
||||||
|
if (index >= 0 && index < d_byUsernameFiltered.size()) {
|
||||||
|
return d_byUsernameFiltered[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareInner::repaintChat(PeerData *peer) {
|
void ShareInner::repaintChat(PeerData *peer) {
|
||||||
|
@ -275,6 +348,12 @@ int ShareInner::chatIndex(PeerData *peer) const {
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
for_const (auto row, d_byUsernameFiltered) {
|
||||||
|
if (row->peer == peer) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -347,6 +426,8 @@ void ShareInner::setActive(int active) {
|
||||||
_active = active;
|
_active = active;
|
||||||
changeNameFg(_active, st::shareNameFg, st::shareNameActiveFg);
|
changeNameFg(_active, st::shareNameFg, st::shareNameActiveFg);
|
||||||
}
|
}
|
||||||
|
auto y = (_active < _columnCount) ? 0 : (_rowsTop + ((_active / _columnCount) * _rowHeight));
|
||||||
|
emit mustScrollTo(y, y + _rowHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
|
void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
|
||||||
|
@ -441,28 +522,14 @@ void ShareInner::paintEvent(QPaintEvent *e) {
|
||||||
auto indexFrom = rowFrom * _columnCount;
|
auto indexFrom = rowFrom * _columnCount;
|
||||||
auto indexTo = rowTo * _columnCount;
|
auto indexTo = rowTo * _columnCount;
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
if (!_chatsIndexed->isEmpty() || !_byUsername.isEmpty()) {
|
if (!_chatsIndexed->isEmpty()) {
|
||||||
if (!_chatsIndexed->isEmpty()) {
|
auto i = _chatsIndexed->cfind(indexFrom, 1);
|
||||||
auto i = _chatsIndexed->cfind(indexFrom, 1);
|
for (auto end = _chatsIndexed->cend(); i != end; ++i) {
|
||||||
for (auto end = _chatsIndexed->cend(); i != end; ++i) {
|
if (indexFrom >= indexTo) {
|
||||||
if (indexFrom >= indexTo) {
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
paintChat(p, getChat(*i), indexFrom);
|
|
||||||
++indexFrom;
|
|
||||||
}
|
|
||||||
indexFrom -= _chatsIndexed->size();
|
|
||||||
indexTo -= _chatsIndexed->size();
|
|
||||||
}
|
|
||||||
if (!_byUsername.isEmpty()) {
|
|
||||||
if (indexFrom < 0) indexFrom = 0;
|
|
||||||
while (indexFrom < indexTo) {
|
|
||||||
if (indexFrom >= d_byUsername.size()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
paintChat(p, d_byUsername[indexFrom], indexFrom);
|
|
||||||
++indexFrom;
|
|
||||||
}
|
}
|
||||||
|
paintChat(p, getChat(*i), indexFrom);
|
||||||
|
++indexFrom;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// empty
|
// empty
|
||||||
|
@ -475,7 +542,8 @@ void ShareInner::paintEvent(QPaintEvent *e) {
|
||||||
p.setFont(st::noContactsFont);
|
p.setFont(st::noContactsFont);
|
||||||
p.setPen(st::noContactsColor);
|
p.setPen(st::noContactsColor);
|
||||||
} else {
|
} else {
|
||||||
if (!_filtered.isEmpty()) {
|
auto filteredSize = _filtered.size();
|
||||||
|
if (filteredSize) {
|
||||||
if (indexFrom < 0) indexFrom = 0;
|
if (indexFrom < 0) indexFrom = 0;
|
||||||
while (indexFrom < indexTo) {
|
while (indexFrom < indexTo) {
|
||||||
if (indexFrom >= _filtered.size()) {
|
if (indexFrom >= _filtered.size()) {
|
||||||
|
@ -484,8 +552,8 @@ void ShareInner::paintEvent(QPaintEvent *e) {
|
||||||
paintChat(p, getChat(_filtered[indexFrom]), indexFrom);
|
paintChat(p, getChat(_filtered[indexFrom]), indexFrom);
|
||||||
++indexFrom;
|
++indexFrom;
|
||||||
}
|
}
|
||||||
indexFrom -= _filtered.size();
|
indexFrom -= filteredSize;
|
||||||
indexTo -= _filtered.size();
|
indexTo -= filteredSize;
|
||||||
}
|
}
|
||||||
if (!_byUsernameFiltered.isEmpty()) {
|
if (!_byUsernameFiltered.isEmpty()) {
|
||||||
if (indexFrom < 0) indexFrom = 0;
|
if (indexFrom < 0) indexFrom = 0;
|
||||||
|
@ -493,7 +561,7 @@ void ShareInner::paintEvent(QPaintEvent *e) {
|
||||||
if (indexFrom >= d_byUsernameFiltered.size()) {
|
if (indexFrom >= d_byUsernameFiltered.size()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
paintChat(p, d_byUsernameFiltered[indexFrom], indexFrom);
|
paintChat(p, d_byUsernameFiltered[indexFrom], filteredSize + indexFrom);
|
||||||
++indexFrom;
|
++indexFrom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,8 +591,7 @@ void ShareInner::updateUpon(const QPoint &pos) {
|
||||||
auto xupon = (x >= left) && (x < left + (_rowWidth - st::shareColumnSkip));
|
auto xupon = (x >= left) && (x < left + (_rowWidth - st::shareColumnSkip));
|
||||||
auto yupon = (y >= top) && (y < top + st::sharePhotoRadius * 2 + st::shareNameTop + st::shareNameFont->height * 2);
|
auto yupon = (y >= top) && (y < top + st::sharePhotoRadius * 2 + st::shareNameTop + st::shareNameFont->height * 2);
|
||||||
auto upon = (xupon && yupon) ? (row * _columnCount + column) : -1;
|
auto upon = (xupon && yupon) ? (row * _columnCount + column) : -1;
|
||||||
auto count = _filter.isEmpty() ? (_chatsIndexed->size() + d_byUsername.size()) : (_filtered.size() + d_byUsernameFiltered.size());
|
if (upon >= displayedChatsCount()) {
|
||||||
if (upon >= count) {
|
|
||||||
upon = -1;
|
upon = -1;
|
||||||
}
|
}
|
||||||
_upon = upon;
|
_upon = upon;
|
||||||
|
@ -533,12 +600,14 @@ void ShareInner::updateUpon(const QPoint &pos) {
|
||||||
void ShareInner::mousePressEvent(QMouseEvent *e) {
|
void ShareInner::mousePressEvent(QMouseEvent *e) {
|
||||||
if (e->button() == Qt::LeftButton) {
|
if (e->button() == Qt::LeftButton) {
|
||||||
updateUpon(e->pos());
|
updateUpon(e->pos());
|
||||||
if (_upon >= 0) {
|
changeCheckState(getChatAtIndex(_upon));
|
||||||
changeCheckState(getChatAtIndex(_upon));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShareInner::onSelectActive() {
|
||||||
|
changeCheckState(getChatAtIndex(_active > 0 ? _active : 0));
|
||||||
|
}
|
||||||
|
|
||||||
void ShareInner::resizeEvent(QResizeEvent *e) {
|
void ShareInner::resizeEvent(QResizeEvent *e) {
|
||||||
_columnSkip = (width() - _columnCount * st::sharePhotoRadius * 2) / float64(_columnCount + 1);
|
_columnSkip = (width() - _columnCount * st::sharePhotoRadius * 2) / float64(_columnCount + 1);
|
||||||
_rowWidthReal = st::sharePhotoRadius * 2 + _columnSkip;
|
_rowWidthReal = st::sharePhotoRadius * 2 + _columnSkip;
|
||||||
|
@ -563,6 +632,20 @@ float64 anim_bumpy(const float64 &delta, const float64 &dt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareInner::changeCheckState(Chat *chat) {
|
void ShareInner::changeCheckState(Chat *chat) {
|
||||||
|
if (!chat) return;
|
||||||
|
|
||||||
|
if (!_filter.isEmpty()) {
|
||||||
|
auto row = _chatsIndexed->getRow(chat->peer->id);
|
||||||
|
if (!row) {
|
||||||
|
row = _chatsIndexed->addToEnd(App::history(chat->peer)).value(0);
|
||||||
|
}
|
||||||
|
chat = getChat(row);
|
||||||
|
if (!chat->selected) {
|
||||||
|
_chatsIndexed->moveToTop(chat->peer);
|
||||||
|
}
|
||||||
|
emit filterCancel();
|
||||||
|
}
|
||||||
|
|
||||||
chat->selected = !chat->selected;
|
chat->selected = !chat->selected;
|
||||||
if (chat->selected) {
|
if (chat->selected) {
|
||||||
_selected.insert(chat->peer);
|
_selected.insert(chat->peer);
|
||||||
|
@ -582,7 +665,9 @@ void ShareInner::changeCheckState(Chat *chat) {
|
||||||
START_ANIMATION(chat->selection, func([this, chat] {
|
START_ANIMATION(chat->selection, func([this, chat] {
|
||||||
repaintChat(chat->peer);
|
repaintChat(chat->peer);
|
||||||
}), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy);
|
}), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy);
|
||||||
setActive(chatIndex(chat->peer));
|
if (chat->selected) {
|
||||||
|
setActive(chatIndex(chat->peer));
|
||||||
|
}
|
||||||
emit selectedChanged();
|
emit selectedChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,11 +769,10 @@ void ShareInner::updateFilter(QString filter) {
|
||||||
_filter = filter;
|
_filter = filter;
|
||||||
|
|
||||||
_byUsernameFiltered.clear();
|
_byUsernameFiltered.clear();
|
||||||
d_byUsernameFiltered.clear();
|
for (int i = 0, l = d_byUsernameFiltered.size(); i < l; ++i) {
|
||||||
for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) {
|
delete d_byUsernameFiltered[i];
|
||||||
delete _byUsernameDatas[i];
|
|
||||||
}
|
}
|
||||||
_byUsernameDatas.clear();
|
d_byUsernameFiltered.clear();
|
||||||
|
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -731,34 +815,13 @@ void ShareInner::updateFilter(QString filter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_byUsernameFiltered.reserve(_byUsername.size());
|
|
||||||
d_byUsernameFiltered.reserve(d_byUsername.size());
|
|
||||||
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
|
|
||||||
auto &names = _byUsername[i]->names;
|
|
||||||
PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni;
|
|
||||||
for (fi = fb; fi != fe; ++fi) {
|
|
||||||
auto filterName = *fi;
|
|
||||||
for (ni = nb; ni != ne; ++ni) {
|
|
||||||
if (ni->startsWith(*fi)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ni == ne) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fi == fe) {
|
|
||||||
_byUsernameFiltered.push_back(_byUsername[i]);
|
|
||||||
d_byUsernameFiltered.push_back(d_byUsername[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
_searching = true;
|
_searching = true;
|
||||||
emit searchByUsername();
|
emit searchByUsername();
|
||||||
}
|
}
|
||||||
|
setActive(-1);
|
||||||
update();
|
update();
|
||||||
loadProfilePhotos(0);
|
loadProfilePhotos(0);
|
||||||
}
|
}
|
||||||
|
@ -781,8 +844,10 @@ void ShareInner::peopleReceived(const QString &query, const QVector<MTPPeer> &pe
|
||||||
if (!peer || !peer->canWrite()) continue;
|
if (!peer || !peer->canWrite()) continue;
|
||||||
|
|
||||||
auto chat = new Chat(peer);
|
auto chat = new Chat(peer);
|
||||||
_byUsernameDatas.push_back(chat);
|
|
||||||
updateChatName(chat, peer);
|
updateChatName(chat, peer);
|
||||||
|
if (auto row = _chatsIndexed->getRow(peer->id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
_byUsernameFiltered.push_back(peer);
|
_byUsernameFiltered.push_back(peer);
|
||||||
d_byUsernameFiltered.push_back(chat);
|
d_byUsernameFiltered.push_back(chat);
|
||||||
|
@ -793,22 +858,12 @@ void ShareInner::peopleReceived(const QString &query, const QVector<MTPPeer> &pe
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareInner::refresh() {
|
void ShareInner::refresh() {
|
||||||
if (_filter.isEmpty()) {
|
auto count = displayedChatsCount();
|
||||||
if (!_chatsIndexed->isEmpty() || !_byUsername.isEmpty()) {
|
if (count) {
|
||||||
auto count = _chatsIndexed->size() + _byUsername.size();
|
auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0);
|
||||||
auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0);
|
resize(width(), _rowsTop + rows * _rowHeight);
|
||||||
resize(width(), _rowsTop + rows * _rowHeight);
|
|
||||||
} else {
|
|
||||||
resize(width(), st::noContactsHeight);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
|
resize(width(), st::noContactsHeight);
|
||||||
resize(width(), st::noContactsHeight);
|
|
||||||
} else {
|
|
||||||
auto count = _filtered.size() + _byUsernameFiltered.size();
|
|
||||||
auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0);
|
|
||||||
resize(width(), _rowsTop + rows * _rowHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -821,17 +876,12 @@ ShareInner::~ShareInner() {
|
||||||
|
|
||||||
QVector<PeerData*> ShareInner::selected() const {
|
QVector<PeerData*> ShareInner::selected() const {
|
||||||
QVector<PeerData*> result;
|
QVector<PeerData*> result;
|
||||||
result.reserve(_dataMap.size() + _byUsername.size());
|
result.reserve(_dataMap.size());
|
||||||
for_const (auto chat, _dataMap) {
|
for_const (auto chat, _dataMap) {
|
||||||
if (chat->selected) {
|
if (chat->selected) {
|
||||||
result.push_back(chat->peer);
|
result.push_back(chat->peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
|
|
||||||
if (d_byUsername[i]->selected) {
|
|
||||||
result.push_back(_byUsername[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,12 @@ private slots:
|
||||||
void onShare();
|
void onShare();
|
||||||
void onSelectedChanged();
|
void onSelectedChanged();
|
||||||
|
|
||||||
|
void onMustScrollTo(int top, int bottom);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
|
||||||
void doSetInnerFocus() override;
|
void doSetInnerFocus() override;
|
||||||
|
|
||||||
|
@ -90,6 +93,8 @@ private:
|
||||||
using PeopleQueries = QMap<mtpRequestId, QString>;
|
using PeopleQueries = QMap<mtpRequestId, QString>;
|
||||||
PeopleQueries _peopleQueries;
|
PeopleQueries _peopleQueries;
|
||||||
|
|
||||||
|
IntAnimation _scrollAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -105,13 +110,20 @@ public:
|
||||||
|
|
||||||
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
|
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
|
||||||
|
|
||||||
|
void activateSkipRow(int direction);
|
||||||
|
void activateSkipColumn(int direction);
|
||||||
|
void activateSkipPage(int pageHeight, int direction);
|
||||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||||
void updateFilter(QString filter = QString());
|
void updateFilter(QString filter = QString());
|
||||||
|
|
||||||
~ShareInner();
|
~ShareInner();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onSelectActive();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectAllQuery();
|
void mustScrollTo(int ymin, int ymax);
|
||||||
|
void filterCancel();
|
||||||
void searchByUsername();
|
void searchByUsername();
|
||||||
void selectedChanged();
|
void selectedChanged();
|
||||||
|
|
||||||
|
@ -127,6 +139,8 @@ private:
|
||||||
// Observed notifications.
|
// Observed notifications.
|
||||||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||||
|
|
||||||
|
int displayedChatsCount() const;
|
||||||
|
|
||||||
static constexpr int WideCacheScale = 4;
|
static constexpr int WideCacheScale = 4;
|
||||||
struct Chat {
|
struct Chat {
|
||||||
Chat(PeerData *peer);
|
Chat(PeerData *peer);
|
||||||
|
@ -192,9 +206,8 @@ private:
|
||||||
QString _lastQuery;
|
QString _lastQuery;
|
||||||
using ByUsernameRows = QVector<PeerData*>;
|
using ByUsernameRows = QVector<PeerData*>;
|
||||||
using ByUsernameDatas = QVector<Chat*>;
|
using ByUsernameDatas = QVector<Chat*>;
|
||||||
ByUsernameRows _byUsername, _byUsernameFiltered;
|
ByUsernameRows _byUsernameFiltered;
|
||||||
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas
|
ByUsernameDatas d_byUsernameFiltered;
|
||||||
ByUsernameDatas _byUsernameDatas;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,16 @@ void IndexedList::adjustByPos(const RowsByLetter &links) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IndexedList::moveToTop(PeerData *peer) {
|
||||||
|
if (_list.moveToTop(peer->id)) {
|
||||||
|
for_const (auto ch, peer->chars) {
|
||||||
|
if (auto list = _index.value(ch)) {
|
||||||
|
list->moveToTop(peer->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||||
t_assert(_sortMode != SortMode::Date);
|
t_assert(_sortMode != SortMode::Date);
|
||||||
if (_sortMode == SortMode::Name) {
|
if (_sortMode == SortMode::Name) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
RowsByLetter addToEnd(History *history);
|
RowsByLetter addToEnd(History *history);
|
||||||
Row *addByName(History *history);
|
Row *addByName(History *history);
|
||||||
void adjustByPos(const RowsByLetter &links);
|
void adjustByPos(const RowsByLetter &links);
|
||||||
|
void moveToTop(PeerData *peer);
|
||||||
|
|
||||||
// For sortMode != SortMode::Date
|
// For sortMode != SortMode::Date
|
||||||
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
||||||
|
|
|
@ -189,6 +189,14 @@ void List::adjustByPos(Row *row) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool List::moveToTop(PeerId peerId) {
|
||||||
|
auto i = _rowByPeer.find(peerId);
|
||||||
|
if (i == _rowByPeer.cend()) return false;
|
||||||
|
|
||||||
|
insertBefore(i.value(), _begin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool List::del(PeerId peerId, Row *replacedBy) {
|
bool List::del(PeerId peerId, Row *replacedBy) {
|
||||||
auto i = _rowByPeer.find(peerId);
|
auto i = _rowByPeer.find(peerId);
|
||||||
if (i == _rowByPeer.cend()) return false;
|
if (i == _rowByPeer.cend()) return false;
|
||||||
|
|
|
@ -53,10 +53,9 @@ public:
|
||||||
|
|
||||||
void paint(Painter &p, int32 w, int32 hFrom, int32 hTo, PeerData *act, PeerData *sel, bool onlyBackground) const;
|
void paint(Painter &p, int32 w, int32 hFrom, int32 hTo, PeerData *act, PeerData *sel, bool onlyBackground) const;
|
||||||
Row *addToEnd(History *history);
|
Row *addToEnd(History *history);
|
||||||
bool insertBefore(Row *row, Row *before);
|
|
||||||
bool insertAfter(Row *row, Row *after);
|
|
||||||
Row *adjustByName(const PeerData *peer);
|
Row *adjustByName(const PeerData *peer);
|
||||||
Row *addByName(History *history);
|
Row *addByName(History *history);
|
||||||
|
bool moveToTop(PeerId peerId);
|
||||||
void adjustByPos(Row *row);
|
void adjustByPos(Row *row);
|
||||||
bool del(PeerId peerId, Row *replacedBy = nullptr);
|
bool del(PeerId peerId, Row *replacedBy = nullptr);
|
||||||
void remove(Row *row);
|
void remove(Row *row);
|
||||||
|
@ -114,6 +113,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void adjustCurrent(int y, int h) const;
|
void adjustCurrent(int y, int h) const;
|
||||||
|
bool insertBefore(Row *row, Row *before);
|
||||||
|
bool insertAfter(Row *row, Row *after);
|
||||||
static Row *next(Row *row) {
|
static Row *next(Row *row) {
|
||||||
return row->_next;
|
return row->_next;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue