diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 934a9a5fa..6d467edab 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -236,17 +236,17 @@ namespace App { case -2: { QDate yesterday(date(now).date()); - return int32(QDateTime(yesterday.addDays(-3)).toTime_t()); + return int32(QDateTime(yesterday.addDays(-3)).toTime_t()) + (unixtime() - myunixtime()); } break; case -3: { QDate weekago(date(now).date()); - return int32(QDateTime(weekago.addDays(-7)).toTime_t()); + return int32(QDateTime(weekago.addDays(-7)).toTime_t()) + (unixtime() - myunixtime()); } break; case -4: { QDate monthago(date(now).date()); - return int32(QDateTime(monthago.addDays(-30)).toTime_t()); + return int32(QDateTime(monthago.addDays(-30)).toTime_t()) + (unixtime() - myunixtime()); } break; } return -online; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index eab2c235b..72b401f84 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -31,24 +31,29 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "localstorage.h" -DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(parent), -dialogs(DialogsSortByDate), -contactsNoDialogs(DialogsSortByName), -contacts(DialogsSortByName), -sel(0), -contactSel(false), -selByMouse(false), -hashtagSel(-1), -filteredSel(-1), -searchedCount(0), -searchedSel(-1), -peopleSel(-1), -_lastSearchId(0), -_state(DefaultState), -_addContactLnk(this, lang(lng_add_contact_button)), -_cancelSearchInPeer(this, st::btnCancelSearch), -_overDelete(false), -_searchInPeer(0) { +DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(parent) +, dialogs(DialogsSortByDate) +, contactsNoDialogs(DialogsSortByName) +, contacts(DialogsSortByName) +, sel(0) +, contactSel(false) +, selByMouse(false) +, _hashtagSel(-1) +, _filteredSel(-1) +, _searchedCount(0) +, _searchedMigratedCount(0) +, _searchedSel(-1) +, _peopleSel(-1) +, _lastSearchDate(0) +, _lastSearchPeer(0) +, _lastSearchId(0) +, _lastSearchMigratedId(0) +, _state(DefaultState) +, _addContactLnk(this, lang(lng_add_contact_button)) +, _cancelSearchInPeer(this, st::btnCancelSearch) +, _overDelete(false) +, _searchInPeer(0) +, _searchInMigrated(0) { connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); @@ -60,15 +65,15 @@ _searchInPeer(0) { } int32 DialogsInner::filteredOffset() const { - return hashtagResults.size() * st::mentionHeight; + return _hashtagResults.size() * st::mentionHeight; } int32 DialogsInner::peopleOffset() const { - return filteredOffset() + (filterResults.size() * st::dlgHeight) + st::searchedBarHeight; + return filteredOffset() + (_filterResults.size() * st::dlgHeight) + st::searchedBarHeight; } int32 DialogsInner::searchedOffset() const { - int32 result = peopleOffset() + (peopleResults.isEmpty() ? 0 : ((peopleResults.size() * st::dlgHeight) + st::searchedBarHeight)); + int32 result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight)); if (_searchInPeer) result += st::dlgHeight; return result; } @@ -101,17 +106,17 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } } } else if (_state == FilteredState || _state == SearchedState) { - if (!hashtagResults.isEmpty()) { - int32 from = floorclamp(r.y(), st::mentionHeight, 0, hashtagResults.size()); - int32 to = ceilclamp(r.y() + r.height(), st::mentionHeight, 0, hashtagResults.size()); + if (!_hashtagResults.isEmpty()) { + int32 from = floorclamp(r.y(), st::mentionHeight, 0, _hashtagResults.size()); + int32 to = ceilclamp(r.y() + r.height(), st::mentionHeight, 0, _hashtagResults.size()); p.translate(0, from * st::mentionHeight); - if (from < hashtagResults.size()) { + if (from < _hashtagResults.size()) { int32 w = fullWidth(), htagwidth = w - st::dlgPaddingHor * 2; p.setFont(st::mentionFont->f); p.setPen(st::black->p); for (; from < to; ++from) { - bool selected = (from == hashtagSel); + bool selected = (from == _hashtagSel); p.fillRect(0, 0, w, st::mentionHeight, (selected ? st::mentionBgOver : st::white)->b); if (!paintingOther) { if (selected) { @@ -119,7 +124,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO p.drawPixmap(QPoint(w - st::notifyClose.icon.pxWidth() - skip, skip), App::sprite(), st::notifyClose.icon); } - QString first = (_hashtagFilter.size() < 2) ? QString() : ('#' + hashtagResults.at(from).mid(0, _hashtagFilter.size() - 1)), second = (_hashtagFilter.size() < 2) ? ('#' + hashtagResults.at(from)) : hashtagResults.at(from).mid(_hashtagFilter.size() - 1); + QString first = (_hashtagFilter.size() < 2) ? QString() : ('#' + _hashtagResults.at(from).mid(0, _hashtagFilter.size() - 1)), second = (_hashtagFilter.size() < 2) ? ('#' + _hashtagResults.at(from)) : _hashtagResults.at(from).mid(_hashtagFilter.size() - 1); int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); if (htagwidth < firstwidth + secondwidth) { if (htagwidth < firstwidth + st::mentionFont->elidew) { @@ -144,23 +149,25 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } } } - if (!filterResults.isEmpty()) { + if (!_filterResults.isEmpty()) { int32 skip = filteredOffset(); - int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, filterResults.size()); - int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, filterResults.size()); + int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, _filterResults.size()); + int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, _filterResults.size()); p.translate(0, from * st::dlgHeight); - if (from < filterResults.size()) { + if (from < _filterResults.size()) { int32 w = fullWidth(); + PeerData *act = App::main()->activePeer(); + MsgId actId = App::main()->activeMsgId(); for (; from < to; ++from) { - bool active = (filterResults[from]->history->peer == App::main()->activePeer() && !App::main()->activeMsgId()); - bool selected = (from == filteredSel); - filterResults[from]->paint(p, w, active, selected, paintingOther); + bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId; + bool selected = (from == _filteredSel); + _filterResults[from]->paint(p, w, active, selected, paintingOther); p.translate(0, st::dlgHeight); } } } - if (!peopleResults.isEmpty()) { + if (!_peopleResults.isEmpty()) { p.fillRect(0, 0, fullWidth(), st::searchedBarHeight, st::searchedBarBG->b); if (!paintingOther) { p.setFont(st::searchedBarFont->f); @@ -170,15 +177,17 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO p.translate(0, st::searchedBarHeight); int32 skip = peopleOffset(); - int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, peopleResults.size()); - int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, peopleResults.size()); + int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, _peopleResults.size()); + int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, _peopleResults.size()); p.translate(0, from * st::dlgHeight); - if (from < peopleResults.size()) { + if (from < _peopleResults.size()) { int32 w = fullWidth(); + PeerData *act = App::main()->activePeer(); + MsgId actId = App::main()->activeMsgId(); for (; from < to; ++from) { - bool active = (peopleResults[from] == App::main()->activePeer() && !App::main()->activeMsgId()); - bool selected = (from == peopleSel); - peopleResultPaint(peopleResults[from], p, w, active, selected, paintingOther); + bool active = ((_peopleResults[from] == act) || (_peopleResults[from]->migrateTo() && _peopleResults[from]->migrateTo() == act)) && !actId; + bool selected = (from == _peopleSel); + peopleResultPaint(_peopleResults[from], p, w, active, selected, paintingOther); p.translate(0, st::dlgHeight); } } @@ -187,7 +196,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO if (_searchInPeer) { searchInPeerPaint(p, fullWidth(), paintingOther); p.translate(0, st::dlgHeight); - if (_state == FilteredState && searchResults.isEmpty()) { + if (_state == FilteredState && _searchResults.isEmpty()) { p.fillRect(0, 0, fullWidth(), st::searchedBarHeight, st::searchedBarBG->b); if (!paintingOther) { p.setFont(st::searchedBarFont->f); @@ -198,8 +207,8 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } } - if (_state == SearchedState || !searchResults.isEmpty()) { - QString text = lng_search_found_results(lt_count, searchResults.isEmpty() ? 0 : searchedCount); + if (_state == SearchedState || !_searchResults.isEmpty()) { + QString text = lng_search_found_results(lt_count, _searchResults.isEmpty() ? 0 : (_searchedMigratedCount + _searchedCount)); p.fillRect(0, 0, fullWidth(), st::searchedBarHeight, st::searchedBarBG->b); if (!paintingOther) { p.setFont(st::searchedBarFont->f); @@ -209,15 +218,17 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO p.translate(0, st::searchedBarHeight); int32 skip = searchedOffset(); - int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, searchResults.size()); - int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, searchResults.size()); + int32 from = floorclamp(r.y() - skip, st::dlgHeight, 0, _searchResults.size()); + int32 to = ceilclamp(r.y() + r.height() - skip, st::dlgHeight, 0, _searchResults.size()); p.translate(0, from * st::dlgHeight); - if (from < searchResults.size()) { + if (from < _searchResults.size()) { int32 w = fullWidth(); + PeerData *act = App::main()->activePeer(); + MsgId actId = App::main()->activeMsgId(); for (; from < to; ++from) { - bool active = (searchResults[from]->_item->history()->peer == App::main()->activePeer() && searchResults[from]->_item->id == App::main()->activeMsgId()); - bool selected = (from == searchedSel); - searchResults[from]->paint(p, w, active, selected, paintingOther); + bool active = (_searchResults[from]->_item->history()->peer == act && _searchResults[from]->_item->id == actId) || (_searchResults[from]->_item->history()->peer->migrateTo() && _searchResults[from]->_item->history()->peer->migrateTo() == act && _searchResults[from]->_item->id == -actId); + bool selected = (from == _searchedSel); + _searchResults[from]->paint(p, w, active, selected, paintingOther); p.translate(0, st::dlgHeight); } } @@ -232,7 +243,11 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a History *history = App::history(peer->id); - p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, peer->photo->pix(st::dlgPhotoSize)); + if (peer->migrateTo()) { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, peer->migrateTo()->photo->pix(st::dlgPhotoSize)); + } else { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, peer->photo->pix(st::dlgPhotoSize)); + } int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding; int32 namewidth = w - nameleft - st::dlgPaddingHor; @@ -254,8 +269,8 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height); p.setFont(st::dlgHistFont->f); QString username = peer->userName(); - if (!act && username.toLower().startsWith(peopleQuery)) { - QString first = '@' + username.mid(0, peopleQuery.size()), second = username.mid(peopleQuery.size()); + if (!act && username.toLower().startsWith(_peopleQuery)) { + QString first = '@' + username.mid(0, _peopleQuery.size()), second = username.mid(_peopleQuery.size()); int32 w = st::dlgHistFont->width(first); if (w >= tr.width()) { p.setPen(st::dlgSystemColor->p); @@ -335,55 +350,55 @@ void DialogsInner::onUpdateSelected(bool force) { setCursor(sel ? style::cur_pointer : style::cur_default); } } else if (_state == FilteredState || _state == SearchedState) { - if (!hashtagResults.isEmpty()) { + if (!_hashtagResults.isEmpty()) { int32 skip = 0, newHashtagSel = (mouseY >= skip) ? ((mouseY - skip) / int32(st::mentionHeight)) : -1; - if (newHashtagSel < 0 || newHashtagSel >= hashtagResults.size()) { + if (newHashtagSel < 0 || newHashtagSel >= _hashtagResults.size()) { newHashtagSel = -1; } - if (newHashtagSel != hashtagSel) { + if (newHashtagSel != _hashtagSel) { updateSelectedRow(); - hashtagSel = newHashtagSel; + _hashtagSel = newHashtagSel; updateSelectedRow(); - setCursor((hashtagSel >= 0) ? style::cur_pointer : style::cur_default); + setCursor((_hashtagSel >= 0) ? style::cur_pointer : style::cur_default); } - if (hashtagSel >= 0) { + if (_hashtagSel >= 0) { _overDelete = (mouse.x() >= w - st::mentionHeight); } } - if (!filterResults.isEmpty()) { + if (!_filterResults.isEmpty()) { int32 skip = filteredOffset(), newFilteredSel = (mouseY >= skip) ? ((mouseY - skip) / int32(st::dlgHeight)) : -1; - if (newFilteredSel < 0 || newFilteredSel >= filterResults.size()) { + if (newFilteredSel < 0 || newFilteredSel >= _filterResults.size()) { newFilteredSel = -1; } - if (newFilteredSel != filteredSel) { + if (newFilteredSel != _filteredSel) { updateSelectedRow(); - filteredSel = newFilteredSel; + _filteredSel = newFilteredSel; updateSelectedRow(); - setCursor((filteredSel >= 0) ? style::cur_pointer : style::cur_default); + setCursor((_filteredSel >= 0) ? style::cur_pointer : style::cur_default); } } - if (!peopleResults.isEmpty()) { + if (!_peopleResults.isEmpty()) { int32 skip = peopleOffset(), newPeopleSel = (mouseY >= skip) ? ((mouseY - skip) / int32(st::dlgHeight)) : -1; - if (newPeopleSel < 0 || newPeopleSel >= peopleResults.size()) { + if (newPeopleSel < 0 || newPeopleSel >= _peopleResults.size()) { newPeopleSel = -1; } - if (newPeopleSel != peopleSel) { + if (newPeopleSel != _peopleSel) { updateSelectedRow(); - peopleSel = newPeopleSel; + _peopleSel = newPeopleSel; updateSelectedRow(); - setCursor((peopleSel >= 0) ? style::cur_pointer : style::cur_default); + setCursor((_peopleSel >= 0) ? style::cur_pointer : style::cur_default); } } - if (_state == SearchedState && !searchResults.isEmpty()) { + if (_state == SearchedState && !_searchResults.isEmpty()) { int32 skip = searchedOffset(), newSearchedSel = (mouseY >= skip) ? ((mouseY - skip) / int32(st::dlgHeight)) : -1; - if (newSearchedSel < 0 || newSearchedSel >= searchResults.size()) { + if (newSearchedSel < 0 || newSearchedSel >= _searchResults.size()) { newSearchedSel = -1; } - if (newSearchedSel != searchedSel) { + if (newSearchedSel != _searchedSel) { updateSelectedRow(); - searchedSel = newSearchedSel; + _searchedSel = newSearchedSel; updateSelectedRow(); - setCursor((searchedSel >= 0) ? style::cur_pointer : style::cur_default); + setCursor((_searchedSel >= 0) ? style::cur_pointer : style::cur_default); } } } @@ -405,13 +420,13 @@ void DialogsInner::resizeEvent(QResizeEvent *e) { void DialogsInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { if (_state == FilteredState || _state == SearchedState) { - for (FilteredDialogs::iterator i = filterResults.begin(); i != filterResults.end();) { + for (FilteredDialogs::iterator i = _filterResults.begin(); i != _filterResults.end();) { if (*i == oldRow) { // this row is shown in filtered and maybe is in contacts! if (newRow) { *i = newRow; ++i; } else { - i = filterResults.erase(i); + i = _filterResults.erase(i); } } else { ++i; @@ -480,8 +495,8 @@ void DialogsInner::dlgUpdated(DialogRow *row) { if (_state == DefaultState) { update(0, row->pos * st::dlgHeight, fullWidth(), st::dlgHeight); } else if (_state == FilteredState || _state == SearchedState) { - for (int32 i = 0, l = filterResults.size(); i < l; ++i) { - if (filterResults.at(i)->history == row->history) { + for (int32 i = 0, l = _filterResults.size(); i < l; ++i) { + if (_filterResults.at(i)->history == row->history) { update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight); break; } @@ -498,16 +513,16 @@ void DialogsInner::dlgUpdated(History *history, MsgId msgId) { } } else if (_state == FilteredState || _state == SearchedState) { int32 cnt = 0, add = filteredOffset(); - for (FilteredDialogs::const_iterator i = filterResults.cbegin(), e = filterResults.cend(); i != e; ++i) { + for (FilteredDialogs::const_iterator i = _filterResults.cbegin(), e = _filterResults.cend(); i != e; ++i) { if ((*i)->history == history) { update(0, add + cnt * st::dlgHeight, fullWidth(), st::dlgHeight); break; } ++cnt; } - if (!peopleResults.isEmpty()) { + if (!_peopleResults.isEmpty()) { int32 cnt = 0, add = peopleOffset(); - for (PeopleResults::const_iterator i = peopleResults.cbegin(), e = peopleResults.cend(); i != e; ++i) { + for (PeopleResults::const_iterator i = _peopleResults.cbegin(), e = _peopleResults.cend(); i != e; ++i) { if ((*i) == history->peer) { update(0, add + cnt * st::dlgHeight, fullWidth(), st::dlgHeight); break; @@ -515,9 +530,9 @@ void DialogsInner::dlgUpdated(History *history, MsgId msgId) { ++cnt; } } - if (!searchResults.isEmpty()) { + if (!_searchResults.isEmpty()) { int32 cnt = 0, add = searchedOffset(); - for (SearchResults::const_iterator i = searchResults.cbegin(), e = searchResults.cend(); i != e; ++i) { + for (SearchResults::const_iterator i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { if ((*i)->_item->history() == history && (*i)->_item->id == msgId) { update(0, add + cnt * st::dlgHeight, fullWidth(), st::dlgHeight); break; @@ -540,14 +555,14 @@ void DialogsInner::updateSelectedRow() { update(0, sel->pos * st::dlgHeight, fullWidth(), st::dlgHeight); } } else if (_state == FilteredState || _state == SearchedState) { - if (hashtagSel >= 0) { - update(0, hashtagSel * st::mentionHeight, fullWidth(), st::mentionHeight); - } else if (filteredSel >= 0) { - update(0, filteredOffset() + filteredSel * st::dlgHeight, fullWidth(), st::dlgHeight); - } else if (peopleSel >= 0) { - update(0, peopleOffset() + peopleSel * st::dlgHeight, fullWidth(), st::dlgHeight); - } else if (searchedSel >= 0) { - update(0, searchedOffset() + searchedSel * st::dlgHeight, fullWidth(), st::dlgHeight); + if (_hashtagSel >= 0) { + update(0, _hashtagSel * st::mentionHeight, fullWidth(), st::mentionHeight); + } else if (_filteredSel >= 0) { + update(0, filteredOffset() + _filteredSel * st::dlgHeight, fullWidth(), st::dlgHeight); + } else if (_peopleSel >= 0) { + update(0, peopleOffset() + _peopleSel * st::dlgHeight, fullWidth(), st::dlgHeight); + } else if (_searchedSel >= 0) { + update(0, searchedOffset() + _searchedSel * st::dlgHeight, fullWidth(), st::dlgHeight); } } @@ -556,10 +571,10 @@ void DialogsInner::updateSelectedRow() { void DialogsInner::leaveEvent(QEvent *e) { setMouseTracking(false); selByMouse = false; - if (sel || filteredSel >= 0 || hashtagSel >= 0 || searchedSel >= 0 || peopleSel >= 0) { + if (sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) { updateSelectedRow(); sel = 0; - filteredSel = searchedSel = peopleSel = hashtagSel = -1; + _filteredSel = _searchedSel = _peopleSel = _hashtagSel = -1; setCursor(style::cur_default); } } @@ -585,7 +600,7 @@ void DialogsInner::onPeerPhotoChanged(PeerData *peer) { void DialogsInner::onFilterUpdate(QString newFilter, bool force) { newFilter = textSearchKey(newFilter); - if (newFilter != filter || force) { + if (newFilter != _filter || force) { QStringList f; if (!newFilter.isEmpty()) { QStringList filterList = newFilter.split(cWordSplit(), QString::SkipEmptyParts); @@ -599,20 +614,22 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { } newFilter = f.join(' '); } - if (newFilter != filter || force) { - filter = newFilter; - if (!_searchInPeer && filter.isEmpty()) { + if (newFilter != _filter || force) { + _filter = newFilter; + if (!_searchInPeer && _filter.isEmpty()) { _state = DefaultState; - hashtagResults.clear(); - filterResults.clear(); - peopleResults.clear(); - searchResults.clear(); - _lastSearchId = 0; + _hashtagResults.clear(); + _filterResults.clear(); + _peopleResults.clear(); + _searchResults.clear(); + _lastSearchDate = 0; + _lastSearchPeer = 0; + _lastSearchId = _lastSearchMigratedId = 0; } else { QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; _state = FilteredState; - filterResults.clear(); + _filterResults.clear(); if (!_searchInPeer && !f.isEmpty()) { DialogsList *dialogsToFilter = 0, *contactsNoDialogsToFilter = 0; if (dialogs.list.count) { @@ -639,7 +656,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { } } } - filterResults.reserve((dialogsToFilter ? dialogsToFilter->count : 0) + (contactsNoDialogsToFilter ? contactsNoDialogsToFilter->count : 0)); + _filterResults.reserve((dialogsToFilter ? dialogsToFilter->count : 0) + (contactsNoDialogsToFilter ? contactsNoDialogsToFilter->count : 0)); if (dialogsToFilter && dialogsToFilter->count) { for (DialogRow *i = dialogsToFilter->begin, *e = dialogsToFilter->end; i != e; i = i->next) { const PeerData::Names &names(i->history->peer->names); @@ -656,7 +673,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { } } if (fi == fe) { - filterResults.push_back(i); + _filterResults.push_back(i); } } } @@ -676,7 +693,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { } } if (fi == fe) { - filterResults.push_back(i); + _filterResults.push_back(i); } } } @@ -694,8 +711,8 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) { if (newFilter.isEmpty() || newFilter.at(0) != '#' || _searchInPeer) { _hashtagFilter = QString(); - if (!hashtagResults.isEmpty()) { - hashtagResults.clear(); + if (!_hashtagResults.isEmpty()) { + _hashtagResults.clear(); refresh(true); setMouseSel(false, true); } @@ -706,13 +723,13 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) { Local::readRecentHashtags(); } const RecentHashtagPack &recent(cRecentSearchHashtags()); - hashtagResults.clear(); + _hashtagResults.clear(); if (!recent.isEmpty()) { - hashtagResults.reserve(qMin(recent.size(), 5)); + _hashtagResults.reserve(qMin(recent.size(), 5)); for (RecentHashtagPack::const_iterator i = recent.cbegin(), e = recent.cend(); i != e; ++i) { if (i->first.startsWith(_hashtagFilter.midRef(1), Qt::CaseInsensitive) && i->first.size() + 1 != newFilter.size()) { - hashtagResults.push_back(i->first); - if (hashtagResults.size() == 5) break; + _hashtagResults.push_back(i->first); + if (_hashtagResults.size() == 5) break; } } } @@ -725,20 +742,23 @@ DialogsInner::~DialogsInner() { } void DialogsInner::clearSearchResults(bool clearPeople) { - if (clearPeople) peopleResults.clear(); - if (!searchResults.isEmpty()) { - for (SearchResults::const_iterator i = searchResults.cbegin(), e = searchResults.cend(); i != e; ++i) { + if (clearPeople) _peopleResults.clear(); + if (!_searchResults.isEmpty()) { + for (SearchResults::const_iterator i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { delete *i; } - searchResults.clear(); + _searchResults.clear(); } - _lastSearchId = 0; + _searchedCount = _searchedMigratedCount = 0; + _lastSearchDate = 0; + _lastSearchPeer = 0; + _lastSearchId = _lastSearchMigratedId = 0; } void DialogsInner::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { - for (int i = 0; i < searchResults.size(); ++i) { - if (searchResults[i]->_item == oldItem) { - searchResults[i]->_item = newItem; + for (int i = 0; i < _searchResults.size(); ++i) { + if (_searchResults[i]->_item == oldItem) { + _searchResults[i]->_item = newItem; } } } @@ -750,28 +770,32 @@ PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) { if (_state == DefaultState) { if (sel) return sel->history->peer; } else if (_state == FilteredState || _state == SearchedState) { - if (filteredSel >= 0 && filteredSel < filterResults.size()) { - return filterResults[filteredSel]->history->peer; - } else if (peopleSel >= 0 && peopleSel < peopleResults.size()) { - return peopleResults[peopleSel]; - } else if (searchedSel >= 0 && searchedSel < searchResults.size()) { - return searchResults[searchedSel]->_item->history()->peer; + if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { + return _filterResults[_filteredSel]->history->peer; + } else if (_peopleSel >= 0 && _peopleSel < _peopleResults.size()) { + return _peopleResults[_peopleSel]; + } else if (_searchedSel >= 0 && _searchedSel < _searchResults.size()) { + return _searchResults[_searchedSel]->_item->history()->peer; } } return 0; } void DialogsInner::itemRemoved(HistoryItem *item) { - int wasCount = searchResults.size(); - for (int i = 0; i < searchResults.size();) { - if (searchResults[i]->_item == item) { - searchResults.remove(i); - if (searchedCount > 0) --searchedCount; + int wasCount = _searchResults.size(); + for (int i = 0; i < _searchResults.size();) { + if (_searchResults[i]->_item == item) { + _searchResults.remove(i); + if (item->history()->peer == _searchInMigrated) { + if (_searchedMigratedCount > 0) --_searchedMigratedCount; + } else { + if (_searchedCount > 0) --_searchedCount; + } } else { ++i; } } - if (wasCount != searchResults.size()) { + if (wasCount != _searchResults.size()) { refresh(); } } @@ -845,32 +869,52 @@ void DialogsInner::addAllSavedPeers() { addSavedPeersAfter(QDateTime()); } -void DialogsInner::searchReceived(const QVector &messages, bool fromStart, int32 fullCount) { - if (fromStart) { +bool DialogsInner::searchReceived(const QVector &messages, DialogsSearchRequestType type, int32 fullCount) { + if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { clearSearchResults(false); } + int32 lastDateFound = 0; for (QVector::const_iterator i = messages.cbegin(), e = messages.cend(); i != e; ++i) { HistoryItem *item = App::histories().addNewMessage(*i, NewMessageExisting); - searchResults.push_back(new FakeDialogRow(item)); - _lastSearchId = item->id; + int32 lastDate = dateFromMessage(*i); + if (lastDate) { + _searchResults.push_back(new FakeDialogRow(item)); + lastDateFound = lastDate; + if (type == DialogsSearchFromStart || type == DialogsSearchFromOffset) { + _lastSearchDate = lastDateFound; + } + } + if (type == DialogsSearchFromStart || type == DialogsSearchFromOffset) { + _lastSearchPeer = item->history()->peer; + } + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _lastSearchMigratedId = item->id; + } else { + _lastSearchId = item->id; + } } - searchedCount = fullCount; - if (_state == FilteredState) { + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _searchedMigratedCount = fullCount; + } else { + _searchedCount = fullCount; + } + if (_state == FilteredState && (!_searchResults.isEmpty() || !_searchInMigrated || type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset)) { _state = SearchedState; } refresh(); + return lastDateFound != 0; } void DialogsInner::peopleReceived(const QString &query, const QVector &people) { - peopleQuery = query.toLower().trimmed(); - peopleResults.clear(); - peopleResults.reserve(people.size()); + _peopleQuery = query.toLower().trimmed(); + _peopleResults.clear(); + _peopleResults.reserve(people.size()); for (QVector::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { PeerId peerId = peerFromMTP(*i); History *h = App::historyLoaded(peerId); if (h && !h->dialogs.isEmpty()) continue; // skip dialogs - peopleResults.push_back(App::peer(peerId)); + _peopleResults.push_back(App::peer(peerId)); } refresh(); } @@ -926,9 +970,9 @@ void DialogsInner::refresh(bool toTop) { } else { if (!_addContactLnk.isHidden()) _addContactLnk.hide(); if (_state == FilteredState) { - h = searchedOffset() + (searchResults.count() * st::dlgHeight) + ((searchResults.isEmpty() && !_searchInPeer) ? -st::searchedBarHeight : 0); + h = searchedOffset() + (_searchResults.count() * st::dlgHeight) + ((_searchResults.isEmpty() && !_searchInPeer) ? -st::searchedBarHeight : 0); } else if (_state == SearchedState) { - h = searchedOffset() + (searchResults.count() * st::dlgHeight); + h = searchedOffset() + (_searchResults.count() * st::dlgHeight); } } setHeight(h); @@ -946,7 +990,7 @@ void DialogsInner::setMouseSel(bool msel, bool toTop) { sel = (dialogs.list.count ? dialogs.list.begin : (contactsNoDialogs.list.count ? contactsNoDialogs.list.begin : 0)); contactSel = !dialogs.list.count && contactsNoDialogs.list.count; } else if (_state == FilteredState || _state == SearchedState) { // don't select first elem in search - filteredSel = peopleSel = searchedSel = hashtagSel = -1; + _filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1; setCursor(style::cur_default); } } @@ -956,14 +1000,14 @@ void DialogsInner::setState(State newState) { _state = newState; if (_state == DefaultState) { clearSearchResults(); - searchedSel = peopleSel = filteredSel = hashtagSel = -1; + _searchedSel = _peopleSel = _filteredSel = _hashtagSel = -1; } else if (_state == DefaultState || _state == SearchedState) { - hashtagResults.clear(); - hashtagSel = -1; - filterResults.clear(); - filteredSel = -1; + _hashtagResults.clear(); + _hashtagSel = -1; + _filterResults.clear(); + _filteredSel = -1; } - onFilterUpdate(filter, true); + onFilterUpdate(_filter, true); refresh(true); } @@ -972,11 +1016,12 @@ DialogsInner::State DialogsInner::state() const { } bool DialogsInner::hasFilteredResults() const { - return !filterResults.isEmpty() && hashtagResults.isEmpty(); + return !_filterResults.isEmpty() && _hashtagResults.isEmpty(); } void DialogsInner::searchInPeer(PeerData *peer) { - _searchInPeer = peer; + _searchInPeer = peer ? (peer->migrateTo() ? peer->migrateTo() : peer) : 0; + _searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0; if (_searchInPeer) { onHashtagFilterUpdate(QStringRef()); _cancelSearchInPeer.show(); @@ -992,12 +1037,14 @@ void DialogsInner::clearFilter() { } else { _state = DefaultState; } - hashtagResults.clear(); - filterResults.clear(); - peopleResults.clear(); - searchResults.clear(); - _lastSearchId = 0; - filter = QString(); + _hashtagResults.clear(); + _filterResults.clear(); + _peopleResults.clear(); + _searchResults.clear(); + _lastSearchDate = 0; + _lastSearchPeer = 0; + _lastSearchId = _lastSearchMigratedId = 0; + _filter = QString(); refresh(true); } } @@ -1030,45 +1077,45 @@ void DialogsInner::selectSkip(int32 direction) { int32 fromY = (sel->pos + (contactSel ? dialogs.list.count : 0)) * st::dlgHeight; emit mustScrollTo(fromY, fromY + st::dlgHeight); } else if (_state == FilteredState || _state == SearchedState) { - if (hashtagResults.isEmpty() && filterResults.isEmpty() && peopleResults.isEmpty() && searchResults.isEmpty()) return; - if ((hashtagSel < 0 || hashtagSel >= hashtagResults.size()) && - (filteredSel < 0 || filteredSel >= filterResults.size()) && - (peopleSel < 0 || peopleSel >= peopleResults.size()) && - (searchedSel < 0 || searchedSel >= searchResults.size())) { - if (hashtagResults.isEmpty() && filterResults.isEmpty() && peopleResults.isEmpty()) { - searchedSel = 0; - } else if (hashtagResults.isEmpty() && filterResults.isEmpty()) { - peopleSel = 0; - } else if (hashtagResults.isEmpty()) { - filteredSel = 0; + if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty() && _searchResults.isEmpty()) return; + if ((_hashtagSel < 0 || _hashtagSel >= _hashtagResults.size()) && + (_filteredSel < 0 || _filteredSel >= _filterResults.size()) && + (_peopleSel < 0 || _peopleSel >= _peopleResults.size()) && + (_searchedSel < 0 || _searchedSel >= _searchResults.size())) { + if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty()) { + _searchedSel = 0; + } else if (_hashtagResults.isEmpty() && _filterResults.isEmpty()) { + _peopleSel = 0; + } else if (_hashtagResults.isEmpty()) { + _filteredSel = 0; } else { - hashtagSel = 0; + _hashtagSel = 0; } } else { - int32 cur = (hashtagSel >= 0 && hashtagSel < hashtagResults.size()) ? hashtagSel : ((filteredSel >= 0 && filteredSel < filterResults.size()) ? (hashtagResults.size() + filteredSel) : ((peopleSel >= 0 && peopleSel < peopleResults.size()) ? (peopleSel + filterResults.size() + hashtagResults.size()) : (searchedSel + peopleResults.size() + filterResults.size() + hashtagResults.size()))); - cur = snap(cur + direction, 0, hashtagResults.size() + filterResults.size() + peopleResults.size() + searchResults.size() - 1); - if (cur < hashtagResults.size()) { - hashtagSel = cur; - filteredSel = peopleSel = searchedSel = -1; - } else if (cur < hashtagResults.size() + filterResults.size()) { - filteredSel = cur - hashtagResults.size(); - hashtagSel = peopleSel = searchedSel = -1; - } else if (cur < hashtagResults.size() + filterResults.size() + peopleResults.size()) { - peopleSel = cur - hashtagResults.size() - filterResults.size(); - hashtagSel = filteredSel = searchedSel = -1; + int32 cur = (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) ? _hashtagSel : ((_filteredSel >= 0 && _filteredSel < _filterResults.size()) ? (_hashtagResults.size() + _filteredSel) : ((_peopleSel >= 0 && _peopleSel < _peopleResults.size()) ? (_peopleSel + _filterResults.size() + _hashtagResults.size()) : (_searchedSel + _peopleResults.size() + _filterResults.size() + _hashtagResults.size()))); + cur = snap(cur + direction, 0, _hashtagResults.size() + _filterResults.size() + _peopleResults.size() + _searchResults.size() - 1); + if (cur < _hashtagResults.size()) { + _hashtagSel = cur; + _filteredSel = _peopleSel = _searchedSel = -1; + } else if (cur < _hashtagResults.size() + _filterResults.size()) { + _filteredSel = cur - _hashtagResults.size(); + _hashtagSel = _peopleSel = _searchedSel = -1; + } else if (cur < _hashtagResults.size() + _filterResults.size() + _peopleResults.size()) { + _peopleSel = cur - _hashtagResults.size() - _filterResults.size(); + _hashtagSel = _filteredSel = _searchedSel = -1; } else { - hashtagSel = filteredSel = peopleSel = -1; - searchedSel = cur - hashtagResults.size() - filterResults.size() - peopleResults.size(); + _hashtagSel = _filteredSel = _peopleSel = -1; + _searchedSel = cur - _hashtagResults.size() - _filterResults.size() - _peopleResults.size(); } } - if (hashtagSel >= 0 && hashtagSel < hashtagResults.size()) { - emit mustScrollTo(hashtagSel * st::mentionHeight, (hashtagSel + 1) * st::mentionHeight); - } else if (filteredSel >= 0 && filteredSel < filterResults.size()) { - emit mustScrollTo(filteredOffset() + filteredSel * st::dlgHeight, filteredOffset() + (filteredSel + 1) * st::dlgHeight); - } else if (peopleSel >= 0 && peopleSel < peopleResults.size()) { - emit mustScrollTo(peopleOffset() + peopleSel * st::dlgHeight + (peopleSel ? 0 : -st::searchedBarHeight), peopleOffset() + (peopleSel + 1) * st::dlgHeight); + if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) { + emit mustScrollTo(_hashtagSel * st::mentionHeight, (_hashtagSel + 1) * st::mentionHeight); + } else if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { + emit mustScrollTo(filteredOffset() + _filteredSel * st::dlgHeight, filteredOffset() + (_filteredSel + 1) * st::dlgHeight); + } else if (_peopleSel >= 0 && _peopleSel < _peopleResults.size()) { + emit mustScrollTo(peopleOffset() + _peopleSel * st::dlgHeight + (_peopleSel ? 0 : -st::searchedBarHeight), peopleOffset() + (_peopleSel + 1) * st::dlgHeight); } else { - emit mustScrollTo(searchedOffset() + searchedSel * st::dlgHeight + (searchedSel ? 0 : -st::searchedBarHeight), searchedOffset() + (searchedSel + 1) * st::dlgHeight); + emit mustScrollTo(searchedOffset() + _searchedSel * st::dlgHeight + (_searchedSel ? 0 : -st::searchedBarHeight), searchedOffset() + (_searchedSel + 1) * st::dlgHeight); } } update(); @@ -1088,16 +1135,16 @@ void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) { } } else if (_state == FilteredState || _state == SearchedState) { if (msgId) { - for (int32 i = 0, c = searchResults.size(); i < c; ++i) { - if (searchResults[i]->_item->history()->peer->id == peer && searchResults[i]->_item->id == msgId) { + for (int32 i = 0, c = _searchResults.size(); i < c; ++i) { + if (_searchResults[i]->_item->history()->peer->id == peer && _searchResults[i]->_item->id == msgId) { fromY = searchedOffset() + i * st::dlgHeight; break; } } } if (fromY < 0) { - for (int32 i = 0, c = filterResults.size(); i < c; ++i) { - if (filterResults[i]->history->peer->id == peer) { + for (int32 i = 0, c = _filterResults.size(); i < c; ++i) { + if (_filterResults[i]->history->peer->id == peer) { fromY = filteredOffset() + (i * st::dlgHeight); break; } @@ -1176,33 +1223,33 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) { } else if (_state == FilteredState || _state == SearchedState) { int32 from = (yFrom - filteredOffset()) / st::dlgHeight; if (from < 0) from = 0; - if (from < filterResults.size()) { + if (from < _filterResults.size()) { int32 to = (yTo / int32(st::dlgHeight)) + 1, w = width(); - if (to > filterResults.size()) to = filterResults.size(); + if (to > _filterResults.size()) to = _filterResults.size(); for (; from < to; ++from) { - filterResults[from]->history->peer->photo->load(); + _filterResults[from]->history->peer->photo->load(); } } - from = (yFrom > filteredOffset() + st::searchedBarHeight ? ((yFrom - filteredOffset() - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - filterResults.size(); + from = (yFrom > filteredOffset() + st::searchedBarHeight ? ((yFrom - filteredOffset() - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - _filterResults.size(); if (from < 0) from = 0; - if (from < peopleResults.size()) { - int32 to = (yTo > filteredOffset() + st::searchedBarHeight ? ((yTo - filteredOffset() - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - filterResults.size() + 1, w = width(); - if (to > peopleResults.size()) to = peopleResults.size(); + if (from < _peopleResults.size()) { + int32 to = (yTo > filteredOffset() + st::searchedBarHeight ? ((yTo - filteredOffset() - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - _filterResults.size() + 1, w = width(); + if (to > _peopleResults.size()) to = _peopleResults.size(); for (; from < to; ++from) { - peopleResults[from]->photo->load(); + _peopleResults[from]->photo->load(); } } - from = (yFrom > filteredOffset() + ((peopleResults.isEmpty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight) ? ((yFrom - filteredOffset() - (peopleResults.isEmpty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - filterResults.size() - peopleResults.size(); + from = (yFrom > filteredOffset() + ((_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight) ? ((yFrom - filteredOffset() - (_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - _filterResults.size() - _peopleResults.size(); if (from < 0) from = 0; - if (from < searchResults.size()) { - int32 to = (yTo > filteredOffset() + (peopleResults.isEmpty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight ? ((yTo - filteredOffset() - (peopleResults.isEmpty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - filterResults.size() - peopleResults.size() + 1, w = width(); - if (to > searchResults.size()) to = searchResults.size(); + if (from < _searchResults.size()) { + int32 to = (yTo > filteredOffset() + (_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight ? ((yTo - filteredOffset() - (_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - _filterResults.size() - _peopleResults.size() + 1, w = width(); + if (to > _searchResults.size()) to = _searchResults.size(); for (; from < to; ++from) { - searchResults[from]->_item->history()->peer->photo->load(); + _searchResults[from]->_item->history()->peer->photo->load(); } } } @@ -1214,8 +1261,8 @@ bool DialogsInner::choosePeer() { if (_state == DefaultState) { if (sel) history = sel->history; } else if (_state == FilteredState || _state == SearchedState) { - if (hashtagSel >= 0 && hashtagSel < hashtagResults.size()) { - QString hashtag = hashtagResults.at(hashtagSel); + if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) { + QString hashtag = _hashtagResults.at(_hashtagSel); if (_overDelete) { lastMousePos = QCursor::pos(); @@ -1239,27 +1286,27 @@ bool DialogsInner::choosePeer() { } return true; } - if (filteredSel >= 0 && filteredSel < filterResults.size()) { - history = filterResults[filteredSel]->history; - } else if (peopleSel >= 0 && peopleSel < peopleResults.size()) { - history = App::history(peopleResults[peopleSel]->id); - } else if (searchedSel >= 0 && searchedSel < searchResults.size()) { - history = searchResults[searchedSel]->_item->history(); - msgId = searchResults[searchedSel]->_item->id; + if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { + history = _filterResults[_filteredSel]->history; + } else if (_peopleSel >= 0 && _peopleSel < _peopleResults.size()) { + history = App::history(_peopleResults[_peopleSel]->id); + } else if (_searchedSel >= 0 && _searchedSel < _searchResults.size()) { + history = _searchResults[_searchedSel]->_item->history(); + msgId = _searchResults[_searchedSel]->_item->id; } } if (history) { if (msgId > 0) { - saveRecentHashtags(filter); + saveRecentHashtags(_filter); } - bool chosen = (!App::main()->selectingPeer(true) && (_state == FilteredState || _state == SearchedState) && filteredSel >= 0 && filteredSel < filterResults.size()); + bool chosen = (!App::main()->selectingPeer(true) && (_state == FilteredState || _state == SearchedState) && _filteredSel >= 0 && _filteredSel < _filterResults.size()); App::main()->choosePeer(history->peer->id, msgId); if (chosen) { emit searchResultChosen(); } updateSelectedRow(); sel = 0; - filteredSel = peopleSel = searchedSel = hashtagSel = -1; + _filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1; return true; } return false; @@ -1296,12 +1343,12 @@ void DialogsInner::saveRecentHashtags(const QString &text) { void DialogsInner::destroyData() { sel = 0; contactSel = false; - hashtagSel = -1; - hashtagResults.clear(); - filteredSel = -1; - filterResults.clear(); - filter.clear(); - searchedSel = peopleSel = -1; + _hashtagSel = -1; + _hashtagResults.clear(); + _filteredSel = -1; + _filterResults.clear(); + _filter.clear(); + _searchedSel = _peopleSel = -1; clearSearchResults(); contacts.clear(); contactsNoDialogs.clear(); @@ -1337,8 +1384,8 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou return; } } else if (_state == FilteredState || _state == SearchedState) { - if (inMsg && !searchResults.isEmpty()) { - for (SearchResults::const_iterator b = searchResults.cbegin(), i = b + 1, e = searchResults.cend(); i != e; ++i) { + if (inMsg && !_searchResults.isEmpty()) { + for (SearchResults::const_iterator b = _searchResults.cbegin(), i = b + 1, e = _searchResults.cend(); i != e; ++i) { if ((*i)->_item->history()->peer == inPeer && (*i)->_item->id == inMsg) { SearchResults::const_iterator j = i - 1; outPeer = (*j)->_item->history()->peer; @@ -1346,27 +1393,27 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou return; } } - if (searchResults.at(0)->_item->history()->peer == inPeer && searchResults.at(0)->_item->id == inMsg) { + if (_searchResults.at(0)->_item->history()->peer == inPeer && _searchResults.at(0)->_item->id == inMsg) { outMsg = ShowAtUnreadMsgId; - if (peopleResults.isEmpty()) { - if (filterResults.isEmpty()) { + if (_peopleResults.isEmpty()) { + if (_filterResults.isEmpty()) { outPeer = 0; } else { - outPeer = filterResults.back()->history->peer; + outPeer = _filterResults.back()->history->peer; } } else { - outPeer = peopleResults.back(); + outPeer = _peopleResults.back(); } return; } } - if (!peopleResults.isEmpty() && peopleResults.at(0) == inPeer) { - outPeer = filterResults.isEmpty() ? 0 : filterResults.back()->history->peer; + if (!_peopleResults.isEmpty() && _peopleResults.at(0) == inPeer) { + outPeer = _filterResults.isEmpty() ? 0 : _filterResults.back()->history->peer; outMsg = ShowAtUnreadMsgId; return; } - if (!peopleResults.isEmpty()) { - for (PeopleResults::const_iterator b = peopleResults.cbegin(), i = b + 1, e = peopleResults.cend(); i != e; ++i) { + if (!_peopleResults.isEmpty()) { + for (PeopleResults::const_iterator b = _peopleResults.cbegin(), i = b + 1, e = _peopleResults.cend(); i != e; ++i) { if ((*i) == inPeer) { outPeer = (*(i - 1)); outMsg = ShowAtUnreadMsgId; @@ -1374,13 +1421,13 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou } } } - if (filterResults.isEmpty() || filterResults.at(0)->history->peer == inPeer) { + if (_filterResults.isEmpty() || _filterResults.at(0)->history->peer == inPeer) { outPeer = 0; outMsg = 0; return; } - for (FilteredDialogs::const_iterator b = filterResults.cbegin(), i = b + 1, e = filterResults.cend(); i != e; ++i) { + for (FilteredDialogs::const_iterator b = _filterResults.cbegin(), i = b + 1, e = _filterResults.cend(); i != e; ++i) { if ((*i)->history->peer == inPeer) { outPeer = (*(i - 1))->history->peer; outMsg = ShowAtUnreadMsgId; @@ -1423,7 +1470,7 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out } } else if (_state == FilteredState || _state == SearchedState) { if (inMsg) { - for (SearchResults::const_iterator i = searchResults.cbegin(), e = searchResults.cend(); i != e; ++i) { + for (SearchResults::const_iterator i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { if ((*i)->_item->history()->peer == inPeer && (*i)->_item->id == inMsg) { ++i; outPeer = (i == e) ? 0 : (*i)->_item->history()->peer; @@ -1432,12 +1479,12 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out } } } - for (PeopleResults::const_iterator i = peopleResults.cbegin(), e = peopleResults.cend(); i != e; ++i) { + for (PeopleResults::const_iterator i = _peopleResults.cbegin(), e = _peopleResults.cend(); i != e; ++i) { if ((*i) == inPeer) { ++i; - if (i == e && !searchResults.isEmpty()) { - outPeer = searchResults.front()->_item->history()->peer; - outMsg = searchResults.front()->_item->id; + if (i == e && !_searchResults.isEmpty()) { + outPeer = _searchResults.front()->_item->history()->peer; + outMsg = _searchResults.front()->_item->id; } else { outPeer = (i == e) ? 0 : (*i); outMsg = ShowAtUnreadMsgId; @@ -1445,15 +1492,15 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out return; } } - for (FilteredDialogs::const_iterator i = filterResults.cbegin(), e = filterResults.cend(); i != e; ++i) { + for (FilteredDialogs::const_iterator i = _filterResults.cbegin(), e = _filterResults.cend(); i != e; ++i) { if ((*i)->history->peer == inPeer) { ++i; - if (i == e && !peopleResults.isEmpty()) { - outPeer = peopleResults.front(); + if (i == e && !_peopleResults.isEmpty()) { + outPeer = _peopleResults.front(); outMsg = ShowAtUnreadMsgId; - } else if (i == e && !searchResults.isEmpty()) { - outPeer = searchResults.front()->_item->history()->peer; - outMsg = searchResults.front()->_item->id; + } else if (i == e && !_searchResults.isEmpty()) { + outPeer = _searchResults.front()->_item->history()->peer; + outMsg = _searchResults.front()->_item->id; } else { outPeer = (i == e) ? 0 : (*i)->history->peer; outMsg = ShowAtUnreadMsgId; @@ -1475,21 +1522,33 @@ DialogsIndexed &DialogsInner::dialogsList() { } DialogsInner::FilteredDialogs &DialogsInner::filteredList() { - return filterResults; + return _filterResults; } DialogsInner::PeopleResults &DialogsInner::peopleList() { - return peopleResults; + return _peopleResults; } DialogsInner::SearchResults &DialogsInner::searchList() { - return searchResults; + return _searchResults; +} + +int32 DialogsInner::lastSearchDate() const { + return _lastSearchDate; +} + +PeerData *DialogsInner::lastSearchPeer() const { + return _lastSearchPeer; } MsgId DialogsInner::lastSearchId() const { return _lastSearchId; } +MsgId DialogsInner::lastSearchMigratedId() const { + return _lastSearchMigratedId; +} + DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) , _dragInScroll(false) , _dragForward(false) @@ -1506,7 +1565,9 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) , _inner(&_scroll, parent) , _a_show(animFunc(this, &DialogsWidget::animStep_show)) , _searchInPeer(0) +, _searchInMigrated(0) , _searchFull(false) +, _searchFullMigrated(false) , _peopleFull(false) { _scroll.setWidget(&_inner); @@ -1777,22 +1838,26 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { SearchCache::const_iterator i = _searchCache.constFind(q); if (i != _searchCache.cend()) { _searchQuery = q; - _searchFull = false; + _searchFull = _searchFullMigrated = false; if (_searchRequest) { MTP::cancel(_searchRequest); _searchRequest = 0; } - searchReceived(true, i.value(), 0); + searchReceived(_searchInPeer ? DialogsSearchPeerFromStart : DialogsSearchFromStart, i.value(), 0); return true; } } else if (_searchQuery != q) { _searchQuery = q; - _searchFull = false; - int32 flags = (_searchInPeer && _searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchFull = _searchFullMigrated = false; if (_searchRequest) { MTP::cancel(_searchRequest); } - _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed)); + if (_searchInPeer) { + int32 flags = (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, DialogsSearchPeerFromStart)); + } else { + _searchRequest = MTP::send(MTPmessages_SearchGlobal(MTP_string(_searchQuery), MTP_int(0), MTP_inputPeerEmpty(), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, DialogsSearchFromStart), rpcFail(&DialogsWidget::searchFailed, DialogsSearchFromStart)); + } _searchQueries.insert(_searchRequest, _searchQuery); } if (!_searchInPeer && q.size() >= MinUsernameLength) { @@ -1825,10 +1890,11 @@ void DialogsWidget::onChooseByDrag() { } void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) { - if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer)) { + if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) { if (inPeer) { - _searchInPeer = inPeer; - _inner.searchInPeer(inPeer); + _searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer; + _searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0; + _inner.searchInPeer(_searchInPeer); } _filter.setText(query); _filter.updatePlaceholder(); @@ -1840,12 +1906,25 @@ void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) { } } -void DialogsWidget::onSearchMore(MsgId minMsgId) { - if (!_searchRequest && !_searchFull) { - int32 flags = (_searchInPeer && _searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; - _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed)); - if (!minMsgId) { - _searchQueries.insert(_searchRequest, _searchQuery); +void DialogsWidget::onSearchMore() { + if (!_searchRequest) { + if (!_searchFull) { + int32 offsetDate = _inner.lastSearchDate(); + PeerData *offsetPeer = _inner.lastSearchPeer(); + MsgId offsetId = _inner.lastSearchId(); + if (_searchInPeer) { + int32 flags = (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart)); + } else { + _searchRequest = MTP::send(MTPmessages_SearchGlobal(MTP_string(_searchQuery), MTP_int(offsetDate), offsetPeer ? offsetPeer->input : MTP_inputPeerEmpty(), MTP_int(offsetId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart), rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart)); + } + if (!offsetId) { + _searchQueries.insert(_searchRequest, _searchQuery); + } + } else if (_searchInMigrated && !_searchFullMigrated) { + MsgId offsetMigratedId = _inner.lastSearchMigratedId(); + int32 flags = (_searchInMigrated->isChannel() && !_searchInMigrated->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInMigrated->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetMigratedId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart), rpcFail(&DialogsWidget::searchFailed, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart)); } } } @@ -1881,12 +1960,14 @@ bool DialogsWidget::contactsFailed(const RPCError &error) { return true; } -void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req) { - if (fromStart && (_inner.state() == DialogsInner::FilteredState || _inner.state() == DialogsInner::SearchedState)) { - SearchQueries::iterator i = _searchQueries.find(req); - if (i != _searchQueries.cend()) { - _searchCache[i.value()] = result; - _searchQueries.erase(i); +void DialogsWidget::searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req) { + if (_inner.state() == DialogsInner::FilteredState || _inner.state() == DialogsInner::SearchedState) { + if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { + SearchQueries::iterator i = _searchQueries.find(req); + if (i != _searchQueries.cend()) { + _searchCache[i.value()] = result; + _searchQueries.erase(i); + } } } @@ -1897,9 +1978,12 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r App::feedUsers(d.vusers); App::feedChats(d.vchats); const QVector &msgs(d.vmessages.c_vector().v); - _inner.searchReceived(msgs, fromStart, msgs.size()); - if (msgs.isEmpty()) { - _searchFull = true; + if (!_inner.searchReceived(msgs, type, msgs.size())) { + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _searchFullMigrated = true; + } else { + _searchFull = true; + } } } break; @@ -1908,9 +1992,12 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r App::feedUsers(d.vusers); App::feedChats(d.vchats); const QVector &msgs(d.vmessages.c_vector().v); - _inner.searchReceived(msgs, fromStart, d.vcount.v); - if (msgs.isEmpty()) { - _searchFull = true; + if (!_inner.searchReceived(msgs, type, d.vcount.v)) { + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _searchFullMigrated = true; + } else { + _searchFull = true; + } } } break; @@ -1928,9 +2015,12 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r App::feedUsers(d.vusers); App::feedChats(d.vchats); const QVector &msgs(d.vmessages.c_vector().v); - _inner.searchReceived(msgs, fromStart, d.vcount.v); - if (msgs.isEmpty()) { - _searchFull = true; + if (!_inner.searchReceived(msgs, type, d.vcount.v)) { + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _searchFullMigrated = true; + } else { + _searchFull = true; + } } } break; } @@ -1965,12 +2055,16 @@ void DialogsWidget::peopleReceived(const MTPcontacts_Found &result, mtpRequestId } } -bool DialogsWidget::searchFailed(const RPCError &error, mtpRequestId req) { +bool DialogsWidget::searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req) { if (mtpIsFlood(error)) return false; if (_searchRequest == req) { _searchRequest = 0; - _searchFull = true; + if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + _searchFullMigrated = true; + } else { + _searchFull = true; + } } return true; } @@ -2072,9 +2166,9 @@ void DialogsWidget::onListScroll() { // if (!App::self()) return; _inner.loadPeerPhotos(_scroll.scrollTop()); - if (_inner.state() == DialogsInner::SearchedState) { + if (_inner.state() == DialogsInner::SearchedState || (_inner.state() == DialogsInner::FilteredState && _searchInMigrated && _searchFull && !_searchFullMigrated)) { if (_scroll.scrollTop() > (_inner.searchList().size() + _inner.filteredList().size() + _inner.peopleList().size()) * st::dlgHeight - PreloadHeightsCount * _scroll.height()) { - onSearchMore(_inner.lastSearchId()); + onSearchMore(); } } else if (_scroll.scrollTop() > _inner.dialogsList().list.count * st::dlgHeight - PreloadHeightsCount * _scroll.height()) { loadDialogs(); @@ -2105,8 +2199,9 @@ void DialogsWidget::onFilterUpdate(bool force) { void DialogsWidget::searchInPeer(PeerData *peer) { onCancelSearch(); - _searchInPeer = peer; - _inner.searchInPeer(peer); + _searchInPeer = peer ? (peer->migrateTo() ? peer->migrateTo() : peer) : 0; + _searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0; + _inner.searchInPeer(_searchInPeer); onFilterUpdate(true); } @@ -2284,7 +2379,7 @@ bool DialogsWidget::onCancelSearch() { if (!cWideMode()) { App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId); } - _searchInPeer = 0; + _searchInPeer = _searchInMigrated = 0; _inner.searchInPeer(0); clearing = true; } @@ -2304,7 +2399,7 @@ void DialogsWidget::onCancelSearchInPeer() { if (!cWideMode() && !App::main()->selectingPeer()) { App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId); } - _searchInPeer = 0; + _searchInPeer = _searchInMigrated = 0; _inner.searchInPeer(0); } _inner.clearFilter(); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 6b4034271..b14091a90 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -22,6 +22,15 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org class MainWidget; +enum DialogsSearchRequestType { + DialogsSearchFromStart, + DialogsSearchFromOffset, + DialogsSearchPeerFromStart, + DialogsSearchPeerFromOffset, + DialogsSearchMigratedFromStart, + DialogsSearchMigratedFromOffset, +}; + class DialogsInner : public SplittedWidget { Q_OBJECT @@ -32,7 +41,7 @@ public: void dialogsReceived(const QVector &dialogs); void addSavedPeersAfter(const QDateTime &date); void addAllSavedPeers(); - void searchReceived(const QVector &messages, bool fromStart, int32 fullCount); + bool searchReceived(const QVector &messages, DialogsSearchRequestType type, int32 fullCount); void peopleReceived(const QString &query, const QVector &people); void showMore(int32 pixels); @@ -86,7 +95,10 @@ public: FilteredDialogs &filteredList(); PeopleResults &peopleList(); SearchResults &searchList(); + int32 lastSearchDate() const; + PeerData *lastSearchPeer() const; MsgId lastSearchId() const; + MsgId lastSearchMigratedId() const; void setMouseSel(bool msel, bool toTop = false); @@ -144,22 +156,24 @@ private: bool contactSel; bool selByMouse; - QString filter, _hashtagFilter; + QString _filter, _hashtagFilter; - QStringList hashtagResults; - int32 hashtagSel; + QStringList _hashtagResults; + int32 _hashtagSel; - FilteredDialogs filterResults; - int32 filteredSel; + FilteredDialogs _filterResults; + int32 _filteredSel; - SearchResults searchResults; - int32 searchedCount, searchedSel; + SearchResults _searchResults; + int32 _searchedCount, _searchedMigratedCount, _searchedSel; - QString peopleQuery; - PeopleResults peopleResults; - int32 peopleSel; + QString _peopleQuery; + PeopleResults _peopleResults; + int32 _peopleSel; - MsgId _lastSearchId; + int32 _lastSearchDate; + PeerData *_lastSearchPeer; + MsgId _lastSearchId, _lastSearchMigratedId; State _state; @@ -172,7 +186,7 @@ private: bool _overDelete; - PeerData *_searchInPeer; + PeerData *_searchInPeer, *_searchInMigrated; }; @@ -184,7 +198,7 @@ public: void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req); void contactsReceived(const MTPcontacts_Contacts &contacts); - void searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req); + void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req); void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); bool addNewContact(int32 uid, bool show = true); @@ -223,7 +237,7 @@ public: DialogsIndexed &dialogsList(); void searchMessages(const QString &query, PeerData *inPeer = 0); - void onSearchMore(MsgId minMsgId); + void onSearchMore(); void itemRemoved(HistoryItem *item); void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem); @@ -260,7 +274,7 @@ private: void unreadCountsReceived(const QVector &dialogs); bool dialogsFailed(const RPCError &error, mtpRequestId req); bool contactsFailed(const RPCError &error); - bool searchFailed(const RPCError &error, mtpRequestId req); + bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req); int32 _dialogsOffset, _dialogsCount; @@ -276,11 +290,11 @@ private: anim::ivalue a_coordUnder, a_coordOver; anim::fvalue a_shadow; - PeerData *_searchInPeer; + PeerData *_searchInPeer, *_searchInMigrated; QTimer _searchTimer; QString _searchQuery, _peopleQuery; - bool _searchFull, _peopleFull; + bool _searchFull, _searchFullMigrated, _peopleFull; mtpRequestId _searchRequest, _peopleRequest; typedef QMap SearchCache; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 6f88cf71e..00e2f93a9 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -179,7 +179,11 @@ void DialogRow::paint(Painter &p, int32 w, bool act, bool sel, bool onlyBackgrou p.fillRect(fullRect, (act ? st::dlgActiveBG : (sel ? st::dlgHoverBG : st::dlgBG))->b); if (onlyBackground) return; - p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->photo->pix(st::dlgPhotoSize)); + if (history->peer->migrateTo()) { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->migrateTo()->photo->pix(st::dlgPhotoSize)); + } else { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->photo->pix(st::dlgPhotoSize)); + } int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding; int32 namewidth = w - nameleft - st::dlgPaddingHor; @@ -277,8 +281,11 @@ void FakeDialogRow::paint(Painter &p, int32 w, bool act, bool sel, bool onlyBack if (onlyBackground) return; History *history = _item->history(); - - p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->photo->pix(st::dlgPhotoSize)); + if (history->peer->migrateTo()) { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->migrateTo()->photo->pix(st::dlgPhotoSize)); + } else { + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->photo->pix(st::dlgPhotoSize)); + } int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding; int32 namewidth = w - nameleft - st::dlgPaddingHor; @@ -363,7 +370,7 @@ History::History(const PeerId &peerId) : width(0), height(0) outboxReadBefore = INT_MAX; } for (int32 i = 0; i < OverviewCount; ++i) { - overviewCount[i] = -1; // not loaded yet + overviewCountData[i] = -1; // not loaded yet } } @@ -444,11 +451,8 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) { for (History::MediaOverview::iterator i = overview[type].begin(), e = overview[type].end(); i != e; ++i) { if ((*i) == msgId) { overview[type].erase(i); - if (overviewCount[type] > 0) { - --overviewCount[type]; - if (!overviewCount[type]) { - overviewCount[type] = -1; - } + if (overviewCountData[type] > 0) { + --overviewCountData[type]; } break; } @@ -1655,7 +1659,9 @@ void History::addToOverview(HistoryItem *item, MediaOverviewType type) { if (overviewIds[type].constFind(item->id) == overviewIds[type].cend()) { overview[type].push_back(item->id); overviewIds[type].insert(item->id, NullType()); - if (overviewCount[type] > 0) ++overviewCount[type]; + if (overviewCountData[type] > 0) { + ++overviewCountData[type]; + } if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type); } } @@ -2105,7 +2111,7 @@ void History::addNewerSlice(const QVector &slice, const QVector &slice, const QVector(media)->document()->song()) { t = OverviewAudioDocuments; - if (overviewCount[t] != 0) { + if (overviewCountData[t] != 0) { overview[t].push_back(item->id); overviewIds[t].insert(item->id, NullType()); mask |= (1 << t); } } else { - if (overviewCount[t] != 0) { + if (overviewCountData[t] != 0) { overview[t].push_back(item->id); overviewIds[t].insert(item->id, NullType()); mask |= (1 << t); @@ -2142,7 +2148,7 @@ void History::addNewerSlice(const QVector &slice, const QVectorhasTextLinks()) { MediaOverviewType t = OverviewLinks; - if (overviewCount[t] != 0) { + if (overviewCountData[t] != 0) { overview[t].push_back(item->id); overviewIds[t].insert(item->id, NullType()); mask |= (1 << t); @@ -2564,9 +2570,11 @@ void History::clear(bool leaveItems) { for (int32 i = 0; i < OverviewCount; ++i) { if (!overview[i].isEmpty() || !overviewIds[i].isEmpty()) { if (leaveItems) { - if (overviewCount[i] == 0) overviewCount[i] = overview[i].size(); + if (overviewCountData[i] == 0) { + overviewCountData[i] = overview[i].size(); + } } else { - overviewCount[i] = -1; // not loaded yet + overviewCountData[i] = -1; // not loaded yet } overview[i].clear(); overviewIds[i].clear(); @@ -2599,6 +2607,86 @@ void History::clear(bool leaveItems) { if (leaveItems && App::main()) App::main()->historyCleared(this); } +void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages &result, bool onlyCounts) { + const QVector *v = 0; + switch (result.type()) { + case mtpc_messages_messages: { + const MTPDmessages_messages &d(result.c_messages_messages()); + App::feedUsers(d.vusers); + App::feedChats(d.vchats); + v = &d.vmessages.c_vector().v; + overviewCountData[overviewIndex] = 0; + } break; + + case mtpc_messages_messagesSlice: { + const MTPDmessages_messagesSlice &d(result.c_messages_messagesSlice()); + App::feedUsers(d.vusers); + App::feedChats(d.vchats); + overviewCountData[overviewIndex] = d.vcount.v; + v = &d.vmessages.c_vector().v; + } break; + + case mtpc_messages_channelMessages: { + const MTPDmessages_channelMessages &d(result.c_messages_channelMessages()); + if (peer->isChannel()) { + peer->asChannel()->ptsReceived(d.vpts.v); + } else { + LOG(("API Error: received messages.channelMessages when no channel was passed! (History::overviewSliceDone, onlyCounts %1)").arg(logBool(onlyCounts))); + } + if (d.has_collapsed()) { // should not be returned + LOG(("API Error: channels.getMessages and messages.getMessages should not return collapsed groups! (History::overviewSliceDone, onlyCounts %1)").arg(logBool(onlyCounts))); + } + + App::feedUsers(d.vusers); + App::feedChats(d.vchats); + overviewCountData[overviewIndex] = d.vcount.v; + v = &d.vmessages.c_vector().v; + } break; + + default: return; + } + + if (!onlyCounts && v->isEmpty()) { + overviewCountData[overviewIndex] = 0; + } else if (overviewCountData[overviewIndex] > 0) { + for (History::MediaOverviewIds::const_iterator i = overviewIds[overviewIndex].cbegin(), e = overviewIds[overviewIndex].cend(); i != e; ++i) { + if (i.key() < 0) { + ++overviewCountData[overviewIndex]; + } else { + break; + } + } + } + + for (QVector::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) { + HistoryItem *item = App::histories().addNewMessage(*i, NewMessageExisting); + if (item && overviewIds[overviewIndex].constFind(item->id) == overviewIds[overviewIndex].cend()) { + overviewIds[overviewIndex].insert(item->id, NullType()); + overview[overviewIndex].push_front(item->id); + } + } +} + +void History::changeMsgId(MsgId oldId, MsgId newId) { + for (int32 i = 0; i < OverviewCount; ++i) { + History::MediaOverviewIds::iterator j = overviewIds[i].find(oldId); + if (j != overviewIds[i].cend()) { + overviewIds[i].erase(j); + int32 index = overview[i].indexOf(oldId); + if (overviewIds[i].constFind(newId) == overviewIds[i].cend()) { + overviewIds[i].insert(newId, NullType()); + if (index >= 0) { + overview[i][index] = newId; + } else { + overview[i].push_back(newId); + } + } else if (index >= 0) { + overview[i].removeAt(index); + } + } + } +} + void History::blockResized(HistoryBlock *block, int32 dh) { int32 i = blocks.indexOf(block), l = blocks.size(); if (i >= 0) { @@ -2910,6 +2998,11 @@ void HistoryItem::detachFast() { _block = 0; } +void HistoryItem::setId(MsgId newId) { + history()->changeMsgId(id, newId); + id = newId; +} + HistoryItem::~HistoryItem() { itemAnimations().remove(this); App::historyUnregItem(this); @@ -6555,7 +6648,7 @@ void HistoryMessage::setViewsCount(int32 count) { void HistoryMessage::setId(MsgId newId) { bool wasPositive = (id > 0), positive = (newId > 0); - id = newId; + HistoryItem::setId(newId); if (wasPositive == positive) { if (App::main()) App::main()->msgUpdated(this); } else { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index a617c35b8..6730b63e6 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -342,20 +342,46 @@ public: QMap mySendActions; typedef QList MediaOverview; - typedef QMap MediaOverviewIds; MediaOverview overview[OverviewCount]; - MediaOverviewIds overviewIds[OverviewCount]; - int32 overviewCount[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded - bool overviewCountKnown(int32 overviewIndex) const { - return overviewCount[overviewIndex] >= 0; + bool overviewCountLoaded(int32 overviewIndex) const { + return overviewCountData[overviewIndex] >= 0; } - int32 overviewCountValue(int32 overviewIndex) const { - return (overviewCount[overviewIndex] == 0) ? overview[overviewIndex].size() : overviewCount[overviewIndex]; + bool overviewLoaded(int32 overviewIndex) const { + return overviewCount(overviewIndex) == overview[overviewIndex].size(); } + int32 overviewCount(int32 overviewIndex, int32 defaultValue = -1) const { + int32 result = overviewCountData[overviewIndex], loaded = overview[overviewIndex].size(); + if (result < 0) return defaultValue; + if (result < loaded) { + if (result > 0) { + const_cast(this)->overviewCountData[overviewIndex] = 0; + } + return loaded; + } + return result; + } + MsgId overviewMinId(int32 overviewIndex) const { + for (MediaOverviewIds::const_iterator i = overviewIds[overviewIndex].cbegin(), e = overviewIds[overviewIndex].cend(); i != e; ++i) { + if (i.key() > 0) { + return i.key(); + } + } + return 0; + } + void overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages &result, bool onlyCounts = false); + bool overviewHasMsgId(int32 overviewIndex, MsgId msgId) const { + return overviewIds[overviewIndex].constFind(msgId) != overviewIds[overviewIndex].cend(); + } + + void changeMsgId(MsgId oldId, MsgId newId); private: + typedef QMap MediaOverviewIds; + MediaOverviewIds overviewIds[OverviewCount]; + int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded + friend class HistoryBlock; friend class ChannelHistory; @@ -469,7 +495,9 @@ struct DialogsList { DialogRow *drawFrom = current; p.translate(0, drawFrom->pos * st::dlgHeight); while (drawFrom != end && drawFrom->pos * st::dlgHeight < hTo) { - drawFrom->paint(p, w, (drawFrom->history->peer == act), (drawFrom->history->peer == sel), onlyBackground); + bool active = (drawFrom->history->peer == act) || (drawFrom->history->peer->migrateTo() && drawFrom->history->peer->migrateTo() == act); + bool selected = (drawFrom->history->peer == sel); + drawFrom->paint(p, w, active, selected, onlyBackground); drawFrom = drawFrom->next; p.translate(0, st::dlgHeight); } @@ -923,9 +951,7 @@ public: } virtual void setViewsCount(int32 count) { } - virtual void setId(MsgId newId) { - id = newId; - } + virtual void setId(MsgId newId); virtual void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const = 0; virtual QString notificationHeader() const { return QString(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index b1e1fc864..946d4dc74 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1296,7 +1296,7 @@ bool MainWidget::preloadOverview(PeerData *peer, MediaOverviewType type) { if (type == OverviewCount) return false; History *h = App::history(peer->id); - if (h->overviewCount[type] >= 0 || _overviewPreload[type].constFind(peer) != _overviewPreload[type].cend()) { + if (h->overviewCountLoaded(type) || _overviewPreload[type].constFind(peer) != _overviewPreload[type].cend()) { return false; } @@ -1331,50 +1331,7 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r if (type == OverviewCount) return; - History *h = App::history(peer->id); - switch (result.type()) { - case mtpc_messages_messages: { - const MTPDmessages_messages &d(result.c_messages_messages()); - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - h->overviewCount[type] = d.vmessages.c_vector().v.size(); - } break; - - case mtpc_messages_messagesSlice: { - const MTPDmessages_messagesSlice &d(result.c_messages_messagesSlice()); - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - h->overviewCount[type] = d.vcount.v; - } break; - - case mtpc_messages_channelMessages: { - const MTPDmessages_channelMessages &d(result.c_messages_channelMessages()); - if (peer && peer->isChannel()) { - peer->asChannel()->ptsReceived(d.vpts.v); - } else { - LOG(("API Error: received messages.channelMessages when no channel was passed! (MainWidget::overviewPreloaded)")); - } - if (d.has_collapsed()) { // should not be returned - LOG(("API Error: channels.getMessages and messages.getMessages should not return collapsed groups! (MainWidget::overviewPreloaded)")); - } - - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - h->overviewCount[type] = d.vcount.v; - } break; - - default: return; - } - - if (h->overviewCount[type] > 0) { - for (History::MediaOverviewIds::const_iterator i = h->overviewIds[type].cbegin(), e = h->overviewIds[type].cend(); i != e; ++i) { - if (i.key() < 0) { - ++h->overviewCount[type]; - } else { - break; - } - } - } + App::history(peer->id)->overviewSliceDone(type, result, true); mediaOverviewUpdated(peer, type); } @@ -1390,9 +1347,9 @@ void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) { History *m = (peer && peer->migrateFrom()) ? App::historyLoaded(peer->migrateFrom()->id) : 0; if (h) { for (int32 i = 0; i < OverviewCount; ++i) { - if (!h->overview[i].isEmpty() || h->overviewCount[i] > 0 || i == overview->type()) { + if (!h->overview[i].isEmpty() || h->overviewCount(i) > 0 || i == overview->type()) { mask |= (1 << i); - } else if (m && (!m->overview[i].isEmpty() || m->overviewCount[i] > 0)) { + } else if (m && (!m->overview[i].isEmpty() || m->overviewCount(i) > 0)) { mask |= (1 << i); } } @@ -1499,22 +1456,16 @@ bool MainWidget::overviewFailed(PeerData *peer, const RPCError &error, mtpReques void MainWidget::loadMediaBack(PeerData *peer, MediaOverviewType type, bool many) { if (_overviewLoad[type].constFind(peer) != _overviewLoad[type].cend()) return; - MsgId minId = 0; - History *hist = App::history(peer->id); - if (hist->overviewCount[type] == 0) return; // all loaded + History *history = App::history(peer->id); + if (history->overviewLoaded(type)) return; - for (History::MediaOverviewIds::const_iterator i = hist->overviewIds[type].cbegin(), e = hist->overviewIds[type].cend(); i != e; ++i) { - if (i.key() > 0) { - minId = i.key(); - break; - } - } - int32 limit = many ? SearchManyPerPage : (hist->overview[type].size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage; + MsgId minId = history->overviewMinId(type); + int32 limit = many ? SearchManyPerPage : (history->overview[type].size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage; MTPMessagesFilter filter = typeToMediaFilter(type); if (type == OverviewCount) return; int32 flags = (peer->isChannel() && !peer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; - _overviewLoad[type].insert(peer, MTP::send(MTPmessages_Search(MTP_int(flags), peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::overviewLoaded, hist))); + _overviewLoad[type].insert(peer, MTP::send(MTPmessages_Search(MTP_int(flags), peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::overviewLoaded, history))); } void MainWidget::peerUsernameChanged(PeerData *peer) { @@ -1542,11 +1493,11 @@ void MainWidget::showNewGroup() { dialogs.onNewGroup(); } -void MainWidget::overviewLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req) { +void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req) { OverviewsPreload::iterator it; MediaOverviewType type = OverviewCount; for (int32 i = 0; i < OverviewCount; ++i) { - it = _overviewLoad[i].find(h->peer); + it = _overviewLoad[i].find(history->peer); if (it != _overviewLoad[i].cend()) { type = MediaOverviewType(i); _overviewLoad[i].erase(it); @@ -1555,65 +1506,9 @@ void MainWidget::overviewLoaded(History *h, const MTPmessages_Messages &msgs, mt } if (type == OverviewCount) return; - const QVector *v = 0; - switch (msgs.type()) { - case mtpc_messages_messages: { - const MTPDmessages_messages &d(msgs.c_messages_messages()); - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - v = &d.vmessages.c_vector().v; - h->overviewCount[type] = 0; - } break; + history->overviewSliceDone(type, result); - case mtpc_messages_messagesSlice: { - const MTPDmessages_messagesSlice &d(msgs.c_messages_messagesSlice()); - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - h->overviewCount[type] = d.vcount.v; - v = &d.vmessages.c_vector().v; - } break; - - case mtpc_messages_channelMessages: { - const MTPDmessages_channelMessages &d(msgs.c_messages_channelMessages()); - if (h && h->peer->isChannel()) { - h->peer->asChannel()->ptsReceived(d.vpts.v); - } else { - LOG(("API Error: received messages.channelMessages when no channel was passed! (MainWidget::overviewLoaded)")); - } - if (d.has_collapsed()) { // should not be returned - LOG(("API Error: channels.getMessages and messages.getMessages should not return collapsed groups! (MainWidget::overviewLoaded)")); - } - - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - h->overviewCount[type] = d.vcount.v; - v = &d.vmessages.c_vector().v; - } break; - - default: return; - } - - if (h->overviewCount[type] > 0) { - for (History::MediaOverviewIds::const_iterator i = h->overviewIds[type].cbegin(), e = h->overviewIds[type].cend(); i != e; ++i) { - if (i.key() < 0) { - ++h->overviewCount[type]; - } else { - break; - } - } - } - if (v->isEmpty()) { - h->overviewCount[type] = 0; - } - - for (QVector::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) { - HistoryItem *item = App::histories().addNewMessage(*i, NewMessageExisting); - if (item && h->overviewIds[type].constFind(item->id) == h->overviewIds[type].cend()) { - h->overviewIds[type].insert(item->id, NullType()); - h->overview[type].push_front(item->id); - } - } - if (App::wnd()) App::wnd()->mediaOverviewUpdated(h->peer, type); + if (App::wnd()) App::wnd()->mediaOverviewUpdated(history->peer, type); } void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) { @@ -4263,22 +4158,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { HistoryItem *msgRow = App::histItemById(msg); if (msgRow) { App::historyUnregItem(msgRow); - History *h = msgRow->history(); - for (int32 i = 0; i < OverviewCount; ++i) { - History::MediaOverviewIds::iterator j = h->overviewIds[i].find(msgRow->id); - if (j != h->overviewIds[i].cend()) { - h->overviewIds[i].erase(j); - if (h->overviewIds[i].constFind(d.vid.v) == h->overviewIds[i].cend()) { - h->overviewIds[i].insert(d.vid.v, NullType()); - for (int32 k = 0, l = h->overview[i].size(); k != l; ++k) { - if (h->overview[i].at(k) == msgRow->id) { - h->overview[i][k] = d.vid.v; - break; - } - } - } - } - } if (App::wnd()) App::wnd()->changingMsgId(msgRow, d.vid.v); msgRow->setId(d.vid.v); if (msgRow->history()->peer->isSelf()) { @@ -4287,6 +4166,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { if (!App::historyRegItem(msgRow)) { msgUpdated(msgRow); } else { + History *h = msgRow->history(); bool wasLast = (h->lastMsg == msgRow); msgRow->destroy(); if (wasLast && !h->lastMsg) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 4eeac7eb7..8bb36a983 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -490,7 +490,7 @@ private: void readRequestDone(PeerData *peer); void messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result); - void overviewLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req); + void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req); bool _started; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 7c0d23b4b..21ee4d867 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -345,7 +345,7 @@ void MediaView::updateControls() { _dateText = lng_mediaview_date_time(lt_date, d.date().toString(qsl("dd.MM.yy")), lt_time, d.time().toString(cTimeFormat())); } if (_from) { - _fromName.setText(st::mvFont, _from->name); + _fromName.setText(st::mvFont, (_from->migrateTo() ? _from->migrateTo() : _from)->name); _nameNav = myrtlrect(st::mvTextLeft, height() - st::mvTextTop, qMin(_fromName.maxWidth(), width() / 3), st::mvFont->height); _dateNav = myrtlrect(st::mvTextLeft + _nameNav.width() + st::mvTextSkip, height() - st::mvTextTop, st::mvFont->width(_dateText), st::mvFont->height); } else { @@ -355,15 +355,15 @@ void MediaView::updateControls() { updateHeader(); if (_photo || (_history && (_overview == OverviewPhotos || _overview == OverviewDocuments))) { _leftNavVisible = (_index > 0) || (_index == 0 && ( - (!_msgmigrated && _history && _history->overview[_overview].size() < _history->overviewCount[_overview]) || - (_msgmigrated && _migrated && _migrated->overview[_overview].size() < _migrated->overviewCount[_overview]) || - (!_msgmigrated && _history && _migrated && (!_migrated->overview[_overview].isEmpty() || _migrated->overviewCount[_overview] > 0)))); + (!_msgmigrated && _history && _history->overview[_overview].size() < _history->overviewCount(_overview)) || + (_msgmigrated && _migrated && _migrated->overview[_overview].size() < _migrated->overviewCount(_overview)) || + (!_msgmigrated && _history && _migrated && (!_migrated->overview[_overview].isEmpty() || _migrated->overviewCount(_overview) > 0)))); _rightNavVisible = (_index >= 0) && ( (!_msgmigrated && _history && _index + 1 < _history->overview[_overview].size()) || (_msgmigrated && _migrated && _index + 1 < _migrated->overview[_overview].size()) || - (_msgmigrated && _migrated && _history && (!_history->overview[_overview].isEmpty() || _history->overviewCount[_overview] > 0)) || + (_msgmigrated && _migrated && _history && (!_history->overview[_overview].isEmpty() || _history->overviewCount(_overview) > 0)) || (!_history && _user && (_index + 1 < _user->photos.size() || _index + 1 < _user->photosCount))); - if (_msgmigrated && _history->overview[_overview].size() < _history->overviewCountValue(_overview)) { + if (_msgmigrated && !_history->overviewLoaded(_overview)) { _leftNavVisible = _rightNavVisible = false; } } else { @@ -1480,7 +1480,7 @@ void MediaView::moveToNext(int32 delta) { if (_index < 0 || (_history && _overview != OverviewPhotos && _overview != OverviewDocuments) || (_overview == OverviewCount && !_user)) { return; } - if (_msgmigrated && _history->overview[_overview].size() < _history->overviewCountValue(_overview)) { + if (_msgmigrated && !_history->overviewLoaded(_overview)) { return; } @@ -1491,7 +1491,7 @@ void MediaView::moveToNext(int32 delta) { newIndex += _migrated->overview[_overview].size(); newMigrated = true; } else if (newMigrated && newIndex >= _migrated->overview[_overview].size()) { - newIndex -= _migrated->overview[_overview].size() + (_history->overviewCountValue(_overview) - _history->overview[_overview].size()); + newIndex -= _migrated->overview[_overview].size() + (_history->overviewCount(_overview) - _history->overview[_overview].size()); newMigrated = false; } if (newIndex >= 0 && newIndex < (newMigrated ? _migrated : _history)->overview[_overview].size()) { @@ -1540,7 +1540,7 @@ void MediaView::preloadData(int32 delta) { int32 previewIndex = i; if (_msgmigrated && previewIndex >= _migrated->overview[_overview].size()) { previewHistory = _history; - previewIndex -= _migrated->overview[_overview].size() + (_history->overviewCountValue(_overview) - _history->overview[_overview].size()); + previewIndex -= _migrated->overview[_overview].size() + (_history->overviewCount(_overview) - _history->overview[_overview].size()); } else if (!_msgmigrated && previewIndex < 0) { previewHistory = _migrated; previewIndex += _migrated->overview[_overview].size(); @@ -1561,7 +1561,7 @@ void MediaView::preloadData(int32 delta) { History *forgetHistory = _msgmigrated ? _migrated : _history; if (_msgmigrated && forgetIndex >= _migrated->overview[_overview].size()) { forgetHistory = _history; - forgetIndex -= _migrated->overview[_overview].size() + (_history->overviewCountValue(_overview) - _history->overview[_overview].size()); + forgetIndex -= _migrated->overview[_overview].size() + (_history->overviewCount(_overview) - _history->overview[_overview].size()); } else if (!_msgmigrated && forgetIndex < 0) { forgetHistory = _migrated; forgetIndex += _migrated->overview[_overview].size(); @@ -1985,10 +1985,10 @@ void MediaView::findCurrent() { break; } } - if (_history->overviewCount[_overview] < 0) { + if (!_history->overviewCountLoaded(_overview)) { loadBack(); - } else if (_history->overviewCountValue(_overview) <= _history->overview[_overview].size()) { // all loaded - if (_migrated->overviewCount[_overview] < 0 || (_index < 2 && _migrated->overviewCount[_overview] > 0)) { + } else if (_history->overviewLoaded(_overview) && !_migrated->overviewLoaded(_overview)) { // all loaded + if (!_migrated->overviewCountLoaded(_overview) || (_index < 2 && _migrated->overviewCount(_overview) > 0)) { loadBack(); } } @@ -1999,10 +1999,14 @@ void MediaView::findCurrent() { break; } } - if (_history->overviewCount[_overview] < 0 || (_index < 2 && _history->overviewCount[_overview] > 0) || (_index < 1 && _migrated && _migrated->overviewCount[_overview] != 0)) { + if (!_history->overviewLoaded(_overview)) { + if (!_history->overviewCountLoaded(_overview) || (_index < 2 && _history->overviewCount(_overview) > 0) || (_index < 1 && _migrated && !_migrated->overviewLoaded(_overview))) { + loadBack(); + } + } else if (_index < 1 && _migrated && !_migrated->overviewLoaded(_overview)) { loadBack(); } - if (_migrated && _migrated->overviewCount[_overview] < 0) { + if (_migrated && !_migrated->overviewCountLoaded(_overview)) { App::main()->preloadOverview(_migrated->peer, _overview); } } @@ -2011,17 +2015,17 @@ void MediaView::findCurrent() { void MediaView::loadBack() { if (_loadRequest || _index < 0 || (_overview == OverviewCount && !_user)) return; - if (_history && _overview != OverviewCount && (_history->overviewCount[_overview] != 0 || (_migrated && _migrated->overviewCount[_overview] != 0))) { + if (_history && _overview != OverviewCount && (!_history->overviewLoaded(_overview) || (_migrated && !_migrated->overviewLoaded(_overview)))) { if (App::main()) { - if (_msgmigrated || (_migrated && _index == 0 && _history->overviewCount[_overview] >= 0 && _history->overviewCountValue(_overview) <= _history->overview[_overview].size())) { + if (_msgmigrated || (_migrated && _index == 0 && _history->overviewLoaded(_overview))) { App::main()->loadMediaBack(_migrated->peer, _overview); } else { App::main()->loadMediaBack(_history->peer, _overview); - if (_migrated && _index == 0 && _migrated->overviewCount[_overview] != 0 && _migrated->overview[_overview].isEmpty()) { + if (_migrated && _index == 0 && _migrated->overview[_overview].isEmpty() && !_migrated->overviewLoaded(_overview)) { App::main()->loadMediaBack(_migrated->peer, _overview); } } - if (_msgmigrated && _history->overviewCount[_overview] < 0) { + if (_msgmigrated && !_history->overviewCountLoaded(_overview)) { App::main()->preloadOverview(_history->peer, _overview); } } @@ -2068,14 +2072,14 @@ void MediaView::userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mt } void MediaView::updateHeader() { - int32 index = _index, count = 0, addcount = (_migrated && _overview != OverviewCount) ? _migrated->overviewCountValue(_overview) : 0; + int32 index = _index, count = 0, addcount = (_migrated && _overview != OverviewCount) ? _migrated->overviewCount(_overview) : 0; if (_history) { if (_overview != OverviewCount) { - count = _history->overviewCountValue(_overview); + count = _history->overviewCount(_overview); if (addcount >= 0 && count >= 0) { count += addcount; } - if (index >= 0 && (_msgmigrated ? (count >= 0 && addcount >= 0 && _history->overviewCountValue(_overview) <= _history->overview[_overview].size()) : (count >= 0))) { + if (index >= 0 && (_msgmigrated ? (count >= 0 && addcount >= 0 && _history->overviewLoaded(_overview)) : (count >= 0))) { if (_msgmigrated) { index += addcount - _migrated->overview[_overview].size(); } else { diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 090e7f116..f9bcfe432 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -136,16 +136,16 @@ int32 OverviewInner::CachedLink::countHeight(int32 w) { // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html -OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const PeerData *peer, MediaOverviewType type) : QWidget(0) +OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerData *peer, MediaOverviewType type) : QWidget(0) , _overview(overview) , _scroll(scroll) , _resizeIndex(-1) , _resizeSkip(0) -, _peer(App::peer(peer->id)) +, _peer(peer->migrateTo() ? peer->migrateTo() : peer) , _type(type) -, _migrated(0) -, _history(App::history(peer->id)) -, _channel(peerToChannel(peer->id)) +, _migrated(_peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0) +, _history(App::history(_peer->id)) +, _channel(peerToChannel(_peer->id)) , _photosInRow(1) , _photosToAdd(0) , _selMode(false) @@ -159,8 +159,10 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const , _itemsToBeLoaded(LinksOverviewPerPage * 2) , _inSearch(false) , _searchFull(false) +, _searchFullMigrated(false) , _searchRequest(0) , _lastSearchId(0) +, _lastSearchMigratedId(0) , _searchedCount(0) , _width(st::wndMinWidth) , _height(0) @@ -169,7 +171,8 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const , _cursor(style::cur_default) , _cursorState(HistoryDefaultCursorState) , _dragAction(NoDrag) -, _dragItem(0), _selectedMsgId(0) +, _dragItem(0) +, _selectedMsgId(0) , _dragItemIndex(-1) , _mousedItem(0) , _mousedItemIndex(-1) @@ -272,16 +275,35 @@ void OverviewInner::touchUpdateSpeed() { _touchPrevPos = _touchPos; } +bool OverviewInner::itemMigrated(MsgId msgId) const { + return _migrated && (msgId < 0) && (-msgId < ServerMaxMsgId); +} + +ChannelId OverviewInner::itemChannel(MsgId msgId) const { + return itemMigrated(msgId) ? _migrated->channelId() : _channel; +} + +MsgId OverviewInner::itemMsgId(MsgId msgId) const { + return itemMigrated(msgId) ? -msgId : msgId; +} + +int32 OverviewInner::migratedIndexSkip() const { + return (_migrated && _history->overviewLoaded(_type)) ? _migrated->overview[_type].size() : 0; +} + void OverviewInner::fixItemIndex(int32 ¤t, MsgId msgId) const { if (!msgId) { current = -1; } else if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { - int32 l = _history->overview[_type].size(); - if (current < 0 || current >= l || _history->overview[_type][current] != msgId) { + History *history = itemMigrated(msgId) ? _migrated : _history; + int32 l = history->overview[_type].size(), indexskip = migratedIndexSkip(); + int32 index = (current >= 0 && history == _history) ? (current - indexskip) : current; + MsgId findMsgId = (history == _history ? 1 : -1) * msgId; + if (current < 0 || current >= l || history->overview[_type][current] != findMsgId) { current = -1; for (int32 i = 0; i < l; ++i) { - if (_history->overview[_type][i] == msgId) { - current = i; + if (history->overview[_type][i] == findMsgId) { + current = i + (history == _history ? indexskip : 0); break; } } @@ -300,12 +322,14 @@ void OverviewInner::fixItemIndex(int32 ¤t, MsgId msgId) const { } } -void OverviewInner::searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req) { - if (fromStart && !_search.text().isEmpty()) { - SearchQueries::iterator i = _searchQueries.find(req); - if (i != _searchQueries.cend()) { - _searchCache[i.value()] = result; - _searchQueries.erase(i); +void OverviewInner::searchReceived(SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req) { + if (!_search.text().isEmpty()) { + if (_type == SearchFromStart) { + SearchQueries::iterator i = _searchQueries.find(req); + if (i != _searchQueries.cend()) { + _searchCache[i.value()] = result; + _searchQueries.erase(i); + } } } @@ -346,20 +370,36 @@ void OverviewInner::searchReceived(bool fromStart, const MTPmessages_Messages &r } break; } if (messages) { + bool migratedSearch = (type == SearchMigratedFromStart || type == SearchMigratedFromOffset); if (messages->isEmpty()) { - _searchFull = true; + if (migratedSearch) { + _searchFullMigrated = true; + } else { + _searchFull = true; + } } - if (fromStart) { + if (type == SearchFromStart) { _searchResults.clear(); - _lastSearchId = 0; + _lastSearchId = _lastSearchMigratedId = 0; _itemsToBeLoaded = LinksOverviewPerPage * 2; } + if (type == SearchMigratedFromStart) { + _lastSearchMigratedId = 0; + } for (QVector::const_iterator i = messages->cbegin(), e = messages->cend(); i != e; ++i) { HistoryItem *item = App::histories().addNewMessage(*i, NewMessageExisting); - _searchResults.push_front(item->id); - _lastSearchId = item->id; + if (migratedSearch) { + _searchResults.push_front(-item->id); + _lastSearchMigratedId = item->id; + } else { + _searchResults.push_front(item->id); + _lastSearchId = item->id; + } } mediaOverviewUpdated(); + if (messages->isEmpty()) { + update(); + } } _searchRequest = 0; @@ -367,19 +407,24 @@ void OverviewInner::searchReceived(bool fromStart, const MTPmessages_Messages &r } } -bool OverviewInner::searchFailed(const RPCError &error, mtpRequestId req) { +bool OverviewInner::searchFailed(SearchRequestType type, const RPCError &error, mtpRequestId req) { if (mtpIsFlood(error)) return false; if (_searchRequest == req) { _searchRequest = 0; - _searchFull = true; + if (type == SearchFromStart || type == SearchFromOffset) { + _searchFull = true; + } else if (type == SearchMigratedFromStart || type == SearchMigratedFromOffset) { + _searchFullMigrated = true; + } } return true; } OverviewInner::CachedLink *OverviewInner::cachedLink(HistoryItem *item) { - CachedLinks::const_iterator i = _links.constFind(item->id); - if (i == _links.cend()) i = _links.insert(item->id, new CachedLink(item)); + MsgId msgId = (item->history() == _migrated) ? -item->id : item->id; + CachedLinks::const_iterator i = _links.constFind(msgId); + if (i == _links.cend()) i = _links.insert(msgId, new CachedLink(item)); return i.value(); } @@ -423,7 +468,7 @@ bool OverviewInner::itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) con return true; } } else { - HistoryItem *item = App::histItemById(_channel, msgId); + HistoryItem *item = App::histItemById(itemChannel(msgId), itemMsgId(msgId)); HistoryMedia *media = item ? item->getMedia(true) : 0; if (media) { int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); @@ -462,11 +507,12 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 index += delta; if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { - if (index < 0 || index >= _history->overview[_type].size()) { + int32 indexskip = migratedIndexSkip(); + if (index < 0 || index >= indexskip + _history->overview[_type].size()) { msgId = 0; index = -1; } else { - msgId = _history->overview[_type][index]; + msgId = (index >= indexskip) ? _history->overview[_type][index - indexskip] : (-_migrated->overview[_type][index]); } } else { while (index >= 0 && index < _items.size() && !_items[index].msgid) { @@ -739,7 +785,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu } if (_dragAction == PrepareSelect && !needClick && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { SelectedItems::iterator i = _selected.find(_dragItem); - if (i == _selected.cend() && _dragItem > 0) { + if (i == _selected.cend() && itemMsgId(_dragItem) > 0) { if (_selected.size() < MaxSelectedItems) { if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { _selected.clear(); @@ -755,7 +801,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu if (i != _selected.cend() && i.value() == FullItemSel) { _selected.erase(i); updateMsg(_dragItem, _dragItemIndex); - } else if (i == _selected.cend() && _dragItem > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + } else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { if (_selected.size() < MaxSelectedItems) { _selected.insert(_dragItem, FullItemSel); updateMsg(_dragItem, _dragItemIndex); @@ -797,7 +843,7 @@ void OverviewInner::onDragExec() { QList urls; bool forwardSelected = false; if (uponSelected) { - forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode() && !_history->peer->isChannel(); + forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode(); } else if (textlnkDown()) { sel = textlnkDown()->encoded(); if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') { @@ -841,9 +887,7 @@ void OverviewInner::onDragExec() { QDrag *drag = new QDrag(App::wnd()); QMimeData *mimeData = new QMimeData; - if (!_history->peer->isChannel()) { - mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); - } + mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); if (lnkDocument) { QString already = static_cast(textlnkDown().data())->document()->already(true); if (!already.isEmpty()) { @@ -867,42 +911,60 @@ void OverviewInner::touchScrollUpdated(const QPoint &screenPos) { touchUpdateSpeed(); } +void OverviewInner::addSelectionRange(int32 selFrom, int32 selTo, History *history) { + if (selFrom < 0 || selTo < 0) return; + for (int32 i = selFrom; i <= selTo; ++i) { + MsgId msgid = 0; + if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { + msgid = ((history == _history) ? 1 : -1) * history->overview[_type][i]; + } else { + msgid = _items[i].msgid; + } + if (!msgid) continue; + + SelectedItems::iterator j = _selected.find(msgid); + if (_dragSelecting && itemMsgId(msgid) > 0) { + if (j == _selected.cend()) { + if (_selected.size() >= MaxSelectedItems) break; + _selected.insert(msgid, FullItemSel); + } else if (j.value() != FullItemSel) { + *j = FullItemSel; + } + } else { + if (j != _selected.cend()) { + _selected.erase(j); + } + } + } +} + void OverviewInner::applyDragSelection() { if (_dragSelFromIndex < 0 || _dragSelToIndex < 0) return; if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { _selected.clear(); } - if (_dragSelecting) { - for (int32 i = _dragSelToIndex; i <= _dragSelFromIndex; ++i) { - MsgId msgid = (_type == OverviewPhotos || _type == OverviewAudioDocuments) ? _history->overview[_type][i] : _items[i].msgid; - if (!msgid) continue; - - SelectedItems::iterator j = _selected.find(msgid); - if (msgid > 0) { - if (j == _selected.cend()) { - if (_selected.size() >= MaxSelectedItems) break; - _selected.insert(msgid, FullItemSel); - } else if (j.value() != FullItemSel) { - *j = FullItemSel; - } + int32 selfrom = _dragSelToIndex, selto = _dragSelFromIndex; + if (_migrated && (_type == OverviewPhotos || _type == OverviewAudioDocuments)) { + int32 indexskip = migratedIndexSkip(); + if (selfrom < indexskip) { + if (selto < indexskip) { + addSelectionRange(selfrom, selto, _migrated); + selto = -1; } else { - if (j != _selected.cend()) { - _selected.erase(j); - } - } - } - } else { - for (int32 i = _dragSelToIndex; i <= _dragSelFromIndex; ++i) { - MsgId msgid = (_type == OverviewPhotos || _type == OverviewAudioDocuments) ? _history->overview[_type][i] : _items[i].msgid; - if (!msgid) continue; - - SelectedItems::iterator j = _selected.find(msgid); - if (j != _selected.cend()) { - _selected.erase(j); + addSelectionRange(selfrom, _migrated->overview[_type].size() - 1, _migrated); + selto -= indexskip; } + selfrom = 0; + } else if (selto < indexskip) { // wtf + selfrom = selto = -1; + } else { + selfrom -= indexskip; + selto -= indexskip; } } + addSelectionRange(selfrom, selto, _history); + _dragSelFrom = _dragSelTo = 0; _dragSelFromIndex = _dragSelToIndex = -1; _overview->updateTopBarSelection(); @@ -940,9 +1002,14 @@ void OverviewInner::clear() { } int32 OverviewInner::itemTop(const FullMsgId &msgId) const { - if (_type == OverviewAudioDocuments && msgId.channel == _channel) { - int32 index = _history->overview[_type].indexOf(msgId.msg); - if (index >= 0) { + if (_type == OverviewAudioDocuments) { + if (msgId.channel == _channel) { + int32 index = _history->overview[_type].indexOf(msgId.msg); + if (index >= 0) { + return _addToY + int32((index + migratedIndexSkip()) * _audioHeight); + } + } else if (_migrated && msgId.channel == _migrated->channelId()) { + int32 index = _migrated->overview[_type].indexOf(msgId.msg); return _addToY + int32(index * _audioHeight); } } @@ -951,21 +1018,30 @@ int32 OverviewInner::itemTop(const FullMsgId &msgId) const { void OverviewInner::preloadMore() { if (_inSearch) { - if (!_searchRequest && !_searchFull) { - int32 flags = (_history->peer->isChannel() && !_history->peer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; - _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _history->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, !_lastSearchId), rpcFail(&OverviewInner::searchFailed)); - if (!_lastSearchId) { - _searchQueries.insert(_searchRequest, _searchQuery); + if (!_searchRequest) { + if (!_searchFull) { + int32 flags = (_history->peer->isChannel() && !_history->peer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _history->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, _lastSearchId ? SearchFromOffset : SearchFromStart), rpcFail(&OverviewInner::searchFailed, _lastSearchId ? SearchFromOffset : SearchFromStart)); + if (!_lastSearchId) { + _searchQueries.insert(_searchRequest, _searchQuery); + } + } else if (_migrated && !_searchFullMigrated) { + int32 flags = (_migrated->peer->isChannel() && !_migrated->peer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _migrated->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchMigratedId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, _lastSearchMigratedId ? SearchMigratedFromOffset : SearchMigratedFromStart), rpcFail(&OverviewInner::searchFailed, _lastSearchMigratedId ? SearchMigratedFromOffset : SearchMigratedFromStart)); } } } else if (App::main()) { - App::main()->loadMediaBack(_history->peer, _type, _type != OverviewLinks); + if (_migrated && _history->overviewLoaded(_type)) { + App::main()->loadMediaBack(_migrated->peer, _type, _type != OverviewLinks); + } else { + App::main()->loadMediaBack(_history->peer, _type, _type != OverviewLinks); + } } } bool OverviewInner::preloadLocal() { if (_type != OverviewLinks) return false; - if (_itemsToBeLoaded >= _history->overview[_type].size()) return false; + if (_itemsToBeLoaded >= migratedIndexSkip() + _history->overview[_type].size()) return false; _itemsToBeLoaded += LinksOverviewPerPage; mediaOverviewUpdated(); return true; @@ -1000,11 +1076,11 @@ void OverviewInner::paintEvent(QPaintEvent *e) { QRect r(e->rect()); p.setClipRect(r); - if (_history->overview[_type].isEmpty()) { + if (_history->overview[_type].isEmpty() && (!_migrated || !_history->overviewLoaded(_type) || _migrated->overview[_type].isEmpty())) { QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9); p.drawPixmap(dogPos, *cChatDogImage()); return; - } else if (_inSearch && _searchResults.isEmpty() && _searchFull && !_searchTimer.isActive()) { + } else if (_inSearch && _searchResults.isEmpty() && _searchFull && (!_migrated || _searchFullMigrated) && !_searchTimer.isActive()) { p.setFont(st::noContactsFont->f); p.setPen(st::noContactsColor->p); p.drawText(QRect(_linksLeft, _addToY, _linksWidth, _addToY), lng_search_found_results(lt_count, 0), style::al_center); @@ -1021,8 +1097,9 @@ void OverviewInner::paintEvent(QPaintEvent *e) { bool hasSel = !_selected.isEmpty(); if (_type == OverviewPhotos) { - History::MediaOverview &overview(_history->overview[_type]); - int32 count = overview.size(); + History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migratedCount = migratedIndexSkip(); + int32 count = migratedCount + overview.size(); int32 rowFrom = floorclamp(r.y() - _addToY - st::overviewPhotoSkip, _vsize + st::overviewPhotoSkip, 0, count); int32 rowTo = ceilclamp(r.y() + r.height() - _addToY - st::overviewPhotoSkip, _vsize + st::overviewPhotoSkip, 0, count); float64 w = float64(_width - st::overviewPhotoSkip) / _photosInRow; @@ -1033,7 +1110,10 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (index < 0) continue; if (index >= count) break; - HistoryItem *item = App::histItemById(_channel, overview[index]); + bool migratedindex = (index < migratedCount); + int32 bareindex = migratedindex ? index : (index - migratedCount); + + HistoryItem *item = App::histItemById(migratedindex ? _migrated->channelId() : _channel, (migratedindex ? *migratedOverview : overview)[bareindex]); HistoryMedia *m = item ? item->getMedia(true) : 0; if (!m) continue; @@ -1088,7 +1168,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (index >= selfrom && index <= selto) { sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; } else if (hasSel) { - SelectedItems::const_iterator i = _selected.constFind(item->id); + SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); if (i != selEnd) { sel = i.value(); } @@ -1104,15 +1184,19 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } } } else if (_type == OverviewAudioDocuments) { - History::MediaOverview &overview(_history->overview[_type]); - int32 count = overview.size(); + History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migratedCount = migratedIndexSkip(); + int32 count = migratedCount + overview.size(); int32 from = floorclamp(r.y() - _addToY, _audioHeight, 0, count); int32 to = ceilclamp(r.y() + r.height() - _addToY, _audioHeight, 0, count); p.translate(_audioLeft, _addToY + from * _audioHeight); for (int32 index = from; index < to; ++index) { if (index >= count) break; - HistoryItem *item = App::histItemById(_channel, overview[index]); + bool migratedindex = (index < migratedCount); + int32 bareindex = migratedindex ? index : (index - migratedCount); + + HistoryItem *item = App::histItemById(migratedindex ? _migrated->channelId() : _channel, (migratedindex ? *migratedOverview : overview)[bareindex]); HistoryMedia *m = item ? item->getMedia(true) : 0; if (!m || m->type() != MediaTypeDocument) continue; @@ -1120,13 +1204,14 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (index >= selfrom && index <= selto) { sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; } else if (hasSel) { - SelectedItems::const_iterator i = _selected.constFind(item->id); + SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); if (i != selEnd) { sel = i.value(); } } - static_cast(m)->drawInPlaylist(p, item, (sel == FullItemSel), ((_menu ? (App::contextItem() ? App::contextItem()->id : 0) : _selectedMsgId) == item->id), _audioWidth); + bool drawOver = _menu ? (App::contextItem() ? (App::contextItem() == item) : false) : (itemMsgId(_selectedMsgId) == item->id && itemChannel(_selectedMsgId) == item->channelId()); + static_cast(m)->drawInPlaylist(p, item, (sel == FullItemSel), drawOver, _audioWidth); p.translate(0, _audioHeight); } } else if (_type == OverviewLinks) { @@ -1171,7 +1256,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { uint32 sel = 0; if (i >= selfrom && i <= selto) { - sel = (_dragSelecting && _items[i].msgid > 0) ? FullItemSel : 0; + sel = (_dragSelecting && itemMsgId(_items[i].msgid) > 0) ? FullItemSel : 0; } else if (hasSel) { SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); if (j != selEnd) { @@ -1231,7 +1316,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.translate(0, curY - y); if (_items[i].msgid) { // draw item - HistoryItem *item = App::histItemById(_channel, _items[i].msgid); + HistoryItem *item = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); HistoryMedia *media = item ? item->getMedia(true) : 0; if (media) { bool out = item->out(), fromChannel = item->fromChannel(), outbg = out && !fromChannel; @@ -1245,9 +1330,9 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (i >= selfrom && i <= selto) { sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; } else if (hasSel) { - SelectedItems::const_iterator i = _selected.constFind(item->id); - if (i != selEnd) { - sel = i.value(); + SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); + if (j != selEnd) { + sel = j.value(); } } @@ -1309,7 +1394,9 @@ void OverviewInner::onUpdateSelected() { if (row < 0) row = 0; bool upon = true; - int32 i = row * _photosInRow + inRow - _photosToAdd, count = _history->overview[_type].size(); + History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migratedCount = migratedIndexSkip(); + int32 i = row * _photosInRow + inRow - _photosToAdd, count = migratedCount + overview.size(); if (i < 0) { i = 0; upon = false; @@ -1319,8 +1406,8 @@ void OverviewInner::onUpdateSelected() { upon = false; } if (i >= 0) { - MsgId msgid = _history->overview[_type][i]; - HistoryItem *histItem = App::histItemById(_channel, msgid); + MsgId msgid = (i >= migratedCount) ? overview[i - migratedCount] : (*migratedOverview)[i]; + HistoryItem *histItem = App::histItemById((i >= migratedCount) ? _channel : _migrated->channelId(), msgid); if (histItem) { item = histItem; index = i; @@ -1335,7 +1422,9 @@ void OverviewInner::onUpdateSelected() { } } } else if (_type == OverviewAudioDocuments) { - int32 i = int32((m.y() - _addToY) / _audioHeight), count = _history->overview[_type].size(); + History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migratedCount = migratedIndexSkip(); + int32 i = int32((m.y() - _addToY) / _audioHeight), count = migratedCount + overview.size(); bool upon = true; if (m.y() < _addToY) { @@ -1347,8 +1436,8 @@ void OverviewInner::onUpdateSelected() { upon = false; } if (i >= 0) { - MsgId msgid = _history->overview[_type][i]; - HistoryItem *histItem = App::histItemById(_channel, msgid); + MsgId msgid = (i >= migratedCount) ? overview[i - migratedCount] : (*migratedOverview)[i]; + HistoryItem *histItem = App::histItemById((i >= migratedCount) ? _channel : _migrated->channelId(), msgid); if (histItem) { item = histItem; index = i; @@ -1356,13 +1445,13 @@ void OverviewInner::onUpdateSelected() { HistoryMedia *media = item->getMedia(true); if (media && media->type() == MediaTypeDocument) { lnk = static_cast(media)->linkInPlaylist(); - newsel = item->id; + newsel = (item->history() == _migrated) ? (-item->id) : item->id; } } } } if (newsel != _selectedMsgId) { - if (_selectedMsgId) updateMsg(App::histItemById(_channel, _selectedMsgId)); + if (_selectedMsgId) updateMsg(_selectedMsgId, -1); _selectedMsgId = newsel; updateMsg(item); } @@ -1386,7 +1475,7 @@ void OverviewInner::onUpdateSelected() { } } - HistoryItem *histItem = App::histItemById(_channel, _items[i].msgid); + HistoryItem *histItem = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); if (histItem) { item = histItem; index = i; @@ -1435,7 +1524,7 @@ void OverviewInner::onUpdateSelected() { } } - HistoryItem *histItem = App::histItemById(_channel, _items[i].msgid); + HistoryItem *histItem = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); if (histItem) { item = histItem; index = i; @@ -1461,7 +1550,7 @@ void OverviewInner::onUpdateSelected() { MsgId oldMousedItem = _mousedItem; int32 oldMousedItemIndex = _mousedItemIndex; - _mousedItem = item ? item->id : 0; + _mousedItem = item ? ((item->history() == _migrated) ? -item->id : item->id) : 0; _mousedItemIndex = index; m = mapMouseToItem(m, _mousedItem, _mousedItemIndex); @@ -1479,7 +1568,7 @@ void OverviewInner::onUpdateSelected() { } if (lnkIndex != _lnkOverIndex || _mousedItem != oldMousedItem) { lnkChanged = true; - if (oldMousedItem) updateMsg(App::histItemById(_channel, oldMousedItem)); + if (oldMousedItem) updateMsg(oldMousedItem, oldMousedItemIndex); _lnkOverIndex = lnkIndex; if (item) updateMsg(item); QToolTip::hideText(); @@ -1606,7 +1695,7 @@ void OverviewInner::onUpdateSelected() { bool dragSelecting = false; MsgId dragFirstAffected = dragSelFrom; int32 dragFirstAffectedIndex = dragSelFromIndex; - while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) { + while (dragFirstAffectedIndex >= 0 && itemMsgId(dragFirstAffected) <= 0) { moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos || _type == OverviewAudioDocuments)) || (!selectingDown && (_type != OverviewPhotos && _type != OverviewAudioDocuments))) ? -1 : 1); } if (dragFirstAffectedIndex >= 0) { @@ -1653,7 +1742,7 @@ void OverviewInner::showLinkTip() { QToolTip::showText(_dragPos, url, this, r); } } else if (_cursorState == HistoryInDateCursorState && _dragAction == NoDrag && _mousedItem) { - if (HistoryItem *item = App::histItemById(_channel, _mousedItem)) { + if (HistoryItem *item = App::histItemById(itemChannel(_mousedItem), itemMsgId(_mousedItem))) { QToolTip::showText(_dragPos, item->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)), this, r); } } @@ -1704,8 +1793,8 @@ void OverviewInner::enterEvent(QEvent *e) { } void OverviewInner::leaveEvent(QEvent *e) { - if (_selectedMsgId > 0) { - updateMsg(App::histItemById(_channel, _selectedMsgId)); + if (_selectedMsgId) { + updateMsg(_selectedMsgId, -1); _selectedMsgId = 0; } if (textlnkOver()) { @@ -1738,14 +1827,14 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->deleteLater(); _menu = 0; updateMsg(App::contextItem()); - if (_selectedMsgId > 0) updateMsg(App::histItemById(_channel, _selectedMsgId)); + if (_selectedMsgId) updateMsg(_selectedMsgId, -1); } if (e->reason() == QContextMenuEvent::Mouse) { dragActionUpdate(e->globalPos()); } bool ignoreMousedItem = false; - if (_mousedItem > 0) { + if (itemMsgId(_mousedItem) > 0) { QPoint m = mapMouseToItem(mapFromGlobal(e->globalPos()), _mousedItem, _mousedItemIndex); if (m.y() < 0 || m.y() >= itemHeight(_mousedItem, _mousedItemIndex)) { ignoreMousedItem = true; @@ -1761,7 +1850,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { isUponSelected = -1; if (_selected.cbegin().value() == FullItemSel) { hasSelected = 2; - if (!ignoreMousedItem && App::mousedItem() && _selected.constFind(App::mousedItem()->id) != _selected.cend()) { + if (!ignoreMousedItem && App::mousedItem() && _selected.constFind(App::mousedItem()->history() == _migrated ? -App::mousedItem()->id : App::mousedItem()->id) != _selected.cend()) { isUponSelected = 2; } else { isUponSelected = -2; @@ -1816,8 +1905,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } App::contextItem(App::hoveredLinkItem()); updateMsg(App::contextItem()); - if (_selectedMsgId > 0) updateMsg(App::histItemById(_channel, _selectedMsgId)); - } else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->id == _mousedItem) { + if (_selectedMsgId) updateMsg(_selectedMsgId, -1); + } else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->channelId() == itemChannel(_mousedItem) && App::mousedItem()->id == itemMsgId(_mousedItem)) { _contextMenuUrl = _lnkOverIndex ? urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex) : QString(); _menu = new PopupMenu(); if ((_contextMenuLnk && dynamic_cast(_contextMenuLnk.data())) || (!_contextMenuUrl.isEmpty() && !urlIsEmail(_contextMenuUrl))) { @@ -1856,7 +1945,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } App::contextItem(App::mousedItem()); updateMsg(App::contextItem()); - if (_selectedMsgId > 0) updateMsg(App::histItemById(_channel, _selectedMsgId)); + if (_selectedMsgId) updateMsg(_selectedMsgId, -1); } if (_menu) { connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*))); @@ -1896,6 +1985,10 @@ PeerData *OverviewInner::peer() const { return _peer; } +PeerData *OverviewInner::migratePeer() const { + return _migrated ? _migrated->peer : 0; +} + MediaOverviewType OverviewInner::type() const { return _type; } @@ -1970,12 +2063,13 @@ void OverviewInner::selectMessage() { HistoryItem *item = App::contextItem(); if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return; + MsgId msgid = item->history() == _migrated ? -item->id : item->id; if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { _selected.clear(); - } else if (_selected.size() == MaxSelectedItems && _selected.constFind(item->id) == _selected.cend()) { + } else if (_selected.size() == MaxSelectedItems && _selected.constFind(msgid) == _selected.cend()) { return; } - _selected.insert(item->id, FullItemSel); + _selected.insert(msgid, FullItemSel); _overview->updateTopBarSelection(); _overview->update(); } @@ -2015,6 +2109,7 @@ void OverviewInner::openContextFile() { } bool OverviewInner::onSearchMessages(bool searchCache) { + _searchTimer.stop(); QString q = _search.text().trimmed(); if (q.isEmpty()) { if (_searchRequest) { @@ -2026,16 +2121,16 @@ bool OverviewInner::onSearchMessages(bool searchCache) { SearchCache::const_iterator i = _searchCache.constFind(q); if (i != _searchCache.cend()) { _searchQuery = q; - _searchFull = false; + _searchFull = _searchFullMigrated = false; _searchRequest = 0; - searchReceived(true, i.value(), 0); + searchReceived(SearchFromStart, i.value(), 0); return true; } } else if (_searchQuery != q) { _searchQuery = q; - _searchFull = false; + _searchFull = _searchFullMigrated = false; int32 flags = (_history->peer->isChannel() && !_history->peer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0; - _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _history->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, true), rpcFail(&OverviewInner::searchFailed)); + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _history->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, SearchFromStart), rpcFail(&OverviewInner::searchFailed, SearchFromStart)); _searchQueries.insert(_searchRequest, _searchQuery); } return false; @@ -2044,7 +2139,7 @@ bool OverviewInner::onSearchMessages(bool searchCache) { void OverviewInner::onNeedSearchMessages() { if (!onSearchMessages(true)) { _searchTimer.start(AutoSearchTimeout); - if (_inSearch && _searchFull && _searchResults.isEmpty()) { + if (_inSearch && _searchFull && (!_migrated || _searchFullMigrated) && _searchResults.isEmpty()) { update(); } } @@ -2098,7 +2193,7 @@ void OverviewInner::onMenuDestroy(QObject *obj) { _menu = 0; dragActionUpdate(QCursor::pos()); updateMsg(App::contextItem()); - if (_selectedMsgId > 0) updateMsg(App::histItemById(_channel, _selectedMsgId)); + if (_selectedMsgId) updateMsg(_selectedMsgId, -1); } } @@ -2106,7 +2201,7 @@ void OverviewInner::getSelectionState(int32 &selectedForForward, int32 &selected selectedForForward = selectedForDelete = 0; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { if (i.value() == FullItemSel) { - if (HistoryItem *item = App::histItemById(_channel, i.key())) { + if (HistoryItem *item = App::histItemById(itemChannel(i.key()), itemMsgId(i.key()))) { if (item->canDelete()) { ++selectedForDelete; } @@ -2131,7 +2226,7 @@ void OverviewInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { if (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel) return; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { - HistoryItem *item = App::histItemById(_channel, i.key()); + HistoryItem *item = App::histItemById(itemChannel(i.key()), itemMsgId(i.key())); if (item && item->toHistoryMessage() && item->id > 0) { if (item->history() == _migrated) { sel.insert(item->id - ServerMaxMsgId, item); @@ -2171,15 +2266,16 @@ void OverviewInner::onTouchScrollTimer() { void OverviewInner::mediaOverviewUpdated(bool fromResize) { int32 oldHeight = _height; if (_type == OverviewLinks) { - History::MediaOverview &o(_inSearch ? _searchResults : _history->overview[_type]); - int32 l = o.size(), tocheck = qMin(l, _itemsToBeLoaded); + History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migrateCount = migratedIndexSkip(); + int32 l = _inSearch ? _searchResults.size() : (migrateCount + o.size()), tocheck = qMin(l, _itemsToBeLoaded); _items.reserve(2 * l); // day items int32 y = 0, in = 0; bool allGood = true; QDate prevDate; for (int32 i = 0; i < tocheck; ++i) { - MsgId msgid = o.at(l - i - 1); + MsgId msgid = _inSearch ? _searchResults.at(l - i - 1) : ((l - i - 1 < migrateCount) ? -(*migratedOverview)[l - i - 1] : o.at(l - i - 1 - migrateCount)); if (allGood) { if (_items.size() > in && _items.at(in).msgid == msgid) { prevDate = _items.at(in).date; @@ -2210,7 +2306,8 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } allGood = false; } - HistoryItem *item = App::histItemById(_channel, msgid); + HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid)); + if (!item) continue; QDate date = item->date.date(); if (!in || (in > 0 && date != prevDate)) { @@ -2227,11 +2324,11 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } if (_items.size() > in) { - _items[in] = CachedItem(item->id, item->date.date(), y); + _items[in] = CachedItem(msgid, item->date.date(), y); _items[in].link = cachedLink(item); y += _items[in].link->countHeight(_linksWidth); } else { - _items.push_back(CachedItem(item->id, item->date.date(), y)); + _items.push_back(CachedItem(msgid, item->date.date(), y)); _items.back().link = cachedLink(item); y += _items.back().link->countHeight(_linksWidth); } @@ -2249,8 +2346,9 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { dragActionUpdate(QCursor::pos()); update(); } else if (_type != OverviewPhotos && _type != OverviewAudioDocuments) { - History::MediaOverview &o(_history->overview[_type]); - int32 l = o.size(); + History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migrateCount = migratedIndexSkip(); + int32 l = migrateCount + o.size(); _items.reserve(2 * l); // day items int32 y = 0, in = 0; @@ -2258,7 +2356,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { bool allGood = true; QDate prevDate; for (int32 i = 0; i < l; ++i) { - MsgId msgid = o.at(l - i - 1); + MsgId msgid = (l - i - 1 < migrateCount) ? -(*migratedOverview)[l - i - 1] : o.at(l - i - 1 - migrateCount); if (allGood) { if (_items.size() > in && _items.at(in).msgid == msgid) { prevDate = _items.at(in).date; @@ -2297,7 +2395,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } allGood = false; } - HistoryItem *item = App::histItemById(_channel, msgid); + HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid)); HistoryMedia *media = item ? item->getMedia(true) : 0; if (!media) continue; @@ -2363,33 +2461,36 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { - if (_dragSelFrom == row->id) _dragSelFrom = newId; - if (_dragSelTo == row->id) _dragSelTo = newId; - if (_mousedItem == row->id) _mousedItem = newId; - if (_dragItem == row->id) _dragItem = newId; + MsgId oldId = (row->history() == _migrated) ? -row->id : row->id; + if (row->history() == _migrated) newId = -newId; + if (_dragSelFrom == oldId) _dragSelFrom = newId; + if (_dragSelTo == oldId) _dragSelTo = newId; + if (_mousedItem == oldId) _mousedItem = newId; + if (_dragItem == oldId) _dragItem = newId; + if (_selectedMsgId == oldId) _selectedMsgId = newId; for (SelectedItems::iterator i = _selected.begin(), e = _selected.end(); i != e; ++i) { - if (i.key() == row->id) { + if (i.key() == oldId) { uint32 sel = i.value(); _selected.erase(i); _selected.insert(newId, sel); break; } } - if (_links.contains(row->id) && row->id != newId) { + if (_links.contains(oldId) && oldId != newId) { if (_links.contains(newId)) { for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { if (i->msgid == newId && i->link) { - i->link = _links[row->id]; + i->link = _links[oldId]; break; } } } - _links[newId] = _links[row->id]; - delete _links[row->id]; - _links.remove(row->id); + delete _links[newId]; + _links[newId] = _links[oldId]; + _links.remove(oldId); } for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { - if (i->msgid == row->id) { + if (i->msgid == oldId) { i->msgid = newId; break; } @@ -2397,11 +2498,15 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { } void OverviewInner::itemRemoved(HistoryItem *item) { - if (_dragItem == item->id) { + MsgId msgId = (item->history() == _migrated) ? -item->id : item->id; + if (_dragItem == msgId) { dragActionCancel(); } + if (_selectedMsgId == msgId) { + _selectedMsgId = 0; + } - SelectedItems::iterator i = _selected.find(item->id); + SelectedItems::iterator i = _selected.find(msgId); if (i != _selected.cend()) { _selected.erase(i); _overview->updateTopBarSelection(); @@ -2409,11 +2514,11 @@ void OverviewInner::itemRemoved(HistoryItem *item) { onUpdateSelected(); - if (_dragSelFrom == item->id) { + if (_dragSelFrom == msgId) { _dragSelFrom = 0; _dragSelFromIndex = -1; } - if (_dragSelTo == item->id) { + if (_dragSelTo == msgId) { _dragSelTo = 0; _dragSelToIndex = -1; } @@ -2427,8 +2532,9 @@ void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) { HistoryMedia *media = item ? item->getMedia(true) : 0; if (!media) return; + MsgId msgId = (item->history() == _migrated) ? -item->id : item->id; for (int32 i = 0, l = _items.size(); i < l; ++i) { - if (_items[i].msgid == item->id) { + if (_items[i].msgid == msgId) { int32 from = 0; if (i > 0) from = _items[i - 1].y; @@ -2460,23 +2566,30 @@ void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) { } void OverviewInner::msgUpdated(const HistoryItem *msg) { - if (!msg || _history != msg->history()) return; + if (!msg) return; + History *history = (msg->history() == _history) ? _history : (msg->history() == _migrated ? _migrated : 0); + if (!history) return; + + int32 migrateindex = migratedIndexSkip(); MsgId msgid = msg->id; - if (_history->overviewIds[_type].constFind(msgid) != _history->overviewIds[_type].cend()) { + if (history->overviewHasMsgId(_type, msgid) && (history == _history || migrateindex > 0)) { if (_type == OverviewPhotos) { - int32 index = _history->overview[_type].indexOf(msgid); + int32 index = history->overview[_type].indexOf(msgid); if (index >= 0) { + if (history == _history) index += migrateindex; float64 w = (float64(width() - st::overviewPhotoSkip) / _photosInRow); int32 vsize = (_vsize + st::overviewPhotoSkip); int32 row = (_photosToAdd + index) / _photosInRow, col = (_photosToAdd + index) % _photosInRow; update(int32(col * w), _addToY + int32(row * vsize), qCeil(w), vsize); } } else if (_type == OverviewAudioDocuments) { - int32 index = _history->overview[_type].indexOf(msgid); + int32 index = history->overview[_type].indexOf(msgid); if (index >= 0) { + if (history == _history) index += migrateindex; update(_audioLeft, _addToY + int32(index * _audioHeight), _audioWidth, _audioHeight); } } else if (_type == OverviewLinks) { + if (history == _migrated) msgid = -msgid; for (int32 i = 0, l = _items.size(); i != l; ++i) { if (_items[i].msgid == msgid) { update(_linksLeft, _addToY + _items[i].y, _linksWidth, itemHeight(msgid, i)); @@ -2484,6 +2597,7 @@ void OverviewInner::msgUpdated(const HistoryItem *msg) { } } } else { + if (history == _migrated) msgid = -msgid; for (int32 i = 0, l = _items.size(); i != l; ++i) { if (_items[i].msgid == msgid) { update(0, _addToY + _height - _items[i].y, _width, itemHeight(msgid, i)); @@ -2499,8 +2613,10 @@ void OverviewInner::showAll(bool recountHeights) { if (_type == OverviewPhotos) { _photosInRow = int32(width() - st::overviewPhotoSkip) / int32(st::overviewPhotoMinSize + st::overviewPhotoSkip); _vsize = (int32(width() - st::overviewPhotoSkip) / _photosInRow) - st::overviewPhotoSkip; - int32 count = _history->overview[_type].size(), fullCount = _history->overviewCount[_type]; - if (fullCount > 0) { + int32 migratedCount = migratedIndexSkip(), count = migratedCount + _history->overview[_type].size(); + int32 migratedFullCount = _migrated ? _migrated->overviewCount(_type) : 0; + int32 fullCount = migratedFullCount + _history->overviewCount(_type); + if (fullCount > 0 && migratedFullCount >= 0) { int32 cnt = count - (fullCount % _photosInRow); if (cnt < 0) cnt += _photosInRow; _photosToAdd = (_photosInRow - (cnt % _photosInRow)) % _photosInRow; @@ -2511,7 +2627,7 @@ void OverviewInner::showAll(bool recountHeights) { newHeight = _height = (_vsize + st::overviewPhotoSkip) * rows + st::overviewPhotoSkip; _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } else if (_type == OverviewAudioDocuments) { - int32 count = _history->overview[_type].size(), fullCount = _history->overviewCount[_type]; + int32 migratedCount = migratedIndexSkip(), count = migratedCount + _history->overview[_type].size(); newHeight = _height = count * _audioHeight + 2 * st::playlistPadding; _addToY = st::playlistPadding; } else if (_type == OverviewLinks) { @@ -2544,7 +2660,7 @@ OverviewInner::~OverviewInner() { _links.clear(); } -OverviewWidget::OverviewWidget(QWidget *parent, const PeerData *peer, MediaOverviewType type) : TWidget(parent) +OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent) , _scroll(this, st::historyScroll, false) , _inner(this, &_scroll, peer, type) , _noDropResizeIndex(false) @@ -2709,6 +2825,10 @@ PeerData *OverviewWidget::peer() const { return _inner.peer(); } +PeerData *OverviewWidget::migratePeer() const { + return _inner.migratePeer(); +} + MediaOverviewType OverviewWidget::type() const { return _inner.type(); } @@ -2861,7 +2981,7 @@ void OverviewWidget::doneShow() { } void OverviewWidget::mediaOverviewUpdated(PeerData *p, MediaOverviewType t) { - if (peer() == p && t == type()) { + if ((peer() == p || migratePeer() == p) && t == type()) { _inner.mediaOverviewUpdated(); onScroll(); updateTopBarSelection(); @@ -2869,13 +2989,13 @@ void OverviewWidget::mediaOverviewUpdated(PeerData *p, MediaOverviewType t) { } void OverviewWidget::changingMsgId(HistoryItem *row, MsgId newId) { - if (peer() == row->history()->peer) { + if (peer() == row->history()->peer || migratePeer() == row->history()->peer) { _inner.changingMsgId(row, newId); } } void OverviewWidget::msgUpdated(const HistoryItem *msg) { - if (peer() == msg->history()->peer) { + if (peer() == msg->history()->peer || migratePeer() == msg->history()->peer) { _inner.msgUpdated(msg); } } @@ -2885,7 +3005,7 @@ void OverviewWidget::itemRemoved(HistoryItem *row) { } void OverviewWidget::itemResized(HistoryItem *row, bool scrollToIt) { - if (!row || row->history()->peer == peer()) { + if (!row || row->history()->peer == peer() || row->history()->peer == migratePeer()) { _inner.itemResized(row, scrollToIt); } } diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index 4cf48b5f1..ac11901bb 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -26,7 +26,7 @@ class OverviewInner : public QWidget, public RPCSender { public: - OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const PeerData *peer, MediaOverviewType type); + OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerData *peer, MediaOverviewType type); void activate(); @@ -61,6 +61,7 @@ public: void dropResizeIndex(); PeerData *peer() const; + PeerData *migratePeer() const; MediaOverviewType type() const; void switchType(MediaOverviewType type); @@ -110,6 +111,11 @@ public slots: private: + bool itemMigrated(MsgId msgId) const; + ChannelId itemChannel(MsgId msgId) const; + MsgId itemMsgId(MsgId msgId) const; + int32 migratedIndexSkip() const; + void fixItemIndex(int32 ¤t, MsgId msgId) const; bool itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) const; int32 itemHeight(MsgId msgId, int32 index) const; @@ -125,6 +131,7 @@ private: void touchDeaccelerate(int32 elapsed); void applyDragSelection(); + void addSelectionRange(int32 selFrom, int32 selTo, History *history); QPixmap genPix(PhotoData *photo, int32 size); void showAll(bool recountHeights = false); @@ -184,13 +191,19 @@ private: QTimer _searchTimer; QString _searchQuery; - bool _inSearch, _searchFull; + bool _inSearch, _searchFull, _searchFullMigrated; mtpRequestId _searchRequest; History::MediaOverview _searchResults; - MsgId _lastSearchId; + MsgId _lastSearchId, _lastSearchMigratedId; int32 _searchedCount; - void searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req); - bool searchFailed(const RPCError &error, mtpRequestId req); + enum SearchRequestType { + SearchFromStart, + SearchFromOffset, + SearchMigratedFromStart, + SearchMigratedFromOffset + }; + void searchReceived(SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req); + bool searchFailed(SearchRequestType type, const RPCError &error, mtpRequestId req); typedef QMap SearchCache; SearchCache _searchCache; @@ -268,7 +281,7 @@ class OverviewWidget : public TWidget, public RPCSender { public: - OverviewWidget(QWidget *parent, const PeerData *peer, MediaOverviewType type); + OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type); void clear(); @@ -283,6 +296,7 @@ public: void topBarClick(); PeerData *peer() const; + PeerData *migratePeer() const; MediaOverviewType type() const; void switchType(MediaOverviewType type); void updateTopBarSelection(); diff --git a/Telegram/SourceFiles/playerwidget.cpp b/Telegram/SourceFiles/playerwidget.cpp index f61ffa048..e14082c3e 100644 --- a/Telegram/SourceFiles/playerwidget.cpp +++ b/Telegram/SourceFiles/playerwidget.cpp @@ -267,22 +267,24 @@ void PlayerWidget::updateOverRect(OverState state) { void PlayerWidget::updateControls() { _fullAvailable = (_index >= 0); + + History *history = _msgmigrated ? _migrated : _history; _prevAvailable = _fullAvailable && ((_index > 0) || (_index == 0 && _migrated && !_msgmigrated && !_migrated->overview[OverviewAudioDocuments].isEmpty())); - _nextAvailable = _fullAvailable && ((_index < (_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments].size() - 1) || (_msgmigrated && _index == _migrated->overview[OverviewAudioDocuments].size() - 1 && _history->overviewCount[OverviewAudioDocuments] >= 0 && _history->overviewCountValue(OverviewAudioDocuments) <= _history->overview[OverviewAudioDocuments].size())); + _nextAvailable = _fullAvailable && ((_index < history->overview[OverviewAudioDocuments].size() - 1) || (_msgmigrated && _index == _migrated->overview[OverviewAudioDocuments].size() - 1 && _history->overviewLoaded(OverviewAudioDocuments) && _history->overviewCount(OverviewAudioDocuments) > 0)); resizeEvent(0); update(); if (_index >= 0 && _index < MediaOverviewStartPerPage) { - if (_history->overviewCount[OverviewAudioDocuments] != 0 || (_migrated && _migrated->overviewCount[OverviewAudioDocuments] != 0)) { + if (!_history->overviewLoaded(OverviewAudioDocuments) || (_migrated && !_migrated->overviewLoaded(OverviewAudioDocuments))) { if (App::main()) { - if (_msgmigrated || (_migrated && _index == 0 && _history->overviewCount[OverviewAudioDocuments] >= 0 && _history->overviewCountValue(OverviewAudioDocuments) <= _history->overview[OverviewAudioDocuments].size())) { + if (_msgmigrated || (_migrated && _index == 0 && _history->overviewLoaded(OverviewAudioDocuments))) { App::main()->loadMediaBack(_migrated->peer, OverviewAudioDocuments); } else { App::main()->loadMediaBack(_history->peer, OverviewAudioDocuments); - if (_migrated && _index == 0 && _migrated->overviewCount[OverviewAudioDocuments] != 0 && _migrated->overview[OverviewAudioDocuments].isEmpty()) { + if (_migrated && _index == 0 && _migrated->overview[OverviewAudioDocuments].isEmpty() && !_migrated->overviewLoaded(OverviewAudioDocuments)) { App::main()->loadMediaBack(_migrated->peer, OverviewAudioDocuments); } } - if (_msgmigrated && _history->overviewCount[OverviewAudioDocuments] < 0) { + if (_msgmigrated && !_history->overviewCountLoaded(OverviewAudioDocuments)) { App::main()->preloadOverview(_history->peer, OverviewAudioDocuments); } } @@ -305,10 +307,11 @@ void PlayerWidget::findCurrent() { } if (_index < 0) return; + History *history = _msgmigrated ? _migrated : _history; HistoryItem *next = 0; if (_index < o->size() - 1) { - next = App::histItemById((_msgmigrated ? _migrated : _history)->channelId(), o->at(_index + 1)); - } else if (_msgmigrated && _index == o->size() - 1 && _history->overviewCount[OverviewAudioDocuments] >= 0 && _history->overviewCountValue(OverviewAudioDocuments) <= _history->overview[OverviewAudioDocuments].size()) { + next = App::histItemById(history->channelId(), o->at(_index + 1)); + } else if (_msgmigrated && _index == o->size() - 1 && _history->overviewLoaded(OverviewAudioDocuments) && _history->overviewCount(OverviewAudioDocuments) > 0) { next = App::histItemById(_history->channelId(), _history->overview[OverviewAudioDocuments].at(0)); } if (next) { @@ -343,9 +346,10 @@ void PlayerWidget::clearSelection() { void PlayerWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) { if (_history && (_history->peer == peer || (_migrated && _migrated->peer == peer)) && type == OverviewAudioDocuments) { _index = -1; - if ((_msgmigrated ? _migrated : _history)->channelId() == _song.msgId.channel) { - for (int i = 0, l = (_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments].size(); i < l; ++i) { - if ((_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments].at(i) == _song.msgId.msg) { + History *history = _msgmigrated ? _migrated : _history; + if (history->channelId() == _song.msgId.channel) { + for (int i = 0, l = history->overview[OverviewAudioDocuments].size(); i < l; ++i) { + if (history->overview[OverviewAudioDocuments].at(i) == _song.msgId.msg) { _index = i; break; } @@ -505,9 +509,10 @@ void PlayerWidget::playPausePressed() { void PlayerWidget::prevPressed() { if (isHidden()) return; - const History::MediaOverview *o = _history ? &(_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments] : 0; + History *history = _msgmigrated ? _migrated : _history; + const History::MediaOverview *o = history ? &history->overview[OverviewAudioDocuments] : 0; if (audioPlayer() && o && _index > 0 && _index <= o->size() && !o->isEmpty()) { - startPlay(FullMsgId((_msgmigrated ? _migrated : _history)->channelId(), o->at(_index - 1))); + startPlay(FullMsgId(history->channelId(), o->at(_index - 1))); } else if (!_index && _history && _migrated && !_msgmigrated) { o = &_migrated->overview[OverviewAudioDocuments]; if (!o->isEmpty()) { @@ -519,12 +524,15 @@ void PlayerWidget::prevPressed() { void PlayerWidget::nextPressed() { if (isHidden()) return; - const History::MediaOverview *o = _history ? &(_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments] : 0; + History *history = _msgmigrated ? _migrated : _history; + const History::MediaOverview *o = history ? &history->overview[OverviewAudioDocuments] : 0; if (audioPlayer() && o && _index >= 0 && _index < o->size() - 1) { - startPlay(FullMsgId((_msgmigrated ? _migrated : _history)->channelId(), o->at(_index + 1))); - } else if (o && (_index == o->size() - 1) && _msgmigrated && _history->overviewCount[OverviewAudioDocuments] >= 0 && _history->overviewCountValue(OverviewAudioDocuments) <= _history->overview[OverviewAudioDocuments].size()) { + startPlay(FullMsgId(history->channelId(), o->at(_index + 1))); + } else if (o && (_index == o->size() - 1) && _msgmigrated && _history->overviewLoaded(OverviewAudioDocuments)) { o = &_history->overview[OverviewAudioDocuments]; - if (!o->isEmpty()) startPlay(FullMsgId(_history->channelId(), o->at(0))); + if (!o->isEmpty()) { + startPlay(FullMsgId(_history->channelId(), o->at(0))); + } } } diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 677b23b18..fe98a79c5 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -1142,7 +1142,7 @@ bool ProfileInner::updateMediaLinks(int32 *addToScroll) { for (int i = 0; i < OverviewCount; ++i) { int32 addToY = _mediaButtons[i]->height() + st::setLittleSkip; - int32 count = _history->overviewCountValue(i), additional = _migrated ? _migrated->overviewCountValue(i) : 0; + int32 count = _history->overviewCount(i), additional = _migrated ? _migrated->overviewCount(i) : 0; int32 sum = (count > 0 ? count : 0) + (additional > 0 ? additional : 0); if (sum > 0) { _mediaButtons[i]->setText(overviewLinkText(i, sum)); diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 69f838bf2..7eb374098 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -118,6 +118,13 @@ inline int32 idFromMessage(const MTPmessage &msg) { } return 0; } +inline int32 dateFromMessage(const MTPmessage &msg) { + switch (msg.type()) { + case mtpc_message: return msg.c_message().vdate.v; + case mtpc_messageService: return msg.c_messageService().vdate.v; + } + return 0; +} typedef uint64 PhotoId; typedef uint64 VideoId; @@ -670,7 +677,7 @@ inline ChannelData *PeerData::migrateTo() const { return (isChat() && asChat()->migrateToPtr && asChat()->migrateToPtr->amIn()) ? asChat()->migrateToPtr : 0; } inline const Text &PeerData::dialogName() const { - return (isUser() && !asUser()->phoneText.isEmpty()) ? asUser()->phoneText : nameText; + return migrateTo() ? migrateTo()->dialogName() : ((isUser() && !asUser()->phoneText.isEmpty()) ? asUser()->phoneText : nameText); } inline const QString &PeerData::shortName() const { return isUser() ? asUser()->firstName : name;