From d581e00299ccbac10845f425dc2ef3fc34268305 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 12 May 2017 16:53:08 +0300 Subject: [PATCH] Improve history items management. Encapsulate HistoryBlock::y and HistoryBlock::height. --- Telegram/SourceFiles/config.h | 3 - Telegram/SourceFiles/history.cpp | 175 +++++++++--------- Telegram/SourceFiles/history.h | 39 ++-- .../history/history_inner_widget.cpp | 83 +++++---- Telegram/SourceFiles/history/history_item.cpp | 1 - Telegram/SourceFiles/history/history_item.h | 30 +-- Telegram/SourceFiles/historywidget.cpp | 38 ++-- 7 files changed, 199 insertions(+), 170 deletions(-) diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 11b1dced38..5d84a57037 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -312,9 +312,6 @@ enum { DialogsFirstLoad = 20, // first dialogs part size requested DialogsPerPage = 500, // next dialogs part size - MessagesFirstLoad = 30, // first history part size requested - MessagesPerPage = 50, // next history part size - FileLoaderQueueStopTimeout = 5000, UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 43d10e09e9..5379281fe7 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -36,19 +36,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace { -constexpr int kStatusShowClientsideTyping = 6000; -constexpr int kStatusShowClientsideRecordVideo = 6000; -constexpr int kStatusShowClientsideUploadVideo = 6000; -constexpr int kStatusShowClientsideRecordVoice = 6000; -constexpr int kStatusShowClientsideUploadVoice = 6000; -constexpr int kStatusShowClientsideRecordRound = 6000; -constexpr int kStatusShowClientsideUploadRound = 6000; -constexpr int kStatusShowClientsideUploadPhoto = 6000; -constexpr int kStatusShowClientsideUploadFile = 6000; -constexpr int kStatusShowClientsideChooseLocation = 6000; -constexpr int kStatusShowClientsideChooseContact = 6000; -constexpr int kStatusShowClientsidePlayGame = 10000; -constexpr int kSetMyActionForMs = 10000; +constexpr auto kStatusShowClientsideTyping = 6000; +constexpr auto kStatusShowClientsideRecordVideo = 6000; +constexpr auto kStatusShowClientsideUploadVideo = 6000; +constexpr auto kStatusShowClientsideRecordVoice = 6000; +constexpr auto kStatusShowClientsideUploadVoice = 6000; +constexpr auto kStatusShowClientsideRecordRound = 6000; +constexpr auto kStatusShowClientsideUploadRound = 6000; +constexpr auto kStatusShowClientsideUploadPhoto = 6000; +constexpr auto kStatusShowClientsideUploadFile = 6000; +constexpr auto kStatusShowClientsideChooseLocation = 6000; +constexpr auto kStatusShowClientsideChooseContact = 6000; +constexpr auto kStatusShowClientsidePlayGame = 10000; +constexpr auto kSetMyActionForMs = 10000; +constexpr auto kNewBlockEachMessage = 50; auto GlobalPinnedIndex = 0; @@ -357,11 +358,12 @@ bool History::updateSendActionNeedsAnimating(TimeMs ms, bool force) { } void ChannelHistory::getRangeDifference() { - auto fromId = MsgId(0), toId = MsgId(0); + auto fromId = MsgId(0); + auto toId = MsgId(0); for (auto blockIndex = 0, blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) { - auto block = blocks.at(blockIndex); + auto block = blocks[blockIndex]; for (auto itemIndex = 0, itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) { - auto item = block->items.at(itemIndex); + auto item = block->items[itemIndex]; if (item->id > 0) { fromId = item->id; break; @@ -372,9 +374,9 @@ void ChannelHistory::getRangeDifference() { if (!fromId) return; for (auto blockIndex = blocks.size(); blockIndex > 0;) { - auto block = blocks.at(--blockIndex); + auto block = blocks[--blockIndex]; for (auto itemIndex = block->items.size(); itemIndex > 0;) { - auto item = block->items.at(--itemIndex); + auto item = block->items[--itemIndex]; if (item->id > 0) { toId = item->id; break; @@ -428,9 +430,9 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } for (auto blockIndex = blocks.size(); blockIndex > 0;) { - auto block = blocks.at(--blockIndex); + auto block = blocks[--blockIndex]; for (auto itemIndex = block->items.size(); itemIndex > 0;) { - auto item = block->items.at(--itemIndex); + auto item = block->items[--itemIndex]; // Due to a server bug sometimes inviteDate is less (before) than the // first message in the megagroup (message about migration), let us @@ -498,10 +500,10 @@ void ChannelHistory::checkJoinedMessage(bool createUnread) { void ChannelHistory::checkMaxReadMessageDate() { if (_maxReadMessageDate.isValid()) return; - for (int blockIndex = blocks.size(); blockIndex > 0;) { - HistoryBlock *block = blocks.at(--blockIndex); - for (int itemIndex = block->items.size(); itemIndex > 0;) { - HistoryItem *item = block->items.at(--itemIndex); + for (auto blockIndex = blocks.size(); blockIndex > 0;) { + auto block = blocks[--blockIndex]; + for (auto itemIndex = block->items.size(); itemIndex > 0;) { + auto item = block->items[--itemIndex]; if (!item->unread()) { _maxReadMessageDate = item->date; if (item->isGroupMigrate() && isMegagroup() && peer->migrateFrom()) { @@ -1105,7 +1107,7 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) { } HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) { - t_assert(!isBuildingFrontBlock()); + Expects(!isBuildingFrontBlock()); addItemToBlock(adding); setLastMessage(adding); @@ -1237,12 +1239,12 @@ HistoryBlock *History::prepareBlockForAddingItem() { result->setIndexInHistory(0); blocks.push_front(result); for (int i = 1, l = blocks.size(); i < l; ++i) { - blocks.at(i)->setIndexInHistory(i); + blocks[i]->setIndexInHistory(i); } return result; } - bool addNewBlock = blocks.isEmpty() || (blocks.back()->items.size() >= MessagesPerPage); + auto addNewBlock = blocks.isEmpty() || (blocks.back()->items.size() >= kNewBlockEachMessage); if (!addNewBlock) { return blocks.back(); } @@ -1251,13 +1253,13 @@ HistoryBlock *History::prepareBlockForAddingItem() { result->setIndexInHistory(blocks.size()); blocks.push_back(result); - result->items.reserve(MessagesPerPage); + result->items.reserve(kNewBlockEachMessage); return result; }; void History::addItemToBlock(HistoryItem *item) { - t_assert(item != nullptr); - t_assert(item->detached()); + Expects(item != nullptr); + Expects(item->detached()); auto block = prepareBlockForAddingItem(); @@ -1311,7 +1313,7 @@ void History::addOlderSlice(const QVector &slice) { // lastParticipants are displayed in Profile as members list. markupSenders = &peer->asChannel()->mgInfo->markupSenders; } - for (int32 i = block->items.size(); i > 0; --i) { + for (auto i = block->items.size(); i > 0; --i) { auto item = block->items[i - 1]; mask |= item->addToOverview(AddToOverviewFront); if (item->from()->id) { @@ -1593,14 +1595,14 @@ void History::getNextShowFrom(HistoryBlock *block, int i) { auto l = block->items.size(); for (++i; i < l; ++i) { if (block->items[i]->id > 0) { - showFrom = block->items.at(i); + showFrom = block->items[i]; return; } } } for (auto j = block->indexInHistory() + 1, s = blocks.size(); j < s; ++j) { - block = blocks.at(j); + block = blocks[j]; for_const (auto item, block->items) { if (item->id > 0) { showFrom = item; @@ -1614,7 +1616,7 @@ void History::getNextShowFrom(HistoryBlock *block, int i) { void History::countScrollState(int top) { countScrollTopItem(top); if (scrollTopItem) { - scrollTopOffset = (top - scrollTopItem->block()->y - scrollTopItem->y); + scrollTopOffset = (top - scrollTopItem->block()->y() - scrollTopItem->y()); } } @@ -1628,22 +1630,22 @@ void History::countScrollTopItem(int top) { if (scrollTopItem && !scrollTopItem->detached()) { itemIndex = scrollTopItem->indexInBlock(); blockIndex = scrollTopItem->block()->indexInHistory(); - itemTop = blocks.at(blockIndex)->y + scrollTopItem->y; + itemTop = blocks[blockIndex]->y() + scrollTopItem->y(); } if (itemTop > top) { // go backward through history while we don't find an item that starts above do { - HistoryBlock *block = blocks.at(blockIndex); + auto block = blocks[blockIndex]; for (--itemIndex; itemIndex >= 0; --itemIndex) { - HistoryItem *item = block->items.at(itemIndex); - itemTop = block->y + item->y; + auto item = block->items[itemIndex]; + itemTop = block->y() + item->y(); if (itemTop <= top) { scrollTopItem = item; return; } } if (--blockIndex >= 0) { - itemIndex = blocks.at(blockIndex)->items.size(); + itemIndex = blocks[blockIndex]->items.size(); } else { break; } @@ -1653,16 +1655,16 @@ void History::countScrollTopItem(int top) { } else { // go forward through history while we don't find the last item that starts above for (int blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) { - HistoryBlock *block = blocks.at(blockIndex); + auto block = blocks[blockIndex]; for (int itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) { - HistoryItem *item = block->items.at(itemIndex); - itemTop = block->y + item->y; + auto item = block->items[itemIndex]; + itemTop = block->y() + item->y(); if (itemTop > top) { t_assert(itemIndex > 0 || blockIndex > 0); if (itemIndex > 0) { - scrollTopItem = block->items.at(itemIndex - 1); + scrollTopItem = block->items[itemIndex - 1]; } else { - scrollTopItem = blocks.at(blockIndex - 1)->items.back(); + scrollTopItem = blocks[blockIndex - 1]->items.back(); } return; } @@ -1676,12 +1678,12 @@ void History::countScrollTopItem(int top) { void History::getNextScrollTopItem(HistoryBlock *block, int32 i) { ++i; if (i > 0 && i < block->items.size()) { - scrollTopItem = block->items.at(i); + scrollTopItem = block->items[i]; return; } int j = block->indexInHistory() + 1; if (j > 0 && j < blocks.size()) { - scrollTopItem = blocks.at(j)->items.front(); + scrollTopItem = blocks[j]->items.front(); return; } scrollTopItem = nullptr; @@ -1707,12 +1709,12 @@ void History::destroyUnreadBar() { } HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex) { - t_assert(blockIndex >= 0); - t_assert(blockIndex < blocks.size()); - t_assert(itemIndex >= 0); - t_assert(itemIndex <= blocks[blockIndex]->items.size()); + Expects(blockIndex >= 0); + Expects(blockIndex < blocks.size()); + Expects(itemIndex >= 0); + Expects(itemIndex <= blocks[blockIndex]->items.size()); - auto block = blocks.at(blockIndex); + auto block = blocks[blockIndex]; newItem->attachToBlock(block, itemIndex); block->items.insert(itemIndex, newItem); @@ -1747,7 +1749,7 @@ HistoryBlock *History::finishBuildingFrontBlock() { if (block) { if (blocks.size() > 1) { auto last = block->items.back(); // ... item, item, item, last ], [ first, item, item ... - auto first = blocks.at(1)->items.front(); + auto first = blocks[1]->items.front(); // we've added a new front block, so previous item for // the old first item of a first block was changed @@ -1942,8 +1944,8 @@ int History::resizeGetHeight(int newWidth) { width = newWidth; int y = 0; - for_const (HistoryBlock *block, blocks) { - block->y = y; + for_const (auto block, blocks) { + block->setY(y); y += block->resizeGetHeight(newWidth, resizeAllItems); } height = y; @@ -2179,11 +2181,11 @@ void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages } void History::changeMsgId(MsgId oldId, MsgId newId) { - for (int32 i = 0; i < OverviewCount; ++i) { + for (auto i = 0; i < OverviewCount; ++i) { auto j = overviewIds[i].find(oldId); if (j != overviewIds[i].cend()) { overviewIds[i].erase(j); - int32 index = overview[i].indexOf(oldId); + auto index = overview[i].indexOf(oldId); if (overviewIds[i].constFind(newId) == overviewIds[i].cend()) { overviewIds[i].insert(newId); if (index >= 0) { @@ -2199,7 +2201,7 @@ void History::changeMsgId(MsgId oldId, MsgId newId) { } void History::removeBlock(HistoryBlock *block) { - t_assert(block->items.isEmpty()); + Expects(block->items.isEmpty()); if (_buildingFrontBlock && block == _buildingFrontBlock->block) { _buildingFrontBlock->block = nullptr; @@ -2209,9 +2211,9 @@ void History::removeBlock(HistoryBlock *block) { blocks.removeAt(index); if (index < blocks.size()) { for (int i = index, l = blocks.size(); i < l; ++i) { - blocks.at(i)->setIndexInHistory(i); + blocks[i]->setIndexInHistory(i); } - blocks.at(index)->items.front()->previousItemChanged(); + blocks[index]->items.front()->previousItemChanged(); } else if (!blocks.empty() && !blocks.back()->items.empty()) { blocks.back()->items.back()->nextItemChanged(); } @@ -2222,65 +2224,64 @@ History::~History() { } int HistoryBlock::resizeGetHeight(int newWidth, bool resizeAllItems) { - int y = 0; - for_const (HistoryItem *item, items) { - item->y = y; + auto y = 0; + for_const (auto item, items) { + item->setY(y); if (resizeAllItems || item->pendingResize()) { y += item->resizeGetHeight(newWidth); } else { y += item->height(); } } - height = y; - return height; + _height = y; + return _height; } void HistoryBlock::clear(bool leaveItems) { - Items lst; - std::swap(lst, items); + auto itemsList = base::take(items); if (leaveItems) { - for_const (HistoryItem *item, lst) { + for_const (auto item, itemsList) { item->detachFast(); } } else { - for_const (HistoryItem *item, lst) { + for_const (auto item, itemsList) { delete item; } } } void HistoryBlock::removeItem(HistoryItem *item) { - t_assert(item->block() == this); + Expects(item->block() == this); - int blockIndex = indexInHistory(); - int itemIndex = item->indexInBlock(); - if (history->showFrom == item) { - history->getNextShowFrom(this, itemIndex); + auto blockIndex = indexInHistory(); + auto itemIndex = item->indexInBlock(); + if (_history->showFrom == item) { + _history->getNextShowFrom(this, itemIndex); } - if (history->lastSentMsg == item) { - history->lastSentMsg = nullptr; + if (_history->lastSentMsg == item) { + _history->lastSentMsg = nullptr; } - if (history->unreadBar == item) { - history->unreadBar = nullptr; + if (_history->unreadBar == item) { + _history->unreadBar = nullptr; } - if (history->scrollTopItem == item) { - history->getNextScrollTopItem(this, itemIndex); + if (_history->scrollTopItem == item) { + _history->getNextScrollTopItem(this, itemIndex); } item->detachFast(); items.remove(itemIndex); - for (int i = itemIndex, l = items.size(); i < l; ++i) { - items.at(i)->setIndexInBlock(i); + for (auto i = itemIndex, l = items.size(); i < l; ++i) { + items[i]->setIndexInBlock(i); } if (items.isEmpty()) { - history->removeBlock(this); + _history->removeBlock(this); } else if (itemIndex < items.size()) { - items.at(itemIndex)->previousItemChanged(); - } else if (blockIndex + 1 < history->blocks.size()) { - history->blocks.at(blockIndex + 1)->items.front()->previousItemChanged(); - } else if (!history->blocks.empty() && !history->blocks.back()->items.empty()) { - history->blocks.back()->items.back()->nextItemChanged(); + items[itemIndex]->previousItemChanged(); + } else if (blockIndex + 1 < _history->blocks.size()) { + _history->blocks[blockIndex + 1]->items.front()->previousItemChanged(); + } else if (!_history->blocks.empty() && !_history->blocks.back()->items.empty()) { + _history->blocks.back()->items.back()->nextItemChanged(); } if (items.isEmpty()) { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index e811668d10..78972e02b9 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -622,14 +622,13 @@ private: class HistoryBlock { public: - HistoryBlock(History *hist) : history(hist), _indexInHistory(-1) { + HistoryBlock(gsl::not_null history) : _history(history) { } HistoryBlock(const HistoryBlock &) = delete; HistoryBlock &operator=(const HistoryBlock &) = delete; - typedef QVector Items; - Items items; + QVector items; void clear(bool leaveItems = false); ~HistoryBlock() { @@ -638,31 +637,45 @@ public: void removeItem(HistoryItem *item); int resizeGetHeight(int newWidth, bool resizeAllItems); - int y = 0; - int height = 0; - History *history; + int y() const { + return _y; + } + void setY(int y) { + _y = y; + } + int height() const { + return _height; + } + gsl::not_null history() const { + return _history; + } HistoryBlock *previousBlock() const { - t_assert(_indexInHistory >= 0); + Expects(_indexInHistory >= 0); - return (_indexInHistory > 0) ? history->blocks.at(_indexInHistory - 1) : nullptr; + return (_indexInHistory > 0) ? _history->blocks.at(_indexInHistory - 1) : nullptr; } HistoryBlock *nextBlock() const { - t_assert(_indexInHistory >= 0); + Expects(_indexInHistory >= 0); - return (_indexInHistory + 1 < history->blocks.size()) ? history->blocks.at(_indexInHistory + 1) : nullptr; + return (_indexInHistory + 1 < _history->blocks.size()) ? _history->blocks.at(_indexInHistory + 1) : nullptr; } void setIndexInHistory(int index) { _indexInHistory = index; } int indexInHistory() const { - t_assert(_indexInHistory >= 0); - t_assert(history->blocks.at(_indexInHistory) == this); + Expects(_indexInHistory >= 0); + Expects(_indexInHistory < _history->blocks.size()); + Expects(_history->blocks[_indexInHistory] == this); return _indexInHistory; } protected: - int _indexInHistory; + const gsl::not_null _history; + + int _y = 0; + int _height = 0; + int _indexInHistory = -1; }; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 02260313dc..82a313761b 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -152,7 +152,7 @@ int binarySearchBlocksOrItems(const T &list, int edge) { auto start = 0, end = static_cast(list.size()); while (end - start > 1) { auto middle = (start + end) / 2; - auto top = list[middle]->y; + auto top = list[middle]->y(); auto chooseLeft = (TopToBottom ? (top <= edge) : (top < edge)); if (chooseLeft) { start = middle; @@ -182,14 +182,14 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met // binary search for itemIndex of the first item that is not completely below the visible area auto block = history->blocks.at(blockIndex); - auto blocktop = historytop + block->y; - auto blockbottom = blocktop + block->height; + auto blocktop = historytop + block->y(); + auto blockbottom = blocktop + block->height(); auto itemIndex = binarySearchBlocksOrItems(block->items, searchEdge - blocktop); while (true) { while (true) { auto item = block->items.at(itemIndex); - auto itemtop = blocktop + item->y; + auto itemtop = blocktop + item->y(); auto itembottom = itemtop + item->height(); // binary search should've skipped all the items that are above / below the visible area @@ -205,7 +205,7 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met debugValue("blockIndex", blockIndex); debugValue("history->blocks.size()", history->blocks.size()); debugValue("blocktop", blocktop); - debugValue("block->height", block->height); + debugValue("block->height", block->height()); debugValue("itemIndex", itemIndex); debugValue("block->items.size()", block->items.size()); debugValue("itemtop", itemtop); @@ -214,10 +214,10 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met debugValue("_visibleAreaTop", _visibleAreaTop); debugValue("_visibleAreaBottom", _visibleAreaBottom); for (int i = 0; i != qMin(history->blocks.size(), 5); ++i) { - debugValue("y[" + QString::number(i) + "]", history->blocks[i]->y); - debugValue("h[" + QString::number(i) + "]", history->blocks[i]->height); + debugValue("y[" + QString::number(i) + "]", history->blocks[i]->y()); + debugValue("h[" + QString::number(i) + "]", history->blocks[i]->height()); for (int j = 0; j != qMin(history->blocks[i]->items.size(), 5); ++j) { - debugValue("y[" + QString::number(i) + "][" + QString::number(j) + "]", history->blocks[i]->items[j]->y); + debugValue("y[" + QString::number(i) + "][" + QString::number(j) + "]", history->blocks[i]->items[j]->y()); debugValue("h[" + QString::number(i) + "][" + QString::number(j) + "]", history->blocks[i]->items[j]->height()); } } @@ -225,8 +225,8 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met auto y = 0; for (int i = 0; i != history->blocks.size(); ++i) { auto innery = 0; - if (history->blocks[i]->y != y) { - debugInfo.append("bad_block_y" + QString::number(i) + ":" + QString::number(history->blocks[i]->y) + "!=" + QString::number(y)); + if (history->blocks[i]->y() != y) { + debugInfo.append("bad_block_y" + QString::number(i) + ":" + QString::number(history->blocks[i]->y()) + "!=" + QString::number(y)); return false; } for (int j = 0; j != history->blocks[i]->items.size(); ++j) { @@ -235,14 +235,14 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met } else if (history->blocks[i]->items[j]->pendingResize()) { debugInfo.append("pending_resize" + QString::number(i) + "," + QString::number(j)); } - if (history->blocks[i]->items[j]->y != innery) { - debugInfo.append("bad_item_y" + QString::number(i) + "," + QString::number(j) + ":" + QString::number(history->blocks[i]->items[j]->y) + "!=" + QString::number(innery)); + if (history->blocks[i]->items[j]->y() != innery) { + debugInfo.append("bad_item_y" + QString::number(i) + "," + QString::number(j) + ":" + QString::number(history->blocks[i]->items[j]->y()) + "!=" + QString::number(innery)); return false; } innery += history->blocks[i]->items[j]->height(); } - if (history->blocks[i]->height != innery) { - debugInfo.append("bad_block_height" + QString::number(i) + ":" + QString::number(history->blocks[i]->height) + "!=" + QString::number(innery)); + if (history->blocks[i]->height() != innery) { + debugInfo.append("bad_block_height" + QString::number(i) + ":" + QString::number(history->blocks[i]->height()) + "!=" + QString::number(innery)); return false; } y += innery; @@ -305,9 +305,9 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met return; } } - block = history->blocks.at(blockIndex); - blocktop = historytop + block->y; - blockbottom = blocktop + block->height; + block = history->blocks[blockIndex]; + blocktop = historytop + block->y(); + blockbottom = blocktop + block->height(); if (TopToBottom) { itemIndex = 0; } else { @@ -472,14 +472,16 @@ void HistoryInner::paintEvent(QPaintEvent *e) { seltoy += _dragSelTo->height(); } - int32 mtop = migratedTop(), htop = historyTop(), hdrawtop = historyDrawTop(); + auto mtop = migratedTop(); + auto htop = historyTop(); + auto hdrawtop = historyDrawTop(); if (mtop >= 0) { - int32 iBlock = (_curHistory == _migrated ? _curBlock : (_migrated->blocks.size() - 1)); - HistoryBlock *block = _migrated->blocks[iBlock]; - int32 iItem = (_curHistory == _migrated ? _curItem : (block->items.size() - 1)); - HistoryItem *item = block->items[iItem]; + auto iBlock = (_curHistory == _migrated ? _curBlock : (_migrated->blocks.size() - 1)); + auto block = _migrated->blocks[iBlock]; + auto iItem = (_curHistory == _migrated ? _curItem : (block->items.size() - 1)); + auto item = block->items[iItem]; - int32 y = mtop + block->y + item->y; + auto y = mtop + block->y() + item->y(); p.save(); p.translate(0, y); if (r.y() < y + item->height()) while (y < drawToY) { @@ -518,17 +520,17 @@ void HistoryInner::paintEvent(QPaintEvent *e) { p.restore(); } if (htop >= 0) { - int32 iBlock = (_curHistory == _history ? _curBlock : 0); - HistoryBlock *block = _history->blocks[iBlock]; - int32 iItem = (_curHistory == _history ? _curItem : 0); - HistoryItem *item = block->items[iItem]; + auto iBlock = (_curHistory == _history ? _curBlock : 0); + auto block = _history->blocks[iBlock]; + auto iItem = (_curHistory == _history ? _curItem : 0); + auto item = block->items[iItem]; - QRect historyRect = r.intersected(QRect(0, hdrawtop, width(), r.top() + r.height())); - int32 y = htop + block->y + item->y; + auto historyRect = r.intersected(QRect(0, hdrawtop, width(), r.top() + r.height())); + auto y = htop + block->y() + item->y(); p.save(); p.translate(0, y); while (y < drawToY) { - int32 h = item->height(); + auto h = item->height(); if (historyRect.y() < y + h && hdrawtop < y + h) { TextSelection sel; if (y >= selfromy && y < seltoy) { @@ -1902,23 +1904,23 @@ void HistoryInner::adjustCurrent(int32 y, History *history) const { _curBlock = history->blocks.size() - 1; _curItem = 0; } - while (history->blocks.at(_curBlock)->y > y && _curBlock > 0) { + while (history->blocks[_curBlock]->y() > y && _curBlock > 0) { --_curBlock; _curItem = 0; } - while (history->blocks.at(_curBlock)->y + history->blocks.at(_curBlock)->height <= y && _curBlock + 1 < history->blocks.size()) { + while (history->blocks[_curBlock]->y() + history->blocks[_curBlock]->height() <= y && _curBlock + 1 < history->blocks.size()) { ++_curBlock; _curItem = 0; } - HistoryBlock *block = history->blocks.at(_curBlock); + auto block = history->blocks[_curBlock]; if (_curItem >= block->items.size()) { _curItem = block->items.size() - 1; } - int by = block->y; - while (block->items.at(_curItem)->y + by > y && _curItem > 0) { + auto by = block->y(); + while (block->items[_curItem]->y() + by > y && _curItem > 0) { --_curItem; } - while (block->items.at(_curItem)->y + block->items.at(_curItem)->height() + by <= y && _curItem + 1 < block->items.size()) { + while (block->items[_curItem]->y() + block->items[_curItem]->height() + by <= y && _curItem + 1 < block->items.size()) { ++_curItem; } } @@ -2300,14 +2302,15 @@ int HistoryInner::historyHeight() const { } int HistoryInner::historyScrollTop() const { - int htop = historyTop(), mtop = migratedTop(); + auto htop = historyTop(); + auto mtop = migratedTop(); if (htop >= 0 && _history->scrollTopItem) { t_assert(!_history->scrollTopItem->detached()); - return htop + _history->scrollTopItem->block()->y + _history->scrollTopItem->y + _history->scrollTopOffset; + return htop + _history->scrollTopItem->block()->y() + _history->scrollTopItem->y() + _history->scrollTopOffset; } if (mtop >= 0 && _migrated->scrollTopItem) { t_assert(!_migrated->scrollTopItem->detached()); - return mtop + _migrated->scrollTopItem->block()->y + _migrated->scrollTopItem->y + _migrated->scrollTopOffset; + return mtop + _migrated->scrollTopItem->block()->y() + _migrated->scrollTopItem->y() + _migrated->scrollTopOffset; } return ScrollMax; } @@ -2331,7 +2334,7 @@ int HistoryInner::itemTop(const HistoryItem *item) const { // -1 if should not b if (item->detached()) return -1; int top = (item->history() == _history) ? historyTop() : (item->history() == _migrated ? migratedTop() : -2); - return (top < 0) ? top : (top + item->y + item->block()->y); + return (top < 0) ? top : (top + item->y() + item->block()->y()); } void HistoryInner::notifyIsBotChanged() { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 966f653aab..1dd5b283d6 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -578,7 +578,6 @@ TextSelection shiftSelection(TextSelection selection, const Text &byText) { } // namespace internal HistoryItem::HistoryItem(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime msgDate, int32 from) : HistoryElement() -, y(0) , id(msgId) , date(msgDate) , _from(from ? App::user(from) : history->peer) diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 743e787f06..937faf0c19 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -156,8 +156,8 @@ struct HistoryMessageReply : public RuntimeComponent { } ~HistoryMessageReply() { // clearData() should be called by holder - t_assert(replyToMsg == nullptr); - t_assert(_replyToVia == nullptr); + Expects(replyToMsg == nullptr); + Expects(_replyToVia == nullptr); } bool updateData(HistoryMessage *holder, bool force = false); @@ -438,7 +438,7 @@ public: return get(); } HistoryMedia &operator*() const { - t_assert(!isNull()); + Expects(!isNull()); return *get(); } explicit operator bool() const { @@ -522,10 +522,10 @@ public: return !_block; } void attachToBlock(HistoryBlock *block, int index) { - t_assert(_block == nullptr); - t_assert(_indexInBlock < 0); - t_assert(block != nullptr); - t_assert(index >= 0); + Expects(_block == nullptr); + Expects(_indexInBlock < 0); + Expects(block != nullptr); + Expects(index >= 0); _block = block; _indexInBlock = index; @@ -534,8 +534,8 @@ public: } } void setIndexInBlock(int index) { - t_assert(_block != nullptr); - t_assert(index >= 0); + Expects(_block != nullptr); + Expects(index >= 0); _indexInBlock = index; } @@ -575,7 +575,7 @@ public: return (_flags & MTPDmessage::Flag::f_reply_markup); } MTPDreplyKeyboardMarkup::Flags replyKeyboardFlags() const { - t_assert(definesReplyKeyboard()); + Expects(definesReplyKeyboard()); if (auto markup = Get()) { return markup->flags; } @@ -701,7 +701,12 @@ public: } QString directLink() const; - int32 y; + int y() const { + return _y; + } + void setY(int y) { + _y = y; + } MsgId id; QDateTime date; @@ -951,6 +956,9 @@ protected: HistoryMediaPtr _media; +private: + int _y = 0; + }; // make all the constructors in HistoryItem children protected diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 0521e5f175..cfd318200e 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -75,6 +75,9 @@ namespace { constexpr auto kStickersUpdateTimeout = 3600000; // update not more than once in an hour constexpr auto kSaveTabbedSelectorSectionTimeout = 1000; +constexpr auto kMessagesPerPageFirst = 30; +constexpr auto kMessagesPerPage = 50; +constexpr auto kPreloadHeightsCount = 3; // when 3 screens to scroll left make a preload request ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() { return [](ChannelData *channel, MsgId msgId) { @@ -2255,7 +2258,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId if (MTP::isDefaultHandledError(error)) return false; if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { - PeerData *was = _peer; + auto was = _peer; App::main()->showBackFromStack(); Ui::show(Box(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); return true; @@ -2437,8 +2440,10 @@ bool HistoryWidget::historyHasNotFreezedUnreadBar(History *history) const { void HistoryWidget::firstLoadMessages() { if (!_history || _firstLoadRequest) return; - PeerData *from = _peer; - int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage; + auto from = _peer; + auto offset_id = 0; + auto offset = 0; + auto loadCount = kMessagesPerPage; if (_showAtMsgId == ShowAtUnreadMsgId) { if (_migrated && _migrated->unreadCount()) { _history->getReadyFor(_showAtMsgId); @@ -2454,7 +2459,7 @@ void HistoryWidget::firstLoadMessages() { } } else if (_showAtMsgId == ShowAtTheEndMsgId) { _history->getReadyFor(_showAtMsgId); - loadCount = MessagesFirstLoad; + loadCount = kMessagesPerPageFirst; } else if (_showAtMsgId > 0) { _history->getReadyFor(_showAtMsgId); offset = -loadCount / 2; @@ -2486,8 +2491,9 @@ void HistoryWidget::loadMessages() { return; } - MsgId offset_id = from->minMsgId(); - int32 offset = 0, loadCount = offset_id ? MessagesPerPage : MessagesFirstLoad; + auto offset_id = from->minMsgId(); + auto offset = 0; + auto loadCount = offset_id ? kMessagesPerPage : kMessagesPerPageFirst; _preloadRequest = MTP::send(MTPmessages_GetHistory(from->peer->input, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed)); } @@ -2505,9 +2511,9 @@ void HistoryWidget::loadMessagesDown() { return; } - int32 loadCount = MessagesPerPage, offset = -loadCount; - - MsgId offset_id = from->maxMsgId(); + auto loadCount = kMessagesPerPage; + auto offset = -loadCount; + auto offset_id = from->maxMsgId(); if (!offset_id) { if (loadMigrated || !_migrated) return; ++offset_id; @@ -2523,8 +2529,10 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) { clearDelayedShowAt(); _delayedShowAtMsgId = showAtMsgId; - PeerData *from = _peer; - int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage; + auto from = _peer; + auto offset_id = 0; + auto offset = 0; + auto loadCount = kMessagesPerPage; if (_delayedShowAtMsgId == ShowAtUnreadMsgId) { if (_migrated && _migrated->unreadCount()) { from = _migrated->peer; @@ -2534,10 +2542,10 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) { offset = -loadCount / 2; offset_id = _history->inboxReadBefore; } else { - loadCount = MessagesFirstLoad; + loadCount = kMessagesPerPageFirst; } } else if (_delayedShowAtMsgId == ShowAtTheEndMsgId) { - loadCount = MessagesFirstLoad; + loadCount = kMessagesPerPageFirst; } else if (_delayedShowAtMsgId > 0) { offset = -loadCount / 2; offset_id = _delayedShowAtMsgId; @@ -2578,11 +2586,11 @@ void HistoryWidget::preloadHistoryIfNeeded() { updateHistoryDownVisibility(); int st = _scroll->scrollTop(), stm = _scroll->scrollTopMax(), sh = _scroll->height(); - if (st + PreloadHeightsCount * sh > stm) { + if (st + kPreloadHeightsCount * sh >= stm) { loadMessagesDown(); } - if (st < PreloadHeightsCount * sh) { + if (st <= kPreloadHeightsCount * sh) { loadMessages(); }