2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-09-01 15:15:13 +00:00

Start HistoryView::Message class for item view.

This commit is contained in:
John Preston
2018-01-10 16:13:33 +03:00
parent 794e31505b
commit 8060cb7426
22 changed files with 696 additions and 514 deletions

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "history/history.h"
#include "history/view/history_view_message.h"
#include "history/history_message.h"
#include "history/history_media_types.h"
#include "history/history_service.h"
@@ -141,7 +142,11 @@ void History::setCloudDraft(std::unique_ptr<Data::Draft> &&draft) {
Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) {
if (Data::draftIsNull(fromDraft)) {
setCloudDraft(std::make_unique<Data::Draft>(TextWithTags(), 0, MessageCursor(), false));
setCloudDraft(std::make_unique<Data::Draft>(
TextWithTags(),
0,
MessageCursor(),
false));
cloudDraft()->date = QDateTime();
} else {
auto existing = cloudDraft();
@@ -369,11 +374,11 @@ void ChannelHistory::getRangeDifference() {
auto fromId = MsgId(0);
auto toId = MsgId(0);
for (auto blockIndex = 0, blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) {
auto block = blocks[blockIndex];
for (auto itemIndex = 0, itemsCount = int(block->items.size()); itemIndex < itemsCount; ++itemIndex) {
auto item = block->items[itemIndex];
if (item->id > 0) {
fromId = item->id;
const auto &block = blocks[blockIndex];
for (auto itemIndex = 0, itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) {
const auto &message = block->messages[itemIndex];
if (message->id() > 0) {
fromId = message->id();
break;
}
}
@@ -382,11 +387,11 @@ void ChannelHistory::getRangeDifference() {
if (!fromId) return;
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->id > 0) {
toId = item->id;
const auto &block = blocks[--blockIndex];
for (auto itemIndex = block->messages.size(); itemIndex > 0;) {
const auto &message = block->messages[--itemIndex];
if (message->id() > 0) {
toId = message->id();
break;
}
}
@@ -438,9 +443,9 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
}
for (auto blockIndex = blocks.size(); blockIndex > 0;) {
auto block = blocks[--blockIndex];
for (auto itemIndex = block->items.size(); itemIndex > 0;) {
auto item = block->items[--itemIndex];
const auto &block = blocks[--blockIndex];
for (auto itemIndex = block->messages.size(); itemIndex > 0;) {
const auto item = block->messages[--itemIndex]->data();
// Due to a server bug sometimes inviteDate is less (before) than the
// first message in the megagroup (message about migration), let us
@@ -497,8 +502,8 @@ void ChannelHistory::checkJoinedMessage(bool createUnread) {
QDateTime inviteDate = peer->asChannel()->inviteDate;
QDateTime firstDate, lastDate;
if (!blocks.empty()) {
firstDate = blocks.front()->items.front()->date;
lastDate = blocks.back()->items.back()->date;
firstDate = blocks.front()->messages.front()->data()->date;
lastDate = blocks.back()->messages.back()->data()->date;
}
if (!firstDate.isNull() && !lastDate.isNull() && (firstDate <= inviteDate || loadedAtTop()) && (lastDate > inviteDate || loadedAtBottom())) {
bool willBeLastMsg = (inviteDate >= lastDate);
@@ -514,9 +519,9 @@ void ChannelHistory::checkMaxReadMessageDate() {
if (_maxReadMessageDate.isValid()) return;
for (auto blockIndex = blocks.size(); blockIndex > 0;) {
auto block = blocks[--blockIndex];
for (auto itemIndex = block->items.size(); itemIndex > 0;) {
auto item = block->items[--itemIndex];
const auto &block = blocks[--blockIndex];
for (auto itemIndex = block->messages.size(); itemIndex > 0;) {
const auto item = block->messages[--itemIndex]->data();
if (!item->unread()) {
_maxReadMessageDate = item->date;
if (item->isGroupMigrate() && isMegagroup() && peer->migrateFrom()) {
@@ -1339,29 +1344,26 @@ HistoryBlock *History::prepareBlockForAddingItem() {
return _buildingFrontBlock->block;
}
auto result = _buildingFrontBlock->block = new HistoryBlock(this);
if (_buildingFrontBlock->expectedItemsCount > 0) {
result->items.reserve(_buildingFrontBlock->expectedItemsCount + 1);
}
result->setIndexInHistory(0);
blocks.push_front(result);
for (int i = 1, l = blocks.size(); i < l; ++i) {
blocks.push_front(std::make_unique<HistoryBlock>(this));
for (auto i = 0, l = int(blocks.size()); i != l; ++i) {
blocks[i]->setIndexInHistory(i);
}
return result;
_buildingFrontBlock->block = blocks.front().get();
if (_buildingFrontBlock->expectedItemsCount > 0) {
_buildingFrontBlock->block->messages.reserve(
_buildingFrontBlock->expectedItemsCount + 1);
}
return _buildingFrontBlock->block;
}
auto addNewBlock = blocks.empty() || (blocks.back()->items.size() >= kNewBlockEachMessage);
if (!addNewBlock) {
return blocks.back();
const auto addNewBlock = blocks.empty()
|| (blocks.back()->messages.size() >= kNewBlockEachMessage);
if (addNewBlock) {
blocks.push_back(std::make_unique<HistoryBlock>(this));
blocks.back()->setIndexInHistory(blocks.size() - 1);
blocks.back()->messages.reserve(kNewBlockEachMessage);
}
auto result = new HistoryBlock(this);
result->setIndexInHistory(blocks.size());
blocks.push_back(result);
result->items.reserve(kNewBlockEachMessage);
return result;
return blocks.back().get();
};
void History::addItemToBlock(not_null<HistoryItem*> item) {
@@ -1369,8 +1371,10 @@ void History::addItemToBlock(not_null<HistoryItem*> item) {
auto block = prepareBlockForAddingItem();
item->attachToBlock(block, block->items.size());
block->items.push_back(item);
block->messages.push_back(std::make_unique<HistoryView::Message>(
item,
HistoryView::Context::History));
item->attachToBlock(block, block->messages.size() - 1);
item->previousItemChanged();
if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) {
@@ -1379,62 +1383,11 @@ void History::addItemToBlock(not_null<HistoryItem*> item) {
}
template <int kSharedMediaTypeCount>
void History::addToSharedMedia(std::vector<MsgId> (&medias)[kSharedMediaTypeCount], bool force) {
void History::addToSharedMedia(
std::vector<MsgId> (&medias)[kSharedMediaTypeCount],
bool force) {
auto from = loadedAtTop() ? 0 : minMsgId();
auto till = loadedAtBottom() ? ServerMaxMsgId : maxMsgId();
if (from > till) {
// History is desync, nothing good can be added.
//// Logging
auto value = QStringList();
for (auto block : blocks) {
auto indices = QStringList();
auto &items = block->items;
auto count = int(items.size());
auto logItem = [&](auto &&item) {
indices.push_back(QString::number(item->id));
};
if (count < 4) {
for (auto item : items) {
logItem(item);
}
} else {
auto last = 0;
auto logLast = [&] {
logItem(items[last]);
};
auto logTill = [&](int till) {
if (last < till - 1) {
indices.push_back("...["
+ QString::number(till - 1 - last)
+ "]...");
}
last = till;
logLast();
};
auto badPair = [&](int index) {
auto prev = items[index - 1]->id;
auto next = items[index]->id;
return IsServerMsgId(prev)
&& IsServerMsgId(next)
&& (next < prev);
};
logLast();
for (auto i = 1; i != count - 1; ++i) {
if (badPair(i) || badPair(i + 1)) {
logTill(i);
}
}
logTill(count - 1);
}
value.push_back(indices.join(","));
}
CrashReports::SetAnnotation("full", value.join(";"));
Assert(!"History desync caught!");
//// Logging
return;
}
for (auto i = 0; i != Storage::kSharedMediaTypeCount; ++i) {
if (force || !medias[i].empty()) {
auto type = static_cast<Storage::SharedMediaType>(i);
@@ -1507,8 +1460,8 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice) {
// lastParticipants are displayed in Profile as members list.
markupSenders = &peer->asChannel()->mgInfo->markupSenders;
}
for (auto i = block->items.size(); i > 0; --i) {
auto item = block->items[i - 1];
for (auto i = block->messages.size(); i > 0; --i) {
const auto item = block->messages[i - 1]->data();
item->addToUnreadMentions(UnreadMentionType::Existing);
if (item->from()->id) {
if (lastAuthors) { // chats
@@ -1678,8 +1631,9 @@ void History::checkAddAllToUnreadMentions() {
return;
}
for (const auto block : blocks) {
for (const auto item : block->items) {
for (const auto &block : blocks) {
for (const auto &message : block->messages) {
const auto item = message->data();
item->addToUnreadMentions(UnreadMentionType::Existing);
}
}
@@ -1688,13 +1642,14 @@ void History::checkAddAllToUnreadMentions() {
void History::addBlockToSharedMedia(HistoryBlock *block) {
std::vector<MsgId> medias[Storage::kSharedMediaTypeCount];
if (block) {
for (auto item : block->items) {
for (const auto &message : block->messages) {
const auto item = message->data();
if (auto types = item->sharedMediaTypes()) {
for (auto i = 0; i != Storage::kSharedMediaTypeCount; ++i) {
auto type = static_cast<Storage::SharedMediaType>(i);
if (types.test(type)) {
if (medias[i].empty()) {
medias[i].reserve(block->items.size());
medias[i].reserve(block->messages.size());
}
medias[i].push_back(item->id);
}
@@ -1709,11 +1664,13 @@ int History::countUnread(MsgId upTo) {
int result = 0;
for (auto i = blocks.cend(), e = blocks.cbegin(); i != e;) {
--i;
for (auto j = (*i)->items.cend(), en = (*i)->items.cbegin(); j != en;) {
const auto &messages = (*i)->messages;
for (auto j = messages.cend(), en = messages.cbegin(); j != en;) {
--j;
if ((*j)->id > 0 && (*j)->id <= upTo) {
const auto item = (*j)->data();
if (item->id > 0 && item->id <= upTo) {
break;
} else if (!(*j)->out() && (*j)->unread() && (*j)->id > upTo) {
} else if (!item->out() && item->unread() && item->id > upTo) {
++result;
}
}
@@ -1726,11 +1683,13 @@ void History::updateShowFrom() {
for (auto i = blocks.cend(); i != blocks.cbegin();) {
--i;
for (auto j = (*i)->items.cend(); j != (*i)->items.cbegin();) {
const auto &messages = (*i)->messages;
for (auto j = messages.cend(); j != messages.cbegin();) {
--j;
if ((*j)->id > 0 && (!(*j)->out() || !showFrom)) {
if ((*j)->id >= inboxReadBefore) {
showFrom = *j;
const auto item = (*j)->data();
if (item->id > 0 && (!item->out() || !showFrom)) {
if (item->id >= inboxReadBefore) {
showFrom = item;
} else {
return;
}
@@ -1779,7 +1738,7 @@ MsgId History::outboxRead(HistoryItem *wasRead) {
}
HistoryItem *History::lastAvailableMessage() const {
return isEmpty() ? nullptr : blocks.back()->items.back();
return isEmpty() ? nullptr : blocks.back()->messages.back()->data().get();
}
void History::setUnreadCount(int newUnreadCount) {
@@ -1839,21 +1798,28 @@ bool History::changeMute(bool newMute) {
}
void History::getNextShowFrom(HistoryBlock *block, int i) {
const auto setFromMessage = [&](const auto &message) {
const auto item = message->data();
if (item->id > 0) {
showFrom = item;
return true;
}
return false;
};
if (i >= 0) {
auto l = block->items.size();
auto l = block->messages.size();
for (++i; i < l; ++i) {
if (block->items[i]->id > 0) {
showFrom = block->items[i];
const auto &message = block->messages[i];
if (setFromMessage(block->messages[i])) {
return;
}
}
}
for (auto j = block->indexInHistory() + 1, s = int(blocks.size()); j < s; ++j) {
block = blocks[j];
for_const (auto item, block->items) {
if (item->id > 0) {
showFrom = item;
block = blocks[j].get();
for (const auto &message : block->messages) {
if (setFromMessage(message)) {
return;
}
}
@@ -1874,7 +1840,7 @@ QDateTime History::adjustChatListDate() const {
void History::countScrollState(int top) {
countScrollTopItem(top);
if (scrollTopItem) {
scrollTopOffset = (top - scrollTopItem->block()->y() - scrollTopItem->y());
scrollTopOffset = (top - scrollTopItem->data()->block()->y() - scrollTopItem->y());
}
}
@@ -1884,64 +1850,65 @@ void History::countScrollTopItem(int top) {
return;
}
int itemIndex = 0, blockIndex = 0, itemTop = 0;
if (scrollTopItem && !scrollTopItem->detached()) {
itemIndex = scrollTopItem->indexInBlock();
blockIndex = scrollTopItem->block()->indexInHistory();
auto itemIndex = 0;
auto blockIndex = 0;
auto itemTop = 0;
if (scrollTopItem) {
itemIndex = scrollTopItem->data()->indexInBlock();
blockIndex = scrollTopItem->data()->block()->indexInHistory();
itemTop = blocks[blockIndex]->y() + scrollTopItem->y();
}
if (itemTop > top) {
// go backward through history while we don't find an item that starts above
do {
auto block = blocks[blockIndex];
const auto &block = blocks[blockIndex];
for (--itemIndex; itemIndex >= 0; --itemIndex) {
auto item = block->items[itemIndex];
itemTop = block->y() + item->y();
const auto view = block->messages[itemIndex].get();
itemTop = block->y() + view->y();
if (itemTop <= top) {
scrollTopItem = item;
scrollTopItem = view;
return;
}
}
if (--blockIndex >= 0) {
itemIndex = blocks[blockIndex]->items.size();
itemIndex = blocks[blockIndex]->messages.size();
} else {
break;
}
} while (true);
scrollTopItem = blocks.front()->items.front();
scrollTopItem = blocks.front()->messages.front().get();
} else {
// go forward through history while we don't find the last item that starts above
for (int blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) {
auto block = blocks[blockIndex];
for (int itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) {
auto item = block->items[itemIndex];
itemTop = block->y() + item->y();
for (auto blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) {
const auto &block = blocks[blockIndex];
for (auto itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) {
itemTop = block->y() + block->messages[itemIndex]->y();
if (itemTop > top) {
Assert(itemIndex > 0 || blockIndex > 0);
if (itemIndex > 0) {
scrollTopItem = block->items[itemIndex - 1];
scrollTopItem = block->messages[itemIndex - 1].get();
} else {
scrollTopItem = blocks[blockIndex - 1]->items.back();
scrollTopItem = blocks[blockIndex - 1]->messages.back().get();
}
return;
}
}
itemIndex = 0;
}
scrollTopItem = blocks.back()->items.back();
scrollTopItem = blocks.back()->messages.back().get();
}
}
void History::getNextScrollTopItem(HistoryBlock *block, int32 i) {
++i;
if (i > 0 && i < block->items.size()) {
scrollTopItem = block->items[i];
if (i > 0 && i < block->messages.size()) {
scrollTopItem = block->messages[i].get();
return;
}
int j = block->indexInHistory() + 1;
if (j > 0 && j < blocks.size()) {
scrollTopItem = blocks[j]->items.front();
scrollTopItem = blocks[j]->messages.front().get();
return;
}
scrollTopItem = nullptr;
@@ -1966,24 +1933,29 @@ void History::destroyUnreadBar() {
}
}
not_null<HistoryItem*> History::addNewInTheMiddle(not_null<HistoryItem*> newItem, int32 blockIndex, int32 itemIndex) {
not_null<HistoryItem*> History::addNewInTheMiddle(
not_null<HistoryItem*> newItem,
int blockIndex,
int itemIndex) {
Expects(blockIndex >= 0);
Expects(blockIndex < blocks.size());
Expects(itemIndex >= 0);
Expects(itemIndex <= blocks[blockIndex]->items.size());
Expects(itemIndex <= blocks[blockIndex]->messages.size());
auto block = blocks[blockIndex];
const auto &block = blocks[blockIndex];
newItem->attachToBlock(block, itemIndex);
block->items.insert(block->items.begin() + itemIndex, newItem);
block->messages.insert(
block->messages.begin() + itemIndex,
std::make_unique<HistoryView::Message>(newItem, HistoryView::Context::History));
newItem->attachToBlock(block.get(), itemIndex);
newItem->previousItemChanged();
if (itemIndex + 1 < block->items.size()) {
for (int i = itemIndex + 1, l = block->items.size(); i < l; ++i) {
block->items[i]->setIndexInBlock(i);
if (itemIndex + 1 < block->messages.size()) {
for (auto i = itemIndex + 1, l = int(block->messages.size()); i != l; ++i) {
block->messages[i]->data()->setIndexInBlock(i);
}
block->items[itemIndex + 1]->previousItemChanged();
} else if (blockIndex + 1 < blocks.size() && !blocks[blockIndex + 1]->items.empty()) {
blocks[blockIndex + 1]->items.front()->previousItemChanged();
block->messages[itemIndex + 1]->data()->previousItemChanged();
} else if (blockIndex + 1 < blocks.size() && !blocks[blockIndex + 1]->messages.empty()) {
blocks[blockIndex + 1]->messages.front()->data()->previousItemChanged();
} else {
newItem->nextItemChanged();
}
@@ -2001,10 +1973,10 @@ HistoryItem *History::findNextItem(not_null<HistoryItem*> item) const {
const auto nextBlockIndex = item->block()->indexInHistory() + 1;
const auto nextItemIndex = item->indexInBlock() + 1;
if (nextItemIndex < int(item->block()->items.size())) {
return item->block()->items[nextItemIndex];
if (nextItemIndex < int(item->block()->messages.size())) {
return item->block()->messages[nextItemIndex]->data();
} else if (nextBlockIndex < int(blocks.size())) {
return blocks[nextBlockIndex]->items.front();
return blocks[nextBlockIndex]->messages.front()->data();
}
return nullptr;
}
@@ -2015,9 +1987,9 @@ HistoryItem *History::findPreviousItem(not_null<HistoryItem*> item) const {
const auto blockIndex = item->block()->indexInHistory();
const auto itemIndex = item->indexInBlock();
if (itemIndex > 0) {
return item->block()->items[itemIndex - 1];
return item->block()->messages[itemIndex - 1]->data();
} else if (blockIndex > 0) {
return blocks[blockIndex - 1]->items.back();
return blocks[blockIndex - 1]->messages.back()->data();
}
return nullptr;
}
@@ -2162,14 +2134,14 @@ HistoryBlock *History::finishBuildingFrontBlock() {
auto block = _buildingFrontBlock->block;
if (block) {
if (blocks.size() > 1) {
auto last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
auto first = blocks[1]->items.front();
const auto last = block->messages.back()->data(); // ... item, item, item, last ], [ first, item, item ...
const auto first = blocks[1]->messages.front()->data();
// we've added a new front block, so previous item for
// the old first item of a first block was changed
first->previousItemChanged();
} else {
block->items.back()->nextItemChanged();
block->messages.back()->data()->nextItemChanged();
}
}
@@ -2288,8 +2260,9 @@ void History::fixLastMessage(bool wasAtBottom) {
}
MsgId History::minMsgId() const {
for (auto block : std::as_const(blocks)) {
for (auto item : std::as_const(block->items)) {
for (const auto &block : blocks) {
for (const auto &message : block->messages) {
const auto item = message->data();
if (IsServerMsgId(item->id)) {
return item->id;
}
@@ -2299,8 +2272,9 @@ MsgId History::minMsgId() const {
}
MsgId History::maxMsgId() const {
for (auto block : base::reversed(std::as_const(blocks))) {
for (auto item : base::reversed(std::as_const(block->items))) {
for (const auto &block : base::reversed(blocks)) {
for (const auto &message : base::reversed(block->messages)) {
const auto item = message->data();
if (IsServerMsgId(item->id)) {
return item->id;
}
@@ -2325,7 +2299,7 @@ int History::resizeGetHeight(int newWidth) {
width = newWidth;
int y = 0;
for_const (auto block, blocks) {
for (const auto &block : blocks) {
block->setY(y);
y += block->resizeGetHeight(newWidth, resizeAllItems);
}
@@ -2357,7 +2331,9 @@ History *History::migrateFrom() const {
}
bool History::isDisplayedEmpty() const {
return isEmpty() || ((blocks.size() == 1) && blocks.front()->items.size() == 1 && blocks.front()->items.front()->isEmpty());
return isEmpty() || ((blocks.size() == 1)
&& blocks.front()->messages.size() == 1
&& blocks.front()->messages.front()->data()->isEmpty());
}
bool History::hasOrphanMediaGroupPart() const {
@@ -2365,10 +2341,10 @@ bool History::hasOrphanMediaGroupPart() const {
return false;
} else if (blocks.size() != 1) {
return false;
} else if (blocks.front()->items.size() != 1) {
} else if (blocks.front()->messages.size() != 1) {
return false;
}
return blocks.front()->items.front()->groupId() != MessageGroupId();
return blocks.front()->messages.front()->data()->groupId() != MessageGroupId();
}
bool History::removeOrphanMediaGroupPart() {
@@ -2444,8 +2420,8 @@ void History::clearUpTill(MsgId availableMinId) {
return;
}
do {
auto item = blocks.front()->items.front();
auto itemId = item->id;
const auto item = blocks.front()->messages.front()->data();
const auto itemId = item->id;
if (IsServerMsgId(itemId) && itemId >= availableMinId) {
if (itemId == availableMinId) {
auto fromId = 0;
@@ -2472,21 +2448,19 @@ void History::clearUpTill(MsgId availableMinId) {
void History::applyGroupAdminChanges(
const base::flat_map<UserId, bool> &changes) {
for (auto block : blocks) {
for (auto item : block->items) {
item->applyGroupAdminChanges(changes);
for (const auto &block : blocks) {
for (const auto &message : block->messages) {
message->data()->applyGroupAdminChanges(changes);
}
}
}
void History::clearBlocks(bool leaveItems) {
Blocks lst;
std::swap(lst, blocks);
for_const (HistoryBlock *block, lst) {
const auto cleared = base::take(blocks);
for (const auto &block : cleared) {
if (leaveItems) {
block->clear(true);
}
delete block;
}
}
@@ -2518,7 +2492,7 @@ void History::changeMsgId(MsgId oldId, MsgId newId) {
}
void History::removeBlock(not_null<HistoryBlock*> block) {
Expects(block->items.empty());
Expects(block->messages.empty());
if (_buildingFrontBlock && block == _buildingFrontBlock->block) {
_buildingFrontBlock->block = nullptr;
@@ -2530,9 +2504,9 @@ void History::removeBlock(not_null<HistoryBlock*> block) {
for (int i = index, l = blocks.size(); i < l; ++i) {
blocks[i]->setIndexInHistory(i);
}
blocks[index]->items.front()->previousItemChanged();
} else if (!blocks.empty() && !blocks.back()->items.empty()) {
blocks.back()->items.back()->nextItemChanged();
blocks[index]->messages.front()->data()->previousItemChanged();
} else if (!blocks.empty() && !blocks.back()->messages.empty()) {
blocks.back()->messages.back()->data()->nextItemChanged();
}
}
@@ -2540,10 +2514,16 @@ History::~History() {
clearOnDestroy();
}
HistoryBlock::HistoryBlock(not_null<History*> history)
: _history(history) {
}
int HistoryBlock::resizeGetHeight(int newWidth, bool resizeAllItems) {
auto y = 0;
for_const (auto item, items) {
item->setY(y);
for (const auto &message : messages) {
message->setY(y);
const auto item = message->data();
if (resizeAllItems || item->pendingResize()) {
y += item->resizeGetHeight(newWidth);
} else {
@@ -2555,17 +2535,14 @@ int HistoryBlock::resizeGetHeight(int newWidth, bool resizeAllItems) {
}
void HistoryBlock::clear(bool leaveItems) {
auto itemsList = base::take(items);
const auto list = base::take(messages);
if (leaveItems) {
for_const (auto item, itemsList) {
item->detachFast();
}
} else {
for_const (auto item, itemsList) {
delete item;
for (const auto &message : list) {
message->data()->detachFast();
}
}
// #TODO feeds delete all items in history
}
void HistoryBlock::removeItem(not_null<HistoryItem*> item) {
@@ -2594,30 +2571,31 @@ void HistoryBlock::removeItem(not_null<HistoryItem*> item) {
if (_history->unreadBar == item) {
_history->unreadBar = nullptr;
}
if (_history->scrollTopItem == item) {
if (_history->scrollTopItem && _history->scrollTopItem->data() == item) {
_history->getNextScrollTopItem(this, itemIndex);
}
item->detachFast();
items.erase(items.begin() + itemIndex);
for (auto i = itemIndex, l = int(items.size()); i < l; ++i) {
items[i]->setIndexInBlock(i);
messages.erase(messages.begin() + itemIndex);
for (auto i = itemIndex, l = int(messages.size()); i < l; ++i) {
messages[i]->data()->setIndexInBlock(i);
}
if (items.empty()) {
if (messages.empty()) {
// Deletes this.
_history->removeBlock(this);
} else if (itemIndex < items.size()) {
items[itemIndex]->previousItemChanged();
} else if (itemIndex < messages.size()) {
messages[itemIndex]->data()->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.empty()) {
delete this;
_history->blocks[blockIndex + 1]->messages.front()->data()->previousItemChanged();
} else if (!_history->blocks.empty() && !_history->blocks.back()->messages.empty()) {
_history->blocks.back()->messages.back()->data()->nextItemChanged();
}
if (needGroupRecount) {
groupHistory->recountGrouping(groupFrom, groupTill);
}
}
HistoryBlock::~HistoryBlock() {
clear();
}