From 2cbda4e1e574ca2a4219613540e86a83080444e4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 19 Mar 2016 21:32:17 +0300 Subject: [PATCH] removed history resize when adding items, simplified adding items, maintaining item and block indices, history scroll management broken when history changes --- Telegram/SourceFiles/history.cpp | 443 ++++++++++++------------------- Telegram/SourceFiles/history.h | 19 +- 2 files changed, 177 insertions(+), 285 deletions(-) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 356719060..85188c283 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -599,25 +599,24 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { return _joinedMessage; } - UserData *inviter = (peer->asChannel()->inviter > 0) ? App::userLoaded(peer->asChannel()->inviter) : 0; - if (!inviter) return 0; + UserData *inviter = (peer->asChannel()->inviter > 0) ? App::userLoaded(peer->asChannel()->inviter) : nullptr; + if (!inviter) return nullptr; - if (peerToUser(inviter->id) == MTP::authedId()) unread = false; MTPDmessage::Flags flags = 0; - if (unread) { + if (peerToUser(inviter->id) == MTP::authedId()) { + unread = false; + } else if (unread) { flags |= MTPDmessage::Flag::f_unread; } + QDateTime inviteDate = peer->asChannel()->inviteDate; if (unread) _maxReadMessageDate = inviteDate; if (isEmpty()) { - HistoryBlock *to = new HistoryBlock(this); - bool newBlock = true; _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); - if (!addNewItem(to, newBlock, _joinedMessage, unread)) { - _joinedMessage = 0; - } + addNewItem(_joinedMessage, unread); return _joinedMessage; } + for (int32 blockIndex = blocks.size(); blockIndex > 1;) { HistoryBlock *block = blocks.at(--blockIndex); for (int32 itemIndex = block->items.size(); itemIndex > 0;) { @@ -627,13 +626,13 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { if (item->date <= inviteDate) { if (peer->isMegagroup() && peer->migrateFrom() && item->isGroupMigrate()) { peer->asChannel()->mgInfo->joinedMessageFound = true; - return 0; + return nullptr; } ++itemIndex; _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); if (!addNewInTheMiddle(_joinedMessage, blockIndex, itemIndex)) { - _joinedMessage = 0; + _joinedMessage = nullptr; } if (lastMsgDate.isNull() || inviteDate >= lastMsgDate) { setLastMessage(_joinedMessage); @@ -648,38 +647,19 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } // adding new item to new block - int32 addToH = 0, skip = 0; - HistoryItem *till = blocks.isEmpty() ? 0 : blocks.front()->items.front(); - HistoryBlock *block = new HistoryBlock(this); + block->setIndexInHistory(0); + blocks.push_front(block); + for (int i = 1, l = blocks.size(); i < l; ++i) { + blocks.at(i)->setIndexInHistory(i); + } _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); - addItemAfterPrevToBlock(_joinedMessage, 0, block); - if (!block->items.isEmpty()) { - blocks.push_front(block); - if (width) { - addToH += block->height; - ++skip; - } - } else { - delete block; - } - if (width && addToH) { - for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) { - if (skip) { - --skip; - } else { - (*i)->y += addToH; - } - } - height += addToH; - } - if (!lastMsgDate.isNull() && inviteDate >= lastMsgDate) { - setLastMessage(_joinedMessage); - if (unread) { - newItemAdded(_joinedMessage); - } - } + addItemAfterPrevToBlock(_joinedMessage, nullptr, block); + + t_assert(blocks.size() > 1); + blocks.at(1)->items.front()->previousItemChanged(); + return _joinedMessage; } @@ -799,23 +779,7 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp clear(true); } - HistoryBlock *to = nullptr; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); - } - HistoryItem *item = createItem((type == NewMessageLast) ? nullptr : to, msg, (type == NewMessageUnread)); - if (type == NewMessageLast && item) { - if (!item->detached()) { - t_assert(!newBlock); - return item; - } - } - return addNewItem(to, newBlock, item, (type == NewMessageUnread)); + return addNewToLastBlock(msg, type); } void ChannelHistory::addNewToOther(HistoryItem *item, NewMessageType type) { @@ -866,16 +830,16 @@ void ChannelHistory::switchMode() { HistoryItem *prev = 0; for (int32 i = 0; i < count;) { HistoryBlock *block = new HistoryBlock(this); + block->setIndexInHistory(blocks.size()); + blocks.push_back(block); + int32 willAddToBlock = qMin(int32(MessagesPerPage), count - i); block->items.reserve(willAddToBlock); for (int32 till = i + willAddToBlock; i < till; ++i) { prev = addItemAfterPrevToBlock(_otherList.at(i), prev, block); } - blocks.push_back(block); - if (width) { - block->y = height; - height += block->height; - } + + t_assert(!block->items.isEmpty()); } } @@ -1244,7 +1208,7 @@ HistoryItem *Histories::addNewMessage(const MTPMessage &msg, NewMessageType type return findOrInsert(peer, 0, 0)->addNewMessage(msg, type); } -HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction) { +HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem) { MsgId msgId = 0; switch (msg.type()) { case mtpc_messageEmpty: msgId = msg.c_messageEmpty().vid.v; break; @@ -1255,10 +1219,8 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo HistoryItem *result = App::histItemById(channelId(), msgId); if (result) { - if (block) { - if (!result->detached()) { - result->detach(); - } + if (!result->detached() && detachExistingItem) { + result->detach(); } if (msg.type() == mtpc_message) { result->updateMedia(msg.c_message().has_media() ? (&msg.c_message().vmedia) : 0); @@ -1505,18 +1467,7 @@ HistoryItem *History::createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 } HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString &text, MTPDmessage::Flags flags, HistoryMedia *media, bool newMsg) { - HistoryBlock *to = 0; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); - } - - HistoryItem *result = HistoryServiceMsg::create(this, msgId, date, text, flags, media); - return addNewItem(to, newBlock, result, newMsg); + return addNewItem(HistoryServiceMsg::create(this, msgId, date, text, flags, media), newMsg); } HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type) { @@ -1534,66 +1485,32 @@ HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type) return item; } - HistoryBlock *to = nullptr; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); + return addNewToLastBlock(msg, type); +} + +HistoryItem *History::addNewToLastBlock(const MTPMessage &msg, NewMessageType type) { + bool applyServiceAction = (type == NewMessageUnread), detachExistingItem = (type != NewMessageLast); + HistoryItem *item = createItem(msg, applyServiceAction, detachExistingItem); + if (!item || !item->detached()) { + return item; } - HistoryItem *item = createItem((type == NewMessageLast) ? nullptr : to, msg, (type == NewMessageUnread)); - if (type == NewMessageLast && item) { - if (!item->detached()) { - t_assert(!newBlock); - return item; - } - } - return addNewItem(to, newBlock, item, (type == NewMessageUnread)); + return addNewItem(item, (type == NewMessageUnread)); } HistoryItem *History::addToHistory(const MTPMessage &msg) { - return createItem(nullptr, msg, false); + return createItem(msg, false, false); } HistoryItem *History::addNewForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *item) { - HistoryBlock *to = nullptr; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); - } - return addNewItem(to, newBlock, createItemForwarded(id, flags, date, from, item), true); + return addNewItem(createItemForwarded(id, flags, date, from, item), true); } HistoryItem *History::addNewDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { - HistoryBlock *to = 0; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); - } - return addNewItem(to, newBlock, createItemDocument(id, flags, viaBotId, replyTo, date, from, doc, caption), true); + return addNewItem(createItemDocument(id, flags, viaBotId, replyTo, date, from, doc, caption), true); } HistoryItem *History::addNewPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { - HistoryBlock *to = 0; - bool newBlock = blocks.isEmpty(); - if (newBlock) { - to = new HistoryBlock(this); - } else { - to = blocks.back(); - t_assert(!to->items.isEmpty()); - t_assert(to->items.back() != nullptr); - } - return addNewItem(to, newBlock, createItemPhoto(id, flags, viaBotId, replyTo, date, from, photo, caption), true); + return addNewItem(createItemPhoto(id, flags, viaBotId, replyTo, date, from, photo, caption), true); } bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMethod method) { @@ -1639,27 +1556,21 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) { if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type); } -HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *adding, bool newMsg) { - if (!adding) { - if (newBlock) delete to; - return adding; - } +HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) { + t_assert(adding != nullptr); + t_assert(adding->detached()); - if (newBlock) { - to->y = height; - blocks.push_back(to); + if (blocks.isEmpty()) { + blocks.push_back(new HistoryBlock(this)); + blocks.back()->setIndexInHistory(blocks.size()); } - adding->attachToBlock(to, to->items.size()); - to->items.push_back(adding); + HistoryBlock *block = blocks.back(); + + adding->attachToBlock(block, block->items.size()); + block->items.push_back(adding); adding->previousItemChanged(); setLastMessage(adding); - adding->y = to->height; - if (width) { - int32 dh = adding->resize(width); - to->height += dh; - height += dh; - } if (newMsg) { newItemAdded(adding); } @@ -1775,10 +1686,6 @@ HistoryItem *History::addItemAfterPrevToBlock(HistoryItem *item, HistoryItem *pr item->attachToBlock(block, block->items.size()); block->items.push_back(item); item->previousItemChanged(); - if (width) { - item->y = block->height; - block->height += item->resize(width); - } return item; } @@ -1824,10 +1731,16 @@ void History::addOlderSlice(const QVector &slice, const QVectorsetIndexInHistory(0); + blocks.push_front(block); + for (int i = 1, l = blocks.size(); i < l; ++i) { + blocks.at(i)->setIndexInHistory(i); + } + block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0)); for (auto i = slice.cend(), e = slice.cbegin(); i != e;) { --i; - HistoryItem *adding = createItem(block, *i, false); + HistoryItem *adding = createItem(*i, false, true); if (!adding) continue; for (; groupsIt != groupsEnd; ++groupsIt) { @@ -1847,112 +1760,99 @@ void History::addOlderSlice(const QVector &slice, const QVectoritems.front(); - while (oldFirst && last && oldFirst->type() == HistoryItemGroup && last->type() == HistoryItemGroup) { - static_cast(last)->uniteWith(static_cast(oldFirst)); - oldFirst->destroy(); - if (blocks.isEmpty()) { - oldFirst = 0; - } else { - t_assert(blocks.size() > 1); - oldFirst = blocks.at(1)->items.front(); - } - } if (block->items.isEmpty()) { - oldLoaded = true; + blocks.pop_front(); delete block; - } else { - if (oldFirst) { - blocks.push_front(block); - if (width) { - block->y = 0; - for (int32 i = 1, l = blocks.size(); i < l; ++i) { - blocks.at(i)->y += block->height; - } - height += block->height; - } - } else { - blocks.push_front(block); - if (width) { - height = block->height; - } - } + block = nullptr; - if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants - bool channel = isChannel(); - int32 mask = 0; - QList *lastAuthors = 0; - OrderedSet *markupSenders = 0; - if (peer->isChat()) { - lastAuthors = &peer->asChat()->lastAuthors; - markupSenders = &peer->asChat()->markupSenders; - } else if (peer->isMegagroup()) { - lastAuthors = &peer->asChannel()->mgInfo->lastParticipants; - markupSenders = &peer->asChannel()->mgInfo->markupSenders; - } - for (int32 i = block->items.size(); i > 0; --i) { - HistoryItem *item = block->items[i - 1]; - mask |= item->addToOverview(AddToOverviewFront); - if (item->from()->id) { - if (lastAuthors) { // chats - if (item->from()->isUser()) { - if (!lastAuthors->contains(item->from()->asUser())) { - lastAuthors->push_back(item->from()->asUser()); - if (peer->isMegagroup()) { - peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated; - } + oldLoaded = true; + } else if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants + bool channel = isChannel(); + int32 mask = 0; + QList *lastAuthors = 0; + OrderedSet *markupSenders = 0; + if (peer->isChat()) { + lastAuthors = &peer->asChat()->lastAuthors; + markupSenders = &peer->asChat()->markupSenders; + } else if (peer->isMegagroup()) { + lastAuthors = &peer->asChannel()->mgInfo->lastParticipants; + markupSenders = &peer->asChannel()->mgInfo->markupSenders; + } + for (int32 i = block->items.size(); i > 0; --i) { + HistoryItem *item = block->items[i - 1]; + mask |= item->addToOverview(AddToOverviewFront); + if (item->from()->id) { + if (lastAuthors) { // chats + if (item->from()->isUser()) { + if (!lastAuthors->contains(item->from()->asUser())) { + lastAuthors->push_back(item->from()->asUser()); + if (peer->isMegagroup()) { + peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated; } } } } - if (item->author()->id) { - if (markupSenders) { // chats with bots - if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { - MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; - if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { - bool wasKeyboardHide = markupSenders->contains(item->author()); - if (!wasKeyboardHide) { - markupSenders->insert(item->author()); - } - if (!(markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_zero)) { - if (!lastKeyboardInited) { - bool botNotInChat = false; - if (peer->isChat()) { - botNotInChat = (!peer->canWrite() || !peer->asChat()->participants.isEmpty()) && item->author()->isUser() && !peer->asChat()->participants.contains(item->author()->asUser()); - } else if (peer->isMegagroup()) { - botNotInChat = (!peer->canWrite() || peer->asChannel()->mgInfo->botStatus != 0) && item->author()->isUser() && !peer->asChannel()->mgInfo->bots.contains(item->author()->asUser()); - } - if (wasKeyboardHide || botNotInChat) { - clearLastKeyboard(); - } else { - lastKeyboardInited = true; - lastKeyboardId = item->id; - lastKeyboardFrom = item->author()->id; - lastKeyboardUsed = false; - } + } + if (item->author()->id) { + if (markupSenders) { // chats with bots + if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { + MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; + if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { + bool wasKeyboardHide = markupSenders->contains(item->author()); + if (!wasKeyboardHide) { + markupSenders->insert(item->author()); + } + if (!(markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_zero)) { + if (!lastKeyboardInited) { + bool botNotInChat = false; + if (peer->isChat()) { + botNotInChat = (!peer->canWrite() || !peer->asChat()->participants.isEmpty()) && item->author()->isUser() && !peer->asChat()->participants.contains(item->author()->asUser()); + } else if (peer->isMegagroup()) { + botNotInChat = (!peer->canWrite() || peer->asChannel()->mgInfo->botStatus != 0) && item->author()->isUser() && !peer->asChannel()->mgInfo->bots.contains(item->author()->asUser()); + } + if (wasKeyboardHide || botNotInChat) { + clearLastKeyboard(); + } else { + lastKeyboardInited = true; + lastKeyboardId = item->id; + lastKeyboardFrom = item->author()->id; + lastKeyboardUsed = false; } } } } - } else if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { // conversations with bots - MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; - if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { - if (markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_zero) { - clearLastKeyboard(); - } else { - lastKeyboardInited = true; - lastKeyboardId = item->id; - lastKeyboardFrom = item->author()->id; - lastKeyboardUsed = false; - } + } + } else if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { // conversations with bots + MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; + if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { + if (markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_zero) { + clearLastKeyboard(); + } else { + lastKeyboardInited = true; + lastKeyboardId = item->id; + lastKeyboardFrom = item->author()->id; + lastKeyboardUsed = false; } } } } - for (int32 t = 0; t < OverviewCount; ++t) { - if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t)); - } } + for (int32 t = 0; t < OverviewCount; ++t) { + if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t)); + } + } + + // we've added a new front block, now we check if both + // last message of the first block and first message of + // the last block are groups, if they are - unite them + HistoryItem *first = (block && blocks.size() > 1) ? blocks.at(1)->items.front() : nullptr; + if (first && last && first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) { + static_cast(first)->uniteWith(static_cast(last)); + last->destroy(); + + // last->destroy() could've destroyed this new block + // so we can't rely on this pointer any more + block = nullptr; } if (isChannel()) { @@ -1976,10 +1876,13 @@ void History::addNewerSlice(const QVector &slice, const QVectoritems.back(); HistoryBlock *block = new HistoryBlock(this); + block->setIndexInHistory(blocks.size()); + blocks.push_back(block); + block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0)); for (auto i = slice.cend(), e = slice.cbegin(); i != e;) { --i; - HistoryItem *adding = createItem(block, *i, false); + HistoryItem *adding = createItem(*i, false, true); if (!adding) continue; for (; groupsIt != groupsEnd; ++groupsIt) { @@ -2002,13 +1905,10 @@ void History::addNewerSlice(const QVector &slice, const QVectoritems.isEmpty()) { newLoaded = true; setLastMessage(lastImportantMessage()); + + blocks.pop_back(); delete block; - } else { - blocks.push_back(block); - if (width) { - block->y = height; - height += block->height; - } + block = nullptr; } } @@ -2621,29 +2521,16 @@ void History::changeMsgId(MsgId oldId, MsgId newId) { } } -void History::blockResized(HistoryBlock *block, int32 dh) { - int32 i = blocks.indexOf(block), l = blocks.size(); - if (i >= 0) { - for (++i; i < l; ++i) { - blocks[i]->y -= dh; - } - height -= dh; - } -} - void History::removeBlock(HistoryBlock *block) { - int32 i = blocks.indexOf(block), h = block->height; - if (i >= 0) { - blocks.removeAt(i); - int32 l = blocks.size(); - if (i > 0 && l == 1) { // only fake block with date left - removeBlock(blocks[0]); - height = 0; - } else if (h) { - for (; i < l; ++i) { - blocks[i]->y -= h; - } - height -= h; + int index = blocks.indexOf(block); + if (index >= 0) { + setPendingResize(); + blocks.removeAt(index); + for (int i = index, l = blocks.size(); i < l; ++i) { + blocks.at(i)->setIndexInHistory(i); + } + if (index < blocks.size()) { + blocks.at(index)->items.front()->previousItemChanged(); } } delete block; @@ -2691,14 +2578,14 @@ void HistoryBlock::clear(bool leaveItems) { } void HistoryBlock::removeItem(HistoryItem *item) { - int32 i = items.indexOf(item), dh = 0; + int32 index = items.indexOf(item), dh = 0; if (history->showFrom == item) { - history->getNextShowFrom(this, i); + history->getNextShowFrom(this, index); } if (history->unreadBar == item) { history->unreadBar = nullptr; } - if (i < 0) { + if (index < 0) { return; } @@ -2708,7 +2595,7 @@ void HistoryBlock::removeItem(HistoryItem *item) { HistoryGroup *nextGroup = 0, *prevGroup = 0; HistoryCollapse *nextCollapse = 0; HistoryItem *prevItem = 0; - for (int32 nextBlock = myIndex, nextIndex = qMin(items.size(), i + 1); nextBlock < history->blocks.size(); ++nextBlock) { + for (int32 nextBlock = myIndex, nextIndex = qMin(items.size(), index + 1); nextBlock < history->blocks.size(); ++nextBlock) { HistoryBlock *block = history->blocks.at(nextBlock); for (; nextIndex < block->items.size(); ++nextIndex) { HistoryItem *item = block->items.at(nextIndex); @@ -2728,7 +2615,7 @@ void HistoryBlock::removeItem(HistoryItem *item) { break; } } - for (int32 prevBlock = myIndex + 1, prevIndex = qMax(1, i); prevBlock > 0;) { + for (int32 prevBlock = myIndex + 1, prevIndex = qMax(1, index); prevBlock > 0;) { --prevBlock; HistoryBlock *block = history->blocks.at(prevBlock); if (!prevIndex) prevIndex = block->items.size(); @@ -2760,19 +2647,21 @@ void HistoryBlock::removeItem(HistoryItem *item) { // myIndex can be invalid now, because of destroying previous blocks dh = item->height(); - items.remove(i); + items.remove(index); if ((!item->out() || item->isPost()) && item->unread() && history->unreadCount) { history->setUnreadCount(history->unreadCount - 1); } History *h = history; - if (int32 l = items.size()) { - for (; i < l; ++i) { - items.at(i)->y -= dh; + if (int l = items.size()) { + for (int i = index; i < l; ++i) { items.at(i)->setIndexInBlock(i); } - height -= dh; - history->blockResized(this, dh); + if (index < items.size()) { + items.at(index)->previousItemChanged(); + } else if (_indexInHistory + 1 < history->blocks.size()) { + history->blocks.at(_indexInHistory + 1)->items.front()->previousItemChanged(); + } } else { history->removeBlock(this); } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 379752697..da98d2955 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -236,16 +236,10 @@ public: return blocks.isEmpty(); } void clear(bool leaveItems = false); - void blockResized(HistoryBlock *block, int32 dh); void removeBlock(HistoryBlock *block); virtual ~History(); - HistoryItem *createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction); - HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg); - HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); - HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); - HistoryItem *addNewService(MsgId msgId, QDateTime date, const QString &text, MTPDmessage::Flags flags = 0, HistoryMedia *media = 0, bool newMsg = true); HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type); HistoryItem *addToHistory(const MTPMessage &msg); @@ -439,6 +433,7 @@ public: protected: void clearOnDestroy(); + HistoryItem *addNewToLastBlock(const MTPMessage &msg, NewMessageType type); private: @@ -467,9 +462,14 @@ private: friend class HistoryBlock; friend class ChannelHistory; + HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem); + HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg); + HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); + HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); + HistoryItem *addItemAfterPrevToBlock(HistoryItem *item, HistoryItem *prev, HistoryBlock *block); HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex); - HistoryItem *addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *adding, bool newMsg); + HistoryItem *addNewItem(HistoryItem *adding, bool newMsg); HistoryItem *addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block); HistoryItem *addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem *prev); @@ -851,6 +851,9 @@ public: HistoryBlock *previous() const { return (_indexInHistory > 0) ? history->blocks.at(_indexInHistory - 1) : nullptr; } + void setIndexInHistory(int index) { + _indexInHistory = index; + } protected: @@ -1346,7 +1349,7 @@ protected: return nullptr; } - // this should be used only in initDimensions() + // this should be used only in previousItemChanged() // to add required bits to the Interfaces mask // after that always use Is() bool displayDate() const {