diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index f66dbaf2b..7109922c6 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -441,7 +441,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt h->clear(true); } if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) { - App::removeDialog(h); + App::main()->removeDialog(h); } } } diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 9edad4f99..7fca36d1b 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -482,7 +482,7 @@ namespace { h->clear(true); } if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) { - App::removeDialog(h); + App::main()->removeDialog(h); } } } @@ -1047,7 +1047,9 @@ namespace { if (auto history = App::historyLoaded(peer)) { history->outboxRead(upTo); if (history->lastMsg && history->lastMsg->out() && history->lastMsg->id <= upTo) { - if (App::main()) App::main()->dlgUpdated(history->peer, history->lastMsg->id); + if (App::main()) { + App::main()->dlgUpdated(history, history->lastMsg->id); + } } history->updateChatListEntry(); @@ -1801,7 +1803,7 @@ namespace { return ::histories.findOrInsert(peer); } - History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead) { + not_null historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead) { return ::histories.findOrInsert(peer, unreadCnt, maxInboxRead, maxOutboxRead); } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 7954e3f95..16fb2a46d 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -173,7 +173,7 @@ namespace App { Histories &histories(); not_null history(const PeerId &peer); - History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead); + not_null historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead); History *historyLoaded(const PeerId &peer); HistoryItem *histItemById(ChannelId channelId, MsgId itemId); inline not_null history(const PeerData *peer) { diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index a4ebe107f..4bad86635 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -238,6 +238,7 @@ void ChatsListBoxController::rebuildRows() { auto appendList = [this](auto chats) { auto count = 0; for_const (auto row, chats->all()) { + // #TODO feeds list if (appendRow(row->history())) { ++count; } @@ -322,6 +323,7 @@ void ContactsBoxController::rebuildRows() { auto appendList = [this](auto chats) { auto count = 0; for_const (auto row, chats->all()) { + // #TODO feeds list auto history = row->history(); if (auto user = history->peer->asUser()) { if (appendRow(user)) { diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 75065716e..9550204f4 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -280,7 +280,7 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac } } for (const auto row : dialogs->all()) { - // #TODO dialogs + // #TODO feeds list if (const auto history = row->history()) { if (!history->peer->isSelf() && _filterCallback(history->peer)) { _chatsIndexed->addToEnd(history); @@ -349,7 +349,9 @@ void ShareBox::Inner::activateSkipPage(int pageHeight, int direction) { void ShareBox::Inner::notifyPeerUpdated(const Notify::PeerUpdate &update) { if (update.flags & Notify::PeerUpdate::Flag::NameChanged) { - _chatsIndexed->peerNameChanged(update.peer, update.oldNameFirstChars); + _chatsIndexed->peerNameChanged( + update.peer, + update.oldNameFirstChars); } updateChat(update.peer); @@ -405,6 +407,7 @@ int ShareBox::Inner::chatIndex(not_null peer) const { int index = 0; if (_filter.isEmpty()) { for_const (auto row, _chatsIndexed->all()) { + // #TODO feeds list if (row->history()->peer == peer) { return index; } @@ -412,6 +415,7 @@ int ShareBox::Inner::chatIndex(not_null peer) const { } } else { for_const (auto row, _filtered) { + // #TODO feeds list if (row->history()->peer == peer) { return index; } @@ -450,6 +454,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) { if (((*i)->pos() * _rowHeight) >= yTo) { break; } + // #TODO feeds list (*i)->history()->peer->loadUserpic(); } } @@ -461,6 +466,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) { if (to > _filtered.size()) to = _filtered.size(); for (; from < to; ++from) { + // #TODO feeds list _filtered[from]->history()->peer->loadUserpic(); } } @@ -470,6 +476,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) { ShareBox::Inner::Chat *ShareBox::Inner::getChat(Dialogs::Row *row) { auto data = static_cast(row->attached); if (!data) { + // #TODO feeds list auto peer = row->history()->peer; auto i = _dataMap.constFind(peer); if (i == _dataMap.cend()) { @@ -640,17 +647,17 @@ void ShareBox::Inner::changeCheckState(Chat *chat) { if (!chat) return; if (!_filter.isEmpty()) { - auto row = _chatsIndexed->getRow(chat->peer->id); + const auto history = App::history(chat->peer); + auto row = _chatsIndexed->getRow(history); if (!row) { - const auto rowsByLetter = _chatsIndexed->addToEnd( - App::history(chat->peer)); + const auto rowsByLetter = _chatsIndexed->addToEnd(history); const auto it = rowsByLetter.find(0); Assert(it != rowsByLetter.cend()); row = it->second; } chat = getChat(row); if (!chat->checkbox.checked()) { - _chatsIndexed->moveToTop(chat->peer); + _chatsIndexed->moveToTop(history); } } @@ -725,6 +732,7 @@ void ShareBox::Inner::updateFilter(QString filter) { if (toFilter) { _filtered.reserve(toFilter->size()); for_const (auto row, *toFilter) { + // #TODO feeds list auto &nameWords = row->history()->peer->nameWords(); auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb; for (fi = fb; fi != fe; ++fi) { @@ -768,15 +776,16 @@ void ShareBox::Inner::peopleReceived(const QString &query, const QVectorid == peerId) break; } if (j == already) { - auto *peer = App::peer(peerId); - if (!peer || !_filterCallback(peer)) continue; - - auto chat = new Chat(peer, [this, peer] { repaintChat(peer); }); - updateChatName(chat, peer); - if (auto row = _chatsIndexed->getRow(peer->id)) { + const auto peer = App::peer(peerId); + const auto history = App::historyLoaded(peer); + if (!peer || !_filterCallback(peer)) { + continue; + } else if (history && _chatsIndexed->getRow(history)) { continue; } + auto chat = new Chat(peer, [this, peer] { repaintChat(peer); }); + updateChatName(chat, peer); _byUsernameFiltered.push_back(peer); d_byUsernameFiltered.push_back(chat); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp index a82f2abb8..7fef3c0eb 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp @@ -15,37 +15,37 @@ IndexedList::IndexedList(SortMode sortMode) , _empty(sortMode) { } -RowsByLetter IndexedList::addToEnd(not_null history) { +RowsByLetter IndexedList::addToEnd(Key key) { RowsByLetter result; - if (!_list.contains(history->peer->id)) { - result.emplace(0, _list.addToEnd(history)); - for (auto ch : history->peer->nameFirstChars()) { + if (!_list.contains(key)) { + result.emplace(0, _list.addToEnd(key)); + for (auto ch : key.nameFirstChars()) { auto j = _index.find(ch); if (j == _index.cend()) { j = _index.emplace( ch, std::make_unique(_sortMode)).first; } - result.emplace(ch, j->second->addToEnd(history)); + result.emplace(ch, j->second->addToEnd(key)); } } return result; } -Row *IndexedList::addByName(not_null history) { - if (const auto row = _list.getRow(history->peer->id)) { +Row *IndexedList::addByName(Key key) { + if (const auto row = _list.getRow(key)) { return row; } - Row *result = _list.addByName(history); - for (auto ch : history->peer->nameFirstChars()) { + Row *result = _list.addByName(key); + for (auto ch : key.nameFirstChars()) { auto j = _index.find(ch); if (j == _index.cend()) { j = _index.emplace( ch, std::make_unique(_sortMode)).first; } - j->second->addByName(history); + j->second->addByName(key); } return result; } @@ -62,11 +62,11 @@ void IndexedList::adjustByPos(const RowsByLetter &links) { } } -void IndexedList::moveToTop(not_null peer) { - if (_list.moveToTop(peer->id)) { - for (auto ch : peer->nameFirstChars()) { +void IndexedList::moveToTop(Key key) { + if (_list.moveToTop(key)) { + for (auto ch : key.nameFirstChars()) { if (auto it = _index.find(ch); it != _index.cend()) { - it->second->moveToTop(peer->id); + it->second->moveToTop(key); } } } @@ -81,6 +81,7 @@ void IndexedList::movePinned(Row *row, int deltaSign) { Assert(swapPinnedIndexWith != cbegin()); --swapPinnedIndexWith; } + // #TODO feeds pinned auto history1 = row->history(); auto history2 = (*swapPinnedIndexWith)->history(); Assert(history1->isPinnedDialog()); @@ -91,44 +92,52 @@ void IndexedList::movePinned(Row *row, int deltaSign) { history2->setPinnedIndex(index1); } -void IndexedList::peerNameChanged(not_null peer, const PeerData::NameFirstChars &oldChars) { - Assert(_sortMode != SortMode::Date); - if (_sortMode == SortMode::Name) { - adjustByName(peer, oldChars); - } else { - adjustNames(Dialogs::Mode::All, peer, oldChars); +void IndexedList::peerNameChanged( + not_null peer, + const PeerData::NameFirstChars &oldChars) { + Expects(_sortMode != SortMode::Date); + + if (const auto history = App::historyLoaded(peer)) { + if (_sortMode == SortMode::Name) { + adjustByName(history, oldChars); + } else { + adjustNames(Dialogs::Mode::All, history, oldChars); + } } } -void IndexedList::peerNameChanged(Mode list, not_null peer, const PeerData::NameFirstChars &oldChars) { - Assert(_sortMode == SortMode::Date); - adjustNames(list, peer, oldChars); +void IndexedList::peerNameChanged( + Mode list, + not_null peer, + const PeerData::NameFirstChars &oldChars) { + Expects(_sortMode == SortMode::Date); + + if (const auto history = App::historyLoaded(peer)) { + adjustNames(list, history, oldChars); + } } void IndexedList::adjustByName( - not_null peer, + Key key, const PeerData::NameFirstChars &oldChars) { - const auto mainRow = _list.adjustByName(peer); + const auto mainRow = _list.adjustByName(key); if (!mainRow) return; - // #TODO dialogs - const auto history = mainRow->history(); - PeerData::NameFirstChars toRemove = oldChars, toAdd; - for (auto ch : peer->nameFirstChars()) { + for (auto ch : key.nameFirstChars()) { auto j = toRemove.find(ch); if (j == toRemove.cend()) { toAdd.insert(ch); } else { toRemove.erase(j); if (auto it = _index.find(ch); it != _index.cend()) { - it->second->adjustByName(peer); + it->second->adjustByName(key); } } } for (auto ch : toRemove) { if (auto it = _index.find(ch); it != _index.cend()) { - it->second->del(peer->id, mainRow); + it->second->del(key, mainRow); } } if (!toAdd.empty()) { @@ -139,20 +148,23 @@ void IndexedList::adjustByName( ch, std::make_unique(_sortMode)).first; } - j->second->addByName(history); + j->second->addByName(key); } } } -void IndexedList::adjustNames(Mode list, not_null peer, const PeerData::NameFirstChars &oldChars) { - auto mainRow = _list.getRow(peer->id); +void IndexedList::adjustNames( + Mode list, + Key key, + const PeerData::NameFirstChars &oldChars) { + auto mainRow = _list.getRow(key); if (!mainRow) return; - // #TODO dialogs + // #TODO feeds dialogs auto history = mainRow->history(); PeerData::NameFirstChars toRemove = oldChars, toAdd; - for (auto ch : peer->nameFirstChars()) { + for (auto ch : key.nameFirstChars()) { auto j = toRemove.find(ch); if (j == toRemove.cend()) { toAdd.insert(ch); @@ -165,7 +177,7 @@ void IndexedList::adjustNames(Mode list, not_null peer, const PeerDat history->removeChatListEntryByLetter(list, ch); } if (auto it = _index.find(ch); it != _index.cend()) { - it->second->del(peer->id, mainRow); + it->second->del(key, mainRow); } } for (auto ch : toAdd) { @@ -175,18 +187,18 @@ void IndexedList::adjustNames(Mode list, not_null peer, const PeerDat ch, std::make_unique(_sortMode)).first; } - auto row = j->second->addToEnd(history); + auto row = j->second->addToEnd(key); if (_sortMode == SortMode::Date) { history->addChatListEntryByLetter(list, ch, row); } } } -void IndexedList::del(not_null peer, Row *replacedBy) { - if (_list.del(peer->id, replacedBy)) { - for (auto ch : peer->nameFirstChars()) { +void IndexedList::del(Key key, Row *replacedBy) { + if (_list.del(key, replacedBy)) { + for (auto ch : key.nameFirstChars()) { if (auto it = _index.find(ch); it != _index.cend()) { - it->second->del(peer->id, replacedBy); + it->second->del(key, replacedBy); } } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h index 3b3d344df..0022e74dc 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h @@ -18,21 +18,26 @@ class IndexedList { public: IndexedList(SortMode sortMode); - RowsByLetter addToEnd(not_null history); - Row *addByName(not_null history); + RowsByLetter addToEnd(Key key); + Row *addByName(Key key); void adjustByPos(const RowsByLetter &links); - void moveToTop(not_null peer); + void moveToTop(Key key); // row must belong to this indexed list all(). void movePinned(Row *row, int deltaSign); // For sortMode != SortMode::Date - void peerNameChanged(not_null peer, const PeerData::NameFirstChars &oldChars); + void peerNameChanged( + not_null peer, + const PeerData::NameFirstChars &oldChars); //For sortMode == SortMode::Date - void peerNameChanged(Mode list, not_null peer, const PeerData::NameFirstChars &oldChars); + void peerNameChanged( + Mode list, + not_null peer, + const PeerData::NameFirstChars &oldChars); - void del(not_null peer, Row *replacedBy = nullptr); + void del(Key key, Row *replacedBy = nullptr); void clear(); const List &all() const { @@ -50,8 +55,8 @@ public: // Part of List interface is duplicated here for all() list. int size() const { return all().size(); } bool isEmpty() const { return all().isEmpty(); } - bool contains(PeerId peerId) const { return all().contains(peerId); } - Row *getRow(PeerId peerId) const { return all().getRow(peerId); } + bool contains(Key key) const { return all().contains(key); } + Row *getRow(Key key) const { return all().getRow(key); } Row *rowAtY(int32 y, int32 h) const { return all().rowAtY(y, h); } using iterator = List::iterator; @@ -70,8 +75,13 @@ public: iterator find(int y, int h) { return all().find(y, h); } private: - void adjustByName(not_null peer, const PeerData::NameFirstChars &oldChars); - void adjustNames(Mode list, not_null peer, const PeerData::NameFirstChars &oldChars); + void adjustByName( + Key key, + const PeerData::NameFirstChars &oldChars); + void adjustNames( + Mode list, + Key key, + const PeerData::NameFirstChars &oldChars); SortMode _sortMode; List _list, _empty; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 73efdbf0f..aca7c2928 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -53,9 +53,9 @@ struct DialogsInner::HashtagResult { }; struct DialogsInner::PeerSearchResult { - PeerSearchResult(PeerData *peer) : peer(peer) { + PeerSearchResult(not_null peer) : peer(peer) { } - PeerData *peer; + not_null peer; Dialogs::RippleRow row; }; @@ -99,7 +99,7 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro }, lifetime()); subscribe(App::histories().sendActionAnimationUpdated(), [this](const Histories::SendActionAnimationUpdate &update) { auto updateRect = Dialogs::Layout::RowPainter::sendActionAnimationRect(update.width, update.height, getFullWidth(), update.textUpdated); - updateDialogRow(update.history->peer, MsgId(0), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered); + updateDialogRow(update.history, MsgId(0), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered); }); subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { @@ -187,7 +187,16 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } auto otherStart = rows->size() * st::dialogsRowHeight; auto active = App::main()->activePeer(); - auto selected = _menuPeer ? _menuPeer : (isPressed() ? (_pressed ? _pressed->history()->peer : nullptr) : (_selected ? _selected->history()->peer : nullptr)); + // #TODO feeds dialogs + auto selected = _menuPeer + ? _menuPeer + : (isPressed() + ? (_pressed + ? _pressed->history()->peer + : nullptr) + : (_selected + ? _selected->history()->peer + : nullptr)); if (otherStart) { auto reorderingPinned = (_aboveIndex >= 0 && !_pinnedRows.empty()); auto &list = rows->all(); @@ -297,8 +306,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO auto activeMsgId = App::main()->activeMsgId(); for (; from < to; ++from) { auto row = _filterResults[from]; + // #TODO feeds dialogs auto peer = row->history()->peer; - auto active = ((peer == activePeer) || (peer->migrateTo() && peer->migrateTo() == activePeer)) && !activeMsgId; + auto active = !activeMsgId && ((peer == activePeer) + || (peer->migrateTo() + && peer->migrateTo() == activePeer)); auto selected = _menuPeer ? (peer == _menuPeer) : (from == (isPressed() ? _filteredPressed : _filteredSelected)); Dialogs::Layout::RowPainter::paint(p, _filterResults[from], fullWidth, active, selected, paintingOther, ms); p.translate(0, st::dialogsRowHeight); @@ -378,20 +390,44 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } } -void DialogsInner::paintDialog(Painter &p, Dialogs::Row *row, int fullWidth, PeerData *active, PeerData *selected, bool onlyBackground, TimeMs ms) { +void DialogsInner::paintDialog( + Painter &p, + not_null row, + int fullWidth, + PeerData *active, + PeerData *selected, + bool onlyBackground, + TimeMs ms) { auto pos = row->pos(); auto xadd = 0, yadd = 0; if (pos < _pinnedRows.size()) { yadd = qRound(_pinnedRows[pos].yadd.current()); } if (xadd || yadd) p.translate(xadd, yadd); - auto isActive = (row->history()->peer == active) || (row->history()->peer->migrateTo() && row->history()->peer->migrateTo() == active); + // #TODO feeds dialogs + auto isActive = (row->history()->peer == active) + || (row->history()->peer->migrateTo() + && row->history()->peer->migrateTo() == active); auto isSelected = (row->history()->peer == selected); - Dialogs::Layout::RowPainter::paint(p, row, fullWidth, isActive, isSelected, onlyBackground, ms); + Dialogs::Layout::RowPainter::paint( + p, + row, + fullWidth, + isActive, + isSelected, + onlyBackground, + ms); if (xadd || yadd) p.translate(-xadd, -yadd); } -void DialogsInner::paintPeerSearchResult(Painter &p, const PeerSearchResult *result, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) const { +void DialogsInner::paintPeerSearchResult( + Painter &p, + not_null result, + int fullWidth, + bool active, + bool selected, + bool onlyBackground, + TimeMs ms) const { QRect fullRect(0, 0, fullWidth, st::dialogsRowHeight); p.fillRect(fullRect, active ? st::dialogsBgActive : (selected ? st::dialogsBgOver : st::dialogsBg)); if (!active) { @@ -443,7 +479,11 @@ void DialogsInner::paintPeerSearchResult(Painter &p, const PeerSearchResult *res peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } -void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackground, TimeMs ms) const { +void DialogsInner::paintSearchInPeer( + Painter &p, + int fullWidth, + bool onlyBackground, + TimeMs ms) const { auto height = searchInPeerSkip(); auto top = st::searchedBarHeight; @@ -657,6 +697,7 @@ void DialogsInner::mousePressEvent(QMouseEvent *e) { auto row = _pressed; row->addRipple(e->pos() - QPoint(0, dialogsOffset() + _pressed->pos() * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [this, row] { if (!_a_pinnedShifting.animating()) { + // #TODO feeds dialogs row->history()->updateChatListEntry(); } }); @@ -667,20 +708,19 @@ void DialogsInner::mousePressEvent(QMouseEvent *e) { update(0, index * st::mentionHeight, getFullWidth(), st::mentionHeight); }); } else if (_filteredPressed >= 0 && _filteredPressed < _filterResults.size()) { - auto row = _filterResults[_filteredPressed]; - row->addRipple(e->pos() - QPoint(0, filteredOffset() + _filteredPressed * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [row] { - if (auto main = App::main()) { - main->dlgUpdated(row->history()->peer, 0); - } - }); + const auto row = _filterResults[_filteredPressed]; + const auto list = Global::DialogsMode(); + row->addRipple( + e->pos() - QPoint(0, filteredOffset() + _filteredPressed * st::dialogsRowHeight), + QSize(getFullWidth(), st::dialogsRowHeight), + [=] { dlgUpdated(list, row); }); } else if (_peerSearchPressed >= 0 && _peerSearchPressed < _peerSearchResults.size()) { auto &result = _peerSearchResults[_peerSearchPressed]; auto row = &result->row; - row->addRipple(e->pos() - QPoint(0, peerSearchOffset() + _peerSearchPressed * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [peer = result->peer] { - if (auto main = App::main()) { - main->dlgUpdated(peer, 0); - } - }); + row->addRipple( + e->pos() - QPoint(0, peerSearchOffset() + _peerSearchPressed * st::dialogsRowHeight), + QSize(getFullWidth(), st::dialogsRowHeight), + [this, peer = result->peer] { updateSearchResult(peer); }); } else if (_searchedPressed >= 0 && _searchedPressed < _searchResults.size()) { auto &row = _searchResults[_searchedPressed]; row->addRipple(e->pos() - QPoint(0, searchedOffset() + _searchedPressed * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [this, index = _searchedPressed] { @@ -708,6 +748,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { int DialogsInner::shownPinnedCount() const { auto result = 0; for_const (auto row, *shownDialogs()) { + // #TODO feeds pinned if (!row->history()->isPinnedDialog()) { break; } @@ -717,6 +758,7 @@ int DialogsInner::shownPinnedCount() const { } int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { + // #TODO feeds pinned if (!ofRow || !ofRow->history()->isPinnedDialog()) { return -1; } @@ -1032,7 +1074,7 @@ void DialogsInner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRo } } -void DialogsInner::createDialog(History *history) { +void DialogsInner::createDialog(not_null history) { if (history->peer->loadedStatus != PeerData::LoadedStatus::FullLoaded) { LOG(("API Error: DialogsInner::createDialog() called for a non loaded peer!")); return; @@ -1041,7 +1083,7 @@ void DialogsInner::createDialog(History *history) { bool creating = !history->inChatList(Dialogs::Mode::All); if (creating) { auto mainRow = history->addToChatList(Dialogs::Mode::All, _dialogs.get()); - _contactsNoDialogs->del(history->peer, mainRow); + _contactsNoDialogs->del(history, mainRow); } if (_dialogsImportant && !history->inChatList(Dialogs::Mode::Important) && !history->mute()) { if (Global::DialogsMode() == Dialogs::Mode::Important) { @@ -1079,9 +1121,8 @@ void DialogsInner::createDialog(History *history) { } } -void DialogsInner::removeDialog(History *history) { - if (!history) return; - +void DialogsInner::removeDialog(not_null history) { + // #TODO feeds dialogs if (history->peer == _menuPeer && _menu) { InvokeQueued(this, [this] { _menu = nullptr; }); } @@ -1096,8 +1137,8 @@ void DialogsInner::removeDialog(History *history) { history->removeFromChatList(Dialogs::Mode::Important, _dialogsImportant.get()); } Auth().notifications().clearFromHistory(history); - if (_contacts->contains(history->peer->id)) { - if (!_contactsNoDialogs->contains(history->peer->id)) { + if (_contacts->contains(history)) { + if (!_contactsNoDialogs->contains(history)) { _contactsNoDialogs->addByName(history); } } @@ -1109,7 +1150,9 @@ void DialogsInner::removeDialog(History *history) { refresh(); } -void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) { +void DialogsInner::dlgUpdated( + Dialogs::Mode list, + not_null row) { if (_state == DefaultState) { if (Global::DialogsMode() == list) { auto position = row->pos(); @@ -1121,9 +1164,13 @@ void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) { } } else if (_state == FilteredState || _state == SearchedState) { if (list == Dialogs::Mode::All) { - for (int32 i = 0, l = _filterResults.size(); i < l; ++i) { - if (_filterResults.at(i)->history() == row->history()) { - update(0, filteredOffset() + i * st::dialogsRowHeight, getFullWidth(), st::dialogsRowHeight); + for (auto i = 0, l = _filterResults.size(); i != l; ++i) { + if (_filterResults[i]->key() == row->key()) { + update( + 0, + filteredOffset() + i * st::dialogsRowHeight, + getFullWidth(), + st::dialogsRowHeight); break; } } @@ -1131,17 +1178,39 @@ void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) { } } -void DialogsInner::dlgUpdated(PeerData *peer, MsgId msgId) { - updateDialogRow(peer, msgId, QRect(0, 0, getFullWidth(), st::dialogsRowHeight)); +void DialogsInner::dlgUpdated(not_null history, MsgId msgId) { + updateDialogRow( + history, + msgId, + QRect(0, 0, getFullWidth(), st::dialogsRowHeight)); } -void DialogsInner::updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect, UpdateRowSections sections) { +void DialogsInner::updateSearchResult(not_null peer) { + if (_state == FilteredState || _state == SearchedState) { + if (!_peerSearchResults.empty()) { + auto index = 0, add = peerSearchOffset(); + for_const (auto &result, _peerSearchResults) { + if (result->peer == peer) { + rtlupdate(0, add + index * st::dialogsRowHeight, getFullWidth(), st::dialogsRowHeight); + break; + } + ++index; + } + } + } +} + +void DialogsInner::updateDialogRow( + not_null history, + MsgId msgId, + QRect updateRect, + UpdateRowSections sections) { auto updateRow = [this, updateRect](int rowTop) { rtlupdate(updateRect.x(), rowTop + updateRect.y(), updateRect.width(), updateRect.height()); }; if (_state == DefaultState) { if (sections & UpdateRowSection::Default) { - if (auto row = shownDialogs()->getRow(peer->id)) { + if (const auto row = shownDialogs()->getRow(history)) { auto position = row->pos(); auto top = dialogsOffset(); if (position >= 0 && position < _pinnedRows.size()) { @@ -1154,7 +1223,7 @@ void DialogsInner::updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect if ((sections & UpdateRowSection::Filtered) && !_filterResults.isEmpty()) { auto index = 0, add = filteredOffset(); for_const (auto row, _filterResults) { - if (row->history()->peer == peer) { + if (row->history() == history) { updateRow(add + index * st::dialogsRowHeight); break; } @@ -1164,7 +1233,7 @@ void DialogsInner::updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect if ((sections & UpdateRowSection::PeerSearch) && !_peerSearchResults.empty()) { auto index = 0, add = peerSearchOffset(); for_const (auto &result, _peerSearchResults) { - if (result->peer == peer) { + if (result->peer == history->peer) { updateRow(add + index * st::dialogsRowHeight); break; } @@ -1175,7 +1244,7 @@ void DialogsInner::updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect auto index = 0, add = searchedOffset(); for_const (auto &result, _searchResults) { auto item = result->item(); - if (item->history()->peer == peer && item->id == msgId) { + if (item->history() == history && item->id == msgId) { updateRow(add + index * st::dialogsRowHeight); break; } @@ -1191,6 +1260,7 @@ void DialogsInner::enterEventHook(QEvent *e) { } void DialogsInner::updateSelectedRow(PeerData *peer) { + // #TODO feeds dialogs if (_state == DefaultState) { if (peer) { if (auto h = App::historyLoaded(peer->id)) { @@ -1210,8 +1280,8 @@ void DialogsInner::updateSelectedRow(PeerData *peer) { } } else if (_state == FilteredState || _state == SearchedState) { if (peer) { - for (int32 i = 0, l = _filterResults.size(); i != l; ++i) { - if (_filterResults.at(i)->history()->peer == peer) { + for (auto i = 0, l = _filterResults.size(); i != l; ++i) { + if (_filterResults[i]->history()->peer == peer) { update(0, filteredOffset() + i * st::dialogsRowHeight, getFullWidth(), st::dialogsRowHeight); break; } @@ -1257,6 +1327,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) { updateSelected(); } + // #TODO feeds context menu auto history = [&]() -> History* { if (_state == DefaultState) { if (_selected) { @@ -1362,6 +1433,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { _filterResults.reserve((toFilter ? toFilter->size() : 0) + (toFilterContacts ? toFilterContacts->size() : 0)); if (toFilter) { for_const (auto row, *toFilter) { + // #TODO feeds dialogs const auto &nameWords = row->history()->peer->nameWords(); auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb; for (fi = fb; fi != fe; ++fi) { @@ -1382,6 +1454,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) { } if (toFilterContacts) { for_const (auto row, *toFilterContacts) { + // #TODO feeds dialogs const auto &nameWords = row->history()->peer->nameWords(); auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb; for (fi = fb; fi != fe; ++fi) { @@ -1453,6 +1526,7 @@ void DialogsInner::clearSearchResults(bool clearPeerSearchResults) { } PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) { + // #TODO feeds dialogs _mouseSelection = true; updateSelected(mapFromGlobal(globalPos)); if (_state == DefaultState) { @@ -1549,9 +1623,11 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) { if (!history->isPinnedDialog() && !history->lastMsgDate.isNull()) { addSavedPeersAfter(history->lastMsgDate); } - _contactsNoDialogs->del(peer); + _contactsNoDialogs->del(history); if (peer->migrateFrom()) { - removeDialog(App::historyLoaded(peer->migrateFrom()->id)); + if (const auto historyFrom = App::historyLoaded(peer->migrateFrom())) { + removeDialog(historyFrom); + } } else if (peer->migrateTo() && peer->migrateTo()->amIn()) { removeDialog(history); } @@ -1591,7 +1667,7 @@ void DialogsInner::addSavedPeersAfter(const QDateTime &date) { while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) { const auto history = App::history(saved.last()->id); history->setChatsListDate(saved.lastKey()); - _contactsNoDialogs->del(history->peer); + _contactsNoDialogs->del(history); saved.remove(saved.lastKey(), saved.last()); } } @@ -1674,19 +1750,19 @@ void DialogsInner::userIsContactUpdated(not_null user) { if (user->contactStatus() == UserData::ContactStatus::Contact) { const auto history = App::history(user->id); _contacts->addByName(history); - if (!shownDialogs()->getRow(user->id) - && !_dialogs->contains(user->id)) { + if (!shownDialogs()->getRow(history) + && !_dialogs->contains(history)) { _contactsNoDialogs->addByName(history); } - } else { - if (_selected && _selected->history()->peer == user) { + } else if (const auto history = App::historyLoaded(user)) { + if (_selected && _selected->history() == history) { _selected = nullptr; } - if (_pressed && _pressed->history()->peer == user) { + if (_pressed && _pressed->history() == history) { setPressed(nullptr); } - _contactsNoDialogs->del(user); - _contacts->del(user); + _contactsNoDialogs->del(history); + _contacts->del(history); } refresh(); } @@ -1932,24 +2008,24 @@ void DialogsInner::selectSkip(int32 direction) { update(); } -void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) { +void DialogsInner::scrollToPeer(not_null history, MsgId msgId) { int32 fromY = -1; if (_state == DefaultState) { - if (auto row = shownDialogs()->getRow(peer)) { + if (auto row = shownDialogs()->getRow(history)) { fromY = dialogsOffset() + row->pos() * st::dialogsRowHeight; } } 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) { + if (_searchResults[i]->item()->history() == history && _searchResults[i]->item()->id == msgId) { fromY = searchedOffset() + i * st::dialogsRowHeight; break; } } } if (fromY < 0) { - for (int32 i = 0, c = _filterResults.size(); i < c; ++i) { - if (_filterResults[i]->history()->peer->id == peer) { + for (auto i = 0, c = _filterResults.size(); i != c; ++i) { + if (_filterResults[i]->history() == history) { fromY = filteredOffset() + (i * st::dialogsRowHeight); break; } @@ -2008,6 +2084,7 @@ void DialogsInner::loadPeerPhotos() { if (((*i)->pos() * st::dialogsRowHeight) >= yTo) { break; } + // #TODO feeds dialogs (*i)->history()->peer->loadUserpic(); } yFrom = 0; @@ -2023,6 +2100,7 @@ void DialogsInner::loadPeerPhotos() { if (to > _filterResults.size()) to = _filterResults.size(); for (; from < to; ++from) { + // #TODO feeds dialogs _filterResults[from]->history()->peer->loadUserpic(); } } @@ -2066,6 +2144,7 @@ bool DialogsInner::choosePeer() { _importantSwitchSelected = true; return true; } else if (_selected) { + // #TODO feeds open history = _selected->history(); } } else if (_state == FilteredState || _state == SearchedState) { @@ -2092,6 +2171,7 @@ bool DialogsInner::choosePeer() { } return true; } + // #TODO feeds open if (_filteredSelected >= 0 && _filteredSelected < _filterResults.size()) { history = _filterResults[_filteredSelected]->history(); } else if (_peerSearchSelected >= 0 && _peerSearchSelected < _peerSearchResults.size()) { @@ -2163,141 +2243,154 @@ void DialogsInner::destroyData() { } } -void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { - if (!inPeer) { - outPeer = nullptr; - outMsg = 0; - return; + +Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( + const Dialogs::RowDescriptor &which) const { + if (!which.key.value) { + return Dialogs::RowDescriptor(); } if (_state == DefaultState) { - if (auto row = shownDialogs()->getRow(inPeer->id)) { - auto i = shownDialogs()->cfind(row); + if (const auto row = shownDialogs()->getRow(which.key)) { + const auto i = shownDialogs()->cfind(row); if (i != shownDialogs()->cbegin()) { - outPeer = (*(--i))->history()->peer; - outMsg = ShowAtUnreadMsgId; - return; + return Dialogs::RowDescriptor((*(i - 1))->key(), + ShowAtUnreadMsgId); } } - outPeer = nullptr; - outMsg = 0; - return; - } else if (_state == FilteredState || _state == SearchedState) { - if (inMsg && !_searchResults.empty()) { - for (auto b = _searchResults.cbegin(), i = b + 1, e = _searchResults.cend(); i != e; ++i) { - if ((*i)->item()->history()->peer == inPeer && (*i)->item()->id == inMsg) { - auto j = i - 1; - outPeer = (*j)->item()->history()->peer; - outMsg = (*j)->item()->id; - return; - } - } - if (_searchResults.at(0)->item()->history()->peer == inPeer && _searchResults.at(0)->item()->id == inMsg) { - outMsg = ShowAtUnreadMsgId; - if (_peerSearchResults.empty()) { - if (_filterResults.isEmpty()) { - outPeer = nullptr; - } else { - outPeer = _filterResults.back()->history()->peer; - } - } else { - outPeer = _peerSearchResults.back()->peer; - } - return; - } - } - if (!_peerSearchResults.empty() && _peerSearchResults[0]->peer == inPeer) { - outPeer = _filterResults.isEmpty() ? 0 : _filterResults.back()->history()->peer; - outMsg = ShowAtUnreadMsgId; - return; - } - if (!_peerSearchResults.empty()) { - for (auto b = _peerSearchResults.cbegin(), i = b + 1, e = _peerSearchResults.cend(); i != e; ++i) { - if ((*i)->peer == inPeer) { - outPeer = (*(i - 1))->peer; - outMsg = ShowAtUnreadMsgId; - return; - } - } - } - if (_filterResults.isEmpty() || _filterResults.at(0)->history()->peer == inPeer) { - outPeer = nullptr; - outMsg = 0; - return; - } + return Dialogs::RowDescriptor(); + } - for (auto b = _filterResults.cbegin(), i = b + 1, e = _filterResults.cend(); i != e; ++i) { - if ((*i)->history()->peer == inPeer) { - outPeer = (*(i - 1))->history()->peer; - outMsg = ShowAtUnreadMsgId; - return; + const auto whichHistory = which.key.history(); + const auto whichMsgId = which.msgId; + if (!whichHistory) { + return Dialogs::RowDescriptor(); + } + if (whichMsgId && !_searchResults.empty()) { + for (auto b = _searchResults.cbegin(), i = b + 1, e = _searchResults.cend(); i != e; ++i) { + if ((*i)->item()->history() == whichHistory + && (*i)->item()->id == whichMsgId) { + const auto j = i - 1; + return Dialogs::RowDescriptor( + (*j)->item()->history(), + (*j)->item()->id); + } + } + if (_searchResults[0]->item()->history() == whichHistory + && _searchResults[0]->item()->id == whichMsgId) { + if (_peerSearchResults.empty()) { + if (_filterResults.isEmpty()) { + return Dialogs::RowDescriptor(); + } + return Dialogs::RowDescriptor( + _filterResults.back()->key(), + ShowAtUnreadMsgId); + } + return Dialogs::RowDescriptor( + App::history(_peerSearchResults.back()->peer), + ShowAtUnreadMsgId); + } + } + if (!_peerSearchResults.empty() && _peerSearchResults[0]->peer == whichHistory->peer) { + if (_filterResults.isEmpty()) { + return Dialogs::RowDescriptor(); + } + return Dialogs::RowDescriptor( + _filterResults.back()->key(), + ShowAtUnreadMsgId); + } + if (!_peerSearchResults.empty()) { + for (auto b = _peerSearchResults.cbegin(), i = b + 1, e = _peerSearchResults.cend(); i != e; ++i) { + if ((*i)->peer == whichHistory->peer) { + return Dialogs::RowDescriptor( + App::history((*(i - 1))->peer), + ShowAtUnreadMsgId); } } } - outPeer = nullptr; - outMsg = 0; + if (_filterResults.isEmpty() || _filterResults[0]->key() == which.key) { + return Dialogs::RowDescriptor(); + } + + for (auto b = _filterResults.cbegin(), i = b + 1, e = _filterResults.cend(); i != e; ++i) { + if ((*i)->key() == which.key) { + return Dialogs::RowDescriptor( + (*(i - 1))->key(), + ShowAtUnreadMsgId); + } + } + return Dialogs::RowDescriptor(); } -void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { - if (!inPeer) { - outPeer = nullptr; - outMsg = 0; - return; +Dialogs::RowDescriptor DialogsInner::chatListEntryAfter( + const Dialogs::RowDescriptor &which) const { + if (!which.key.value) { + return Dialogs::RowDescriptor(); } if (_state == DefaultState) { - if (auto row = shownDialogs()->getRow(inPeer->id)) { - auto i = shownDialogs()->cfind(row) + 1; + if (const auto row = shownDialogs()->getRow(which.key)) { + const auto i = shownDialogs()->cfind(row) + 1; if (i != shownDialogs()->cend()) { - outPeer = (*i)->history()->peer; - outMsg = ShowAtUnreadMsgId; - return; + return Dialogs::RowDescriptor( + (*i)->key(), + ShowAtUnreadMsgId); } } - outPeer = nullptr; - outMsg = 0; - return; - } else if (_state == FilteredState || _state == SearchedState) { - if (inMsg) { - for (auto i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { - if ((*i)->item()->history()->peer == inPeer && (*i)->item()->id == inMsg) { - ++i; - outPeer = (i == e) ? nullptr : (*i)->item()->history()->peer; - outMsg = (i == e) ? 0 : (*i)->item()->id; - return; + return Dialogs::RowDescriptor(); + } + + const auto whichHistory = which.key.history(); + const auto whichMsgId = which.msgId; + if (!whichHistory) { + return Dialogs::RowDescriptor(); + } + if (whichMsgId) { + for (auto i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { + if ((*i)->item()->history() == whichHistory + && (*i)->item()->id == whichMsgId) { + if (++i != e) { + return Dialogs::RowDescriptor( + (*i)->item()->history(), + (*i)->item()->id); } - } - } - for (auto i = _peerSearchResults.cbegin(), e = _peerSearchResults.cend(); i != e; ++i) { - if ((*i)->peer == inPeer) { - ++i; - if (i == e && !_searchResults.empty()) { - outPeer = _searchResults.front()->item()->history()->peer; - outMsg = _searchResults.front()->item()->id; - } else { - outPeer = (i == e) ? nullptr : (*i)->peer; - outMsg = ShowAtUnreadMsgId; - } - return; - } - } - for (FilteredDialogs::const_iterator i = _filterResults.cbegin(), e = _filterResults.cend(); i != e; ++i) { - if ((*i)->history()->peer == inPeer) { - ++i; - if (i == e && !_peerSearchResults.empty()) { - outPeer = _peerSearchResults.front()->peer; - outMsg = ShowAtUnreadMsgId; - } else if (i == e && !_searchResults.empty()) { - outPeer = _searchResults.front()->item()->history()->peer; - outMsg = _searchResults.front()->item()->id; - } else { - outPeer = (i == e) ? nullptr : (*i)->history()->peer; - outMsg = ShowAtUnreadMsgId; - } - return; + return Dialogs::RowDescriptor(); } } } - outPeer = nullptr; - outMsg = 0; + for (auto i = _peerSearchResults.cbegin(), e = _peerSearchResults.cend(); i != e; ++i) { + if ((*i)->peer == whichHistory->peer) { + ++i; + if (i != e) { + return Dialogs::RowDescriptor( + App::history((*i)->peer), + ShowAtUnreadMsgId); + } else if (!_searchResults.empty()) { + return Dialogs::RowDescriptor( + _searchResults.front()->item()->history(), + _searchResults.front()->item()->id); + } + return Dialogs::RowDescriptor(); + } + } + for (auto i = _filterResults.cbegin(), e = _filterResults.cend(); i != e; ++i) { + if ((*i)->key() == which.key) { + ++i; + if (i != e) { + return Dialogs::RowDescriptor( + (*i)->key(), + ShowAtUnreadMsgId); + } else if (!_peerSearchResults.empty()) { + return Dialogs::RowDescriptor( + App::history(_peerSearchResults.front()->peer), + ShowAtUnreadMsgId); + } else if (!_searchResults.empty()) { + return Dialogs::RowDescriptor( + _searchResults.front()->item()->history(), + _searchResults.front()->item()->id); + } + return Dialogs::RowDescriptor(); + } + } + return Dialogs::RowDescriptor(); } Dialogs::IndexedList *DialogsInner::contactsList() { diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 6482300bc..0f1488bc9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -44,10 +44,10 @@ public: void selectSkip(int32 direction); void selectSkipPage(int32 pixels, int32 direction); - void createDialog(History *history); - void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row); - void dlgUpdated(PeerData *peer, MsgId msgId); - void removeDialog(History *history); + void createDialog(not_null history); + void dlgUpdated(Dialogs::Mode list, not_null row); + void dlgUpdated(not_null history, MsgId msgId); + void removeDialog(not_null history); void dragLeft(); @@ -59,9 +59,13 @@ public: void destroyData(); - void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; - void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; - void scrollToPeer(const PeerId &peer, MsgId msgId); + + Dialogs::RowDescriptor chatListEntryBefore( + const Dialogs::RowDescriptor &which) const; + Dialogs::RowDescriptor chatListEntryAfter( + const Dialogs::RowDescriptor &which) const; + + void scrollToPeer(not_null history, MsgId msgId); Dialogs::IndexedList *contactsList(); Dialogs::IndexedList *dialogsList(); @@ -185,8 +189,9 @@ private: using UpdateRowSections = base::flags; friend inline constexpr auto is_flag_type(UpdateRowSection) { return true; }; + void updateSearchResult(not_null peer); void updateDialogRow( - PeerData *peer, + not_null history, MsgId msgId, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All); @@ -197,9 +202,27 @@ private: int searchedOffset() const; int searchInPeerSkip() const; - void paintDialog(Painter &p, Dialogs::Row *row, int fullWidth, PeerData *active, PeerData *selected, bool onlyBackground, TimeMs ms); - void paintPeerSearchResult(Painter &p, const PeerSearchResult *result, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) const; - void paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackground, TimeMs ms) const; + void paintDialog( + Painter &p, + not_null row, + int fullWidth, + PeerData *active, + PeerData *selected, + bool onlyBackground, + TimeMs ms); + void paintPeerSearchResult( + Painter &p, + not_null result, + int fullWidth, + bool active, + bool selected, + bool onlyBackground, + TimeMs ms) const; + void paintSearchInPeer( + Painter &p, + int fullWidth, + bool onlyBackground, + TimeMs ms) const; void paintSearchInFilter( Painter &p, PeerData *peer, diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index d12aabd38..c18b9c48d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -334,6 +334,7 @@ void RowPainter::paint( bool selected, bool onlyBackground, TimeMs ms) { + // #TODO feeds show auto history = row->history(); auto item = history->lastMsg; auto cloudDraft = history->cloudDraft(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_list.cpp index b1c05f041..de685718b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_list.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Dialogs { List::List(SortMode sortMode) -: _last(std::make_unique(nullptr, nullptr, nullptr, 0)) +: _last(std::make_unique(nullptr)) , _begin(_last.get()) , _end(_last.get()) , _sortMode(sortMode) @@ -33,15 +33,15 @@ void List::adjustCurrent(int32 y, int32 h) const { } } -Row *List::addToEnd(not_null history) { - const auto result = new Row(history, _end->_prev, _end, _end->_pos); +Row *List::addToEnd(Key key) { + const auto result = new Row(key, _end->_prev, _end, _end->_pos); _end->_pos++; if (_begin == _end) { _begin = _current = result; } else { _end->_prev->_next = result; } - _rowByPeer.insert(history->peer->id, result); + _rowByKey.emplace(key, result); ++_count; _end->_prev = result; if (_sortMode == SortMode::Date) { @@ -51,13 +51,15 @@ Row *List::addToEnd(not_null history) { } bool List::insertBefore(Row *row, Row *before) { - if (row == before) return false; + if (row == before) { + return false; + } if (_current == row) { _current = row->_prev; } - Row *updateTill = row->_prev; + const auto updateTill = row->_prev; remove(row); // insert row @@ -70,8 +72,8 @@ bool List::insertBefore(Row *row, Row *before) { _begin = row; } - // update y - for (Row *n = row; n != updateTill; n = n->_next) { + // update pos + for (auto n = row; n != updateTill; n = n->_next) { n->_next->_pos++; row->_pos--; } @@ -79,13 +81,15 @@ bool List::insertBefore(Row *row, Row *before) { } bool List::insertAfter(Row *row, Row *after) { - if (row == after) return false; + if (row == after) { + return false; + } if (_current == row) { _current = row->_next; } - Row *updateFrom = row->_next; + const auto updateFrom = row->_next; remove(row); // insert row @@ -94,26 +98,28 @@ bool List::insertAfter(Row *row, Row *after) { row->_prev->_next = row; // update row->prev row->_next->_prev = row; // update row->next - // update y - for (Row *n = updateFrom; n != row; n = n->_next) { + // update pos + for (auto n = updateFrom; n != row; n = n->_next) { n->_pos--; row->_pos++; } return true; } -Row *List::adjustByName(const PeerData *peer) { +Row *List::adjustByName(Key key) { if (_sortMode != SortMode::Name) return nullptr; - auto i = _rowByPeer.find(peer->id); - if (i == _rowByPeer.cend()) return nullptr; + const auto i = _rowByKey.find(key); + if (i == _rowByKey.cend()) return nullptr; - Row *row = i.value(), *change = row; - while (change->_prev && change->_prev->history()->peer->name > peer->name) { + const auto row = i->second; + const auto name = key.name(); + auto change = row; + while (change->_prev && change->_prev->name().compare(name, Qt::CaseInsensitive) < 0) { change = change->_prev; } if (!insertBefore(row, change)) { - while (change->_next != _end && change->_next->history()->peer->name < peer->name) { + while (change->_next != _end && change->_next->name().compare(name, Qt::CaseInsensitive) < 0) { change = change->_next; } insertAfter(row, change); @@ -121,19 +127,19 @@ Row *List::adjustByName(const PeerData *peer) { return row; } -Row *List::addByName(not_null history) { +Row *List::addByName(Key key) { if (_sortMode != SortMode::Name) { return nullptr; } - const auto row = addToEnd(history); + const auto row = addToEnd(key); auto change = row; - const QString &peerName(history->peer->name); - while (change->_prev && change->_prev->history()->peer->name.compare(peerName, Qt::CaseInsensitive) > 0) { + const auto name = key.name(); + while (change->_prev && change->_prev->name().compare(name, Qt::CaseInsensitive) > 0) { change = change->_prev; } if (!insertBefore(row, change)) { - while (change->_next != _end && change->_next->history()->peer->name.compare(peerName, Qt::CaseInsensitive) < 0) { + while (change->_next != _end && change->_next->name().compare(name, Qt::CaseInsensitive) < 0) { change = change->_next; } insertAfter(row, change); @@ -145,18 +151,18 @@ void List::adjustByPos(Row *row) { if (_sortMode != SortMode::Date || !_begin) return; Row *change = row; - if (change != _begin && _begin->history()->sortKeyInChatList() < row->history()->sortKeyInChatList()) { + if (change != _begin && _begin->sortKey() < row->sortKey()) { change = _begin; } else { - while (change->_prev && change->_prev->history()->sortKeyInChatList() < row->history()->sortKeyInChatList()) { + while (change->_prev && change->_prev->sortKey() < row->sortKey()) { change = change->_prev; } } if (!insertBefore(row, change)) { - if (change->_next != _end && _end->_prev->history()->sortKeyInChatList() > row->history()->sortKeyInChatList()) { + if (change->_next != _end && _end->_prev->sortKey() > row->sortKey()) { change = _end->_prev; } else { - while (change->_next != _end && change->_next->history()->sortKeyInChatList() > row->history()->sortKeyInChatList()) { + while (change->_next != _end && change->_next->sortKey() > row->sortKey()) { change = change->_next; } } @@ -164,19 +170,23 @@ void List::adjustByPos(Row *row) { } } -bool List::moveToTop(PeerId peerId) { - auto i = _rowByPeer.find(peerId); - if (i == _rowByPeer.cend()) return false; +bool List::moveToTop(Key key) { + auto i = _rowByKey.find(key); + if (i == _rowByKey.cend()) { + return false; + } - insertBefore(i.value(), _begin); + insertBefore(i->second, _begin); return true; } -bool List::del(PeerId peerId, Row *replacedBy) { - auto i = _rowByPeer.find(peerId); - if (i == _rowByPeer.cend()) return false; +bool List::del(Key key, Row *replacedBy) { + auto i = _rowByKey.find(key); + if (i == _rowByKey.cend()) { + return false; + } - auto row = i.value(); + const auto row = i->second; if (App::main()) { emit App::main()->dialogRowReplaced(row, replacedBy); } @@ -191,7 +201,7 @@ bool List::del(PeerId peerId, Row *replacedBy) { remove(row); delete row; --_count; - _rowByPeer.erase(i); + _rowByKey.erase(i); return true; } @@ -212,7 +222,7 @@ void List::clear() { delete _current; } _current = _begin; - _rowByPeer.clear(); + _rowByKey.clear(); _count = 0; } diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.h b/Telegram/SourceFiles/dialogs/dialogs_list.h index fa3698062..d32dcde85 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_list.h @@ -24,11 +24,12 @@ public: bool isEmpty() const { return size() == 0; } - bool contains(PeerId peerId) const { - return _rowByPeer.contains(peerId); + bool contains(Key key) const { + return _rowByKey.find(key) != _rowByKey.end(); } - Row *getRow(PeerId peerId) const { - return _rowByPeer.value(peerId); + Row *getRow(Key key) const { + const auto i = _rowByKey.find(key); + return (i == _rowByKey.end()) ? nullptr : i->second.get(); } Row *rowAtY(int32 y, int32 h) const { auto i = cfind(y, h); @@ -38,12 +39,12 @@ public: return *i; } - Row *addToEnd(not_null history); - Row *adjustByName(const PeerData *peer); - Row *addByName(not_null history); - bool moveToTop(PeerId peerId); + Row *addToEnd(Key key); + Row *adjustByName(Key key); + Row *addByName(Key key); + bool moveToTop(Key key); void adjustByPos(Row *row); - bool del(PeerId peerId, Row *replacedBy = nullptr); + bool del(Key key, Row *replacedBy = nullptr); void remove(Row *row); void clear(); @@ -114,10 +115,10 @@ private: SortMode _sortMode; int _count = 0; - typedef QHash RowByPeer; - RowByPeer _rowByPeer; + std::map> _rowByKey; mutable Row *_current; // cache + }; } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index 1f84212b7..f3dff3669 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -8,10 +8,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/text/text.h" +#include "base/value_ordering.h" class History; class HistoryItem; +namespace Data { +class Feed; +} // namespace Data + namespace Ui { class RippleAnimation; } // namespace Ui @@ -21,6 +26,79 @@ namespace Layout { class RowPainter; } // namespace Layout +struct Key { + Key() = default; + Key(History *history) : value(history) { + } + Key(not_null history) : value(history) { + } + Key(Data::Feed *feed) : value(feed) { + } + Key(not_null feed) : value(feed) { + } + const QString &name() const { + if (const auto p = base::get_if>(&value)) { + return (*p)->peer->name; + } + // #TODO feeds name + static const auto empty = QString(); + return empty; + } + const PeerData::NameFirstChars &nameFirstChars() const { + if (const auto p = base::get_if>(&value)) { + return (*p)->peer->nameFirstChars(); + } + // #TODO feeds name + static const auto empty = PeerData::NameFirstChars(); + return empty; + } + uint64 sortKey() const { + if (const auto p = base::get_if>(&value)) { + return (*p)->sortKeyInChatList(); + } + // #TODO feeds sort in chats list + return 0ULL; + } + History *history() const { + if (const auto p = base::get_if>(&value)) { + return *p; + } + return nullptr; + } + Data::Feed *feed() const { + if (const auto p = base::get_if>(&value)) { + return *p; + } + return nullptr; + } + + inline bool operator<(const Key &other) const { + return value < other.value; + } + inline bool operator==(const Key &other) const { + return value == other.value; + } + + // Not working :( + //friend inline auto value_ordering_helper(const Key &key) { + // return key.value; + //} + + base::optional_variant< + not_null, + not_null> value; + +}; + +struct RowDescriptor { + RowDescriptor() = default; + RowDescriptor(Key key, MsgId msgId) : key(key), msgId(msgId) { + } + + Key key; + MsgId msgId = 0; +}; + class RippleRow { public: RippleRow(); @@ -39,27 +117,44 @@ private: class List; class Row : public RippleRow { public: - Row(History *history, Row *prev, Row *next, int pos) - : _history(history) - , _prev(prev) - , _next(next) - , _pos(pos) { + explicit Row(std::nullptr_t) { + } + Row(Key key, Row *prev, Row *next, int pos) + : _id(key) + , _prev(prev) + , _next(next) + , _pos(pos) { } - void *attached = nullptr; // for any attached data, for example View in contacts list + Key key() const { + return _id; + } History *history() const { - return _history; + return _id.history(); + } + Data::Feed *feed() const { + return _id.feed(); + } + QString name() const { + return _id.name(); } int pos() const { return _pos; } + uint64 sortKey() const { + return _id.sortKey(); + } + + // for any attached data, for example View in contacts list + void *attached = nullptr; private: friend class List; - History *_history; - Row *_prev, *_next; - int _pos; + Key _id; + Row *_prev = nullptr; + Row *_next = nullptr; + int _pos = 0; }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 27dc7ea54..9857e7082 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -9,8 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_inner_widget.h" #include "dialogs/dialogs_search_from_controllers.h" -#include "styles/style_dialogs.h" -#include "styles/style_window.h" +#include "dialogs/dialogs_row.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/wrap/fade_wrap.h" @@ -28,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "profile/profile_channel_controllers.h" #include "storage/storage_media_prepare.h" #include "data/data_session.h" +#include "styles/style_dialogs.h" +#include "styles/style_window.h" namespace { @@ -181,11 +182,11 @@ void DialogsWidget::activate() { _inner->activate(); } -void DialogsWidget::createDialog(History *history) { +void DialogsWidget::createDialog(not_null history) { auto creating = !history->inChatList(Dialogs::Mode::All); _inner->createDialog(history); if (creating && history->peer->migrateFrom()) { - if (auto migrated = App::historyLoaded(history->peer->migrateFrom()->id)) { + if (const auto migrated = App::historyLoaded(history->peer->migrateFrom())) { if (migrated->inChatList(Dialogs::Mode::All)) { removeDialog(migrated); } @@ -193,12 +194,14 @@ void DialogsWidget::createDialog(History *history) { } } -void DialogsWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) { +void DialogsWidget::dlgUpdated( + Dialogs::Mode list, + not_null row) { _inner->dlgUpdated(list, row); } -void DialogsWidget::dlgUpdated(PeerData *peer, MsgId msgId) { - _inner->dlgUpdated(peer, msgId); +void DialogsWidget::dlgUpdated(not_null history, MsgId msgId) { + _inner->dlgUpdated(history, msgId); } void DialogsWidget::dialogsToUp() { @@ -1103,19 +1106,21 @@ void DialogsWidget::destroyData() { _inner->destroyData(); } -void DialogsWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { - return _inner->peerBefore(inPeer, inMsg, outPeer, outMsg); +Dialogs::RowDescriptor DialogsWidget::chatListEntryBefore( + const Dialogs::RowDescriptor &which) const { + return _inner->chatListEntryBefore(which); } -void DialogsWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { - return _inner->peerAfter(inPeer, inMsg, outPeer, outMsg); +Dialogs::RowDescriptor DialogsWidget::chatListEntryAfter( + const Dialogs::RowDescriptor &which) const { + return _inner->chatListEntryAfter(which); } -void DialogsWidget::scrollToPeer(const PeerId &peer, MsgId msgId) { - _inner->scrollToPeer(peer, msgId); +void DialogsWidget::scrollToPeer(not_null history, MsgId msgId) { + _inner->scrollToPeer(history, msgId); } -void DialogsWidget::removeDialog(History *history) { +void DialogsWidget::removeDialog(not_null history) { _inner->removeDialog(history); onFilterUpdate(); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 2768936f9..562354d9d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class DialogsInner; namespace Dialogs { +struct RowDescriptor; class Row; class FakeRow; class IndexedList; @@ -54,9 +55,10 @@ public: void loadDialogs(); void loadPinnedDialogs(); - void createDialog(History *history); - void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row); - void dlgUpdated(PeerData *peer, MsgId msgId); + void createDialog(not_null history); + void removeDialog(not_null history); + void dlgUpdated(Dialogs::Mode list, not_null row); + void dlgUpdated(not_null history, MsgId msgId); void dialogsToUp(); @@ -71,11 +73,12 @@ public: void destroyData(); - void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; - void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; - void scrollToPeer(const PeerId &peer, MsgId msgId); + Dialogs::RowDescriptor chatListEntryBefore( + const Dialogs::RowDescriptor &which) const; + Dialogs::RowDescriptor chatListEntryAfter( + const Dialogs::RowDescriptor &which) const; - void removeDialog(History *history); + void scrollToPeer(not_null history, MsgId msgId); Dialogs::IndexedList *contactsList(); Dialogs::IndexedList *dialogsList(); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 32acd562f..2ca6e2ad8 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -168,12 +168,6 @@ void joinGroupByHash(const QString &hash) { if (MainWidget *m = main()) m->joinGroupByHash(hash); } -void removeDialog(History *history) { - if (MainWidget *m = main()) { - m->removeDialog(history); - } -} - void showSettings() { if (auto w = wnd()) { w->showSettings(); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index a892e051d..d46b48430 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -133,7 +133,6 @@ void openPeerByName( MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString()); void joinGroupByHash(const QString &hash); -void removeDialog(History *history); void showSettings(); void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button); diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 954c641fe..d25dd2424 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2564,7 +2564,7 @@ Dialogs::Row *History::addToChatList(Dialogs::Mode list, Dialogs::IndexedList *i void History::removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) { Assert(indexed != nullptr); if (inChatList(list)) { - indexed->del(peer); + indexed->del(this); chatListLinks(list).clear(); if (list == Dialogs::Mode::All && unreadCount()) { App::histories().unreadIncrement(-unreadCount(), mute()); @@ -2590,9 +2590,13 @@ void History::addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs void History::updateChatListEntry() const { if (auto main = App::main()) { if (inChatList(Dialogs::Mode::All)) { - main->dlgUpdated(Dialogs::Mode::All, mainChatListLink(Dialogs::Mode::All)); + main->dlgUpdated( + Dialogs::Mode::All, + mainChatListLink(Dialogs::Mode::All)); if (inChatList(Dialogs::Mode::Important)) { - main->dlgUpdated(Dialogs::Mode::Important, mainChatListLink(Dialogs::Mode::Important)); + main->dlgUpdated( + Dialogs::Mode::Important, + mainChatListLink(Dialogs::Mode::Important)); } } } diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 2db09e271..dd6089f5a 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -164,7 +164,8 @@ ReplyKeyboard *HistoryItem::inlineReplyKeyboard() { void HistoryItem::invalidateChatsListEntry() { if (App::main()) { - App::main()->dlgUpdated(history()->peer, id); + // #TODO feeds dialogs + App::main()->dlgUpdated(history(), id); } // invalidate cache for drawInDialog diff --git a/Telegram/SourceFiles/history/history_service.cpp b/Telegram/SourceFiles/history/history_service.cpp index 783ad64c7..9d79de344 100644 --- a/Telegram/SourceFiles/history/history_service.cpp +++ b/Telegram/SourceFiles/history/history_service.cpp @@ -775,7 +775,8 @@ void HistoryService::updateDependentText() { history()->textCachedFor = nullptr; } if (App::main()) { - App::main()->dlgUpdated(history()->peer, id); + // #TODO feeds dialogs + App::main()->dlgUpdated(history(), id); } App::historyUpdateDependent(this); } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index b8f26f1e3..46bea9634 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -7,13 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "history/history_widget.h" -#include "styles/style_history.h" -#include "styles/style_dialogs.h" -#include "styles/style_window.h" -#include "styles/style_boxes.h" -#include "styles/style_profile.h" -#include "styles/style_chat_helpers.h" -#include "styles/style_info.h" #include "boxes/confirm_box.h" #include "boxes/send_files_box.h" #include "boxes/share_box.h" @@ -72,6 +65,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_results_widget.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "core/crash_reports.h" +#include "dialogs/dialogs_row.h" +#include "styles/style_history.h" +#include "styles/style_dialogs.h" +#include "styles/style_window.h" +#include "styles/style_boxes.h" +#include "styles/style_profile.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_info.h" namespace { @@ -1391,24 +1392,30 @@ bool HistoryWidget::cmd_search() { } bool HistoryWidget::cmd_next_chat() { - PeerData *p = 0; - MsgId m = 0; - App::main()->peerAfter(_peer, qMax(_showAtMsgId, 0), p, m); - if (p) { - Ui::showPeerHistory(p, m); + if (!_history) { + return false; + } + const auto next = App::main()->chatListEntryAfter( + Dialogs::RowDescriptor(_history, std::max(_showAtMsgId, 0))); + if (const auto history = next.key.history()) { + Ui::showPeerHistory(history, next.msgId); return true; } + // #TODO feeds show return false; } bool HistoryWidget::cmd_previous_chat() { - PeerData *p = 0; - MsgId m = 0; - App::main()->peerBefore(_peer, qMax(_showAtMsgId, 0), p, m); - if (p) { - Ui::showPeerHistory(p, m); + if (!_history) { + return false; + } + const auto next = App::main()->chatListEntryBefore( + Dialogs::RowDescriptor(_history, std::max(_showAtMsgId, 0))); + if (const auto history = next.key.history()) { + Ui::showPeerHistory(history, next.msgId); return true; } + // #TODO feeds show return false; } @@ -1579,7 +1586,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re if (!canShowNow) { delayedShowAt(showAtMsgId); - App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId); + if (wasHistory) { + App::main()->dlgUpdated(wasHistory, wasMsgId); + } emit historyShown(_history, _showAtMsgId); } else { _history->forgetScrollState(); @@ -1780,7 +1789,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); - App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId); + if (wasHistory) { + App::main()->dlgUpdated(wasHistory, wasMsgId); + } emit historyShown(_history, _showAtMsgId); controller()->historyPeer = _peer; @@ -2988,11 +2999,14 @@ PeerData *HistoryWidget::peer() const { return _peer; } -void HistoryWidget::setMsgId(MsgId showAtMsgId) { // sometimes _showAtMsgId is set directly +// Sometimes _showAtMsgId is set directly. +void HistoryWidget::setMsgId(MsgId showAtMsgId) { if (_showAtMsgId != showAtMsgId) { auto wasMsgId = _showAtMsgId; _showAtMsgId = showAtMsgId; - App::main()->dlgUpdated(_history ? _history->peer : nullptr, wasMsgId); + if (_history) { + App::main()->dlgUpdated(_history, wasMsgId); + } emit historyShown(_history, _showAtMsgId); } } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 195f665e5..75fc425e1 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -15,15 +15,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_web_page.h" #include "data/data_game.h" #include "data/data_peer_values.h" -#include "styles/style_dialogs.h" -#include "styles/style_history.h" +#include "data/data_drafts.h" +#include "data/data_session.h" #include "ui/special_buttons.h" #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" #include "window/section_memento.h" #include "window/section_widget.h" -#include "data/data_drafts.h" -#include "data/data_session.h" #include "ui/widgets/dropdown_menu.h" #include "ui/focus_persister.h" #include "ui/resize_area.h" @@ -36,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "observer_peer.h" #include "apiwrap.h" #include "dialogs/dialogs_widget.h" +#include "dialogs/dialogs_row.h" #include "history/history_widget.h" #include "history/history_message.h" #include "history/history_media.h" @@ -69,16 +68,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_slide_animation.h" #include "window/window_controller.h" #include "window/themes/window_theme.h" -#include "styles/style_boxes.h" #include "mtproto/dc_options.h" #include "core/file_utilities.h" -#include "auth_session.h" #include "calls/calls_instance.h" #include "calls/calls_top_bar.h" #include "auth_session.h" #include "storage/storage_facade.h" #include "storage/storage_shared_media.h" #include "storage/storage_user_photos.h" +#include "styles/style_dialogs.h" +#include "styles/style_history.h" +#include "styles/style_boxes.h" enum StackItemType { HistoryStackItem, @@ -120,10 +120,11 @@ private: class StackItemHistory : public StackItem { public: StackItemHistory( - PeerData *peer, + not_null history, MsgId msgId, QList replyReturns) - : StackItem(peer) + : StackItem(history->peer) + , history(history) , msgId(msgId) , replyReturns(replyReturns) { } @@ -132,6 +133,7 @@ public: return HistoryStackItem; } + not_null history; MsgId msgId; QList replyReturns; @@ -902,7 +904,7 @@ void MainWidget::hiderLayer(object_ptr h) { _hider->hide(); auto animationParams = prepareDialogsAnimation(); - onHistoryShown(0, 0); + onHistoryShown(nullptr, 0); if (_mainSection) { _mainSection->hide(); } else { @@ -1089,7 +1091,7 @@ void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result) App::feedUserLink(MTP_int(peerToUser(user->id)), d.vmy_link, d.vforeign_link); } -void MainWidget::removeDialog(History *history) { +void MainWidget::removeDialog(not_null history) { _dialogs->removeDialog(history); } @@ -2198,7 +2200,7 @@ bool MainWidget::viewsIncrementFail(const RPCError &error, mtpRequestId req) { return false; } -void MainWidget::createDialog(History *history) { +void MainWidget::createDialog(not_null history) { _dialogs->createDialog(history); } @@ -2307,15 +2309,12 @@ void MainWidget::ui_showPeerHistory( auto animationParams = animatedShow() ? prepareHistoryAnimation(peerId) : Window::SectionSlideParams(); - dlgUpdated(); if (back || (way == Way::ClearStack)) { - _peerInStack = nullptr; - _msgIdInStack = 0; + clearEntryInStack(); } else { // This may modify the current section, for example remove its contents. saveSectionInStack(); } - dlgUpdated(); if (_history->peer() && _history->peer()->id != peerId && way != Way::Forward) { clearBotStartToken(_history->peer()); @@ -2371,7 +2370,9 @@ void MainWidget::ui_showPeerHistory( if (!_dialogs->isHidden()) { if (!back) { - _dialogs->scrollToPeer(peerId, showAtMsgId); + if (const auto history = _history->history()) { + _dialogs->scrollToPeer(history, showAtMsgId); + } } _dialogs->update(); } @@ -2387,22 +2388,20 @@ PeerData *MainWidget::ui_getPeerForMouseAction() { return _history->ui_getPeerForMouseAction(); } -void MainWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) { +Dialogs::RowDescriptor MainWidget::chatListEntryBefore( + const Dialogs::RowDescriptor &which) const { if (selectingPeer()) { - outPeer = 0; - outMsg = 0; - return; + return Dialogs::RowDescriptor(); } - _dialogs->peerBefore(inPeer, inMsg, outPeer, outMsg); + return _dialogs->chatListEntryBefore(which); } -void MainWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) { +Dialogs::RowDescriptor MainWidget::chatListEntryAfter( + const Dialogs::RowDescriptor &which) const { if (selectingPeer()) { - outPeer = 0; - outMsg = 0; - return; + return Dialogs::RowDescriptor(); } - _dialogs->peerAfter(inPeer, inMsg, outPeer, outMsg); + return _dialogs->chatListEntryAfter(which); } PeerData *MainWidget::peer() { @@ -2410,13 +2409,33 @@ PeerData *MainWidget::peer() { } PeerData *MainWidget::activePeer() { - return _history->peer() ? _history->peer() : _peerInStack; + if (const auto history = _history->history()) { + return history->peer; + } else if (_historyInStack) { + return _historyInStack->peer; + } + return nullptr; } MsgId MainWidget::activeMsgId() { return _history->peer() ? _history->msgId() : _msgIdInStack; } +void MainWidget::setEntryInStack(not_null history, MsgId msgId) { + setEntryInStackValues(history, msgId); +} + +void MainWidget::clearEntryInStack() { + setEntryInStackValues(nullptr, 0); +} + +void MainWidget::setEntryInStackValues(History *history, MsgId msgId) { + updateCurrentChatListEntry(); + _historyInStack = history; + _msgIdInStack = msgId; + updateCurrentChatListEntry(); +} + void MainWidget::saveSectionInStack() { if (_mainSection) { if (auto memento = _mainSection->createMemento()) { @@ -2424,11 +2443,10 @@ void MainWidget::saveSectionInStack() { std::move(memento))); _stack.back()->setThirdSectionWeak(_thirdSection.data()); } - } else if (_history->peer()) { - _peerInStack = _history->peer(); - _msgIdInStack = _history->msgId(); + } else if (const auto history = _history->history()) { + setEntryInStack(history, _history->msgId()); _stack.push_back(std::make_unique( - _peerInStack, + _historyInStack, _msgIdInStack, _history->replyReturns())); _stack.back()->setThirdSectionWeak(_thirdSection.data()); @@ -2765,15 +2783,11 @@ void MainWidget::showBackFromStack( } _thirdSectionFromStack = item->takeThirdSectionMemento(); if (item->type() == HistoryStackItem) { - dlgUpdated(); - _peerInStack = nullptr; - _msgIdInStack = 0; + clearEntryInStack(); for (auto i = _stack.size(); i > 0;) { if (_stack[--i]->type() == HistoryStackItem) { auto historyItem = static_cast(_stack[i].get()); - _peerInStack = historyItem->peer(); - _msgIdInStack = historyItem->msgId; - dlgUpdated(); + setEntryInStack(historyItem->history, historyItem->msgId); break; } } @@ -2899,24 +2913,29 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m return result; } -void MainWidget::dlgUpdated() { - if (_peerInStack) { - _dialogs->dlgUpdated(_peerInStack, _msgIdInStack); +void MainWidget::updateCurrentChatListEntry() { + if (_historyInStack) { + _dialogs->dlgUpdated(_historyInStack, _msgIdInStack); } } -void MainWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) { +void MainWidget::dlgUpdated( + Dialogs::Mode list, + not_null row) { if (row) { _dialogs->dlgUpdated(list, row); } } -void MainWidget::dlgUpdated(PeerData *peer, MsgId msgId) { - if (!peer) return; - if (msgId < 0 && -msgId < ServerMaxMsgId && peer->migrateFrom()) { - _dialogs->dlgUpdated(peer->migrateFrom(), -msgId); +void MainWidget::dlgUpdated(not_null history, MsgId msgId) { + if (msgId < 0 && -msgId < ServerMaxMsgId) { + if (const auto from = history->peer->migrateFrom()) { + if (const auto migrated = App::historyLoaded(from)) { + _dialogs->dlgUpdated(migrated, -msgId); + } + } } else { - _dialogs->dlgUpdated(peer, msgId); + _dialogs->dlgUpdated(history, msgId); } } @@ -3539,7 +3558,9 @@ int MainWidget::backgroundFromY() const { void MainWidget::onHistoryShown(History *history, MsgId atMsgId) { // updateControlsGeometry(); - dlgUpdated(history ? history->peer : nullptr, atMsgId); + if (history) { + dlgUpdated(history, atMsgId); + } } void MainWidget::searchInPeer(PeerData *peer) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index fc3d57140..3782373ca 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -25,6 +25,7 @@ struct PeerUpdate; } // namespace Notify namespace Dialogs { +struct RowDescriptor; class Row; } // namespace Dialogs @@ -105,11 +106,10 @@ public: void activate(); - void createDialog(History *history); - void removeDialog(History *history); - void dlgUpdated(); - void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row); - void dlgUpdated(PeerData *peer, MsgId msgId); + void createDialog(not_null history); + void removeDialog(not_null history); + void dlgUpdated(Dialogs::Mode list, not_null row); + void dlgUpdated(not_null history, MsgId msgId); void windowShown(); @@ -126,10 +126,12 @@ public: void newUnreadMsg(History *history, HistoryItem *item); void markActiveHistoryAsRead(); - void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); - void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); - PeerData *peer(); + Dialogs::RowDescriptor chatListEntryBefore( + const Dialogs::RowDescriptor &which) const; + Dialogs::RowDescriptor chatListEntryAfter( + const Dialogs::RowDescriptor &which) const; + PeerData *peer(); PeerData *activePeer(); MsgId activeMsgId(); @@ -438,6 +440,11 @@ private: void closeBothPlayers(); void playerHeightUpdated(); + void updateCurrentChatListEntry(); + void setEntryInStack(not_null history, MsgId msgId); + void clearEntryInStack(); + void setEntryInStackValues(History *history, MsgId msgId); + void setCurrentCall(Calls::Call *call); void createCallTopBar(); void destroyCallTopBar(); @@ -581,7 +588,7 @@ private: QPointer _forwardConfirm; // for single column layout object_ptr _hider = { nullptr }; std::vector> _stack; - PeerData *_peerInStack = nullptr; + History *_historyInStack = nullptr; MsgId _msgIdInStack = 0; int _playerHeight = 0; diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp index 354e7ed24..c7cebd2e3 100644 --- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp +++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp @@ -1935,6 +1935,7 @@ void AddParticipantBoxSearchController::addChatsContacts() { } for_const (auto row, *list) { + // #TODO feeds list if (auto user = row->history()->peer->asUser()) { if (allWordsAreFound(user->nameWords())) { delegate()->peerListSearchAddRow(user);