mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-20 15:17:41 +00:00
Improve history items management.
Encapsulate HistoryBlock::y and HistoryBlock::height.
This commit is contained in:
parent
3f2bed8a92
commit
d581e00299
@ -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
|
||||
|
@ -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<MTPMessage> &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()) {
|
||||
|
@ -622,14 +622,13 @@ private:
|
||||
|
||||
class HistoryBlock {
|
||||
public:
|
||||
HistoryBlock(History *hist) : history(hist), _indexInHistory(-1) {
|
||||
HistoryBlock(gsl::not_null<History*> history) : _history(history) {
|
||||
}
|
||||
|
||||
HistoryBlock(const HistoryBlock &) = delete;
|
||||
HistoryBlock &operator=(const HistoryBlock &) = delete;
|
||||
|
||||
typedef QVector<HistoryItem*> Items;
|
||||
Items items;
|
||||
QVector<HistoryItem*> 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*> 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*> _history;
|
||||
|
||||
int _y = 0;
|
||||
int _height = 0;
|
||||
int _indexInHistory = -1;
|
||||
|
||||
};
|
||||
|
@ -152,7 +152,7 @@ int binarySearchBlocksOrItems(const T &list, int edge) {
|
||||
auto start = 0, end = static_cast<int>(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<TopToBottom>(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() {
|
||||
|
@ -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)
|
||||
|
@ -156,8 +156,8 @@ struct HistoryMessageReply : public RuntimeComponent<HistoryMessageReply> {
|
||||
}
|
||||
~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<HistoryMessageReplyMarkup>()) {
|
||||
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
|
||||
|
@ -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<InformBox>(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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user