diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index fe436909e..6e9458d94 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -293,8 +293,8 @@ History::History(const PeerId &peerId) : width(0), height(0) if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) { outboxReadBefore = INT_MAX; } - for (int32 i = 0; i < OverviewCount; ++i) { - overviewCountData[i] = -1; // not loaded yet + for (auto &countData : overviewCountData) { + countData = -1; // not loaded yet } } @@ -309,6 +309,15 @@ void History::clearLastKeyboard() { lastKeyboardFrom = 0; } +bool History::canHaveFromPhotos() const { + if (peer->isUser() && !Adaptive::Wide()) { + return false; + } else if (isChannel() && asChannelHistory()->onlyImportant()) { + return false; + } + return true; +} + void History::setHasPendingResizedItems() { _flags |= Flag::f_has_pending_resized_items; Global::RefHandleHistoryUpdate().call(); @@ -6030,8 +6039,7 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const { } HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg) : - HistoryItem(history, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) -, _text(st::msgMinWidth) { + HistoryItem(history, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) { PeerId authorOriginalId = 0, fromOriginalId = 0; MsgId originalId = 0; if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) { @@ -7540,9 +7548,7 @@ bool HistoryServiceMessage::updatePinnedText(const QString *pfrom, QString *ptex } HistoryServiceMessage::HistoryServiceMessage(History *history, const MTPDmessageService &msg) : - HistoryItem(history, msg.vid.v, mtpCastFlags(msg.vflags.v), ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) -, _text(st::msgMinWidth) -, _media(0) { + HistoryItem(history, msg.vid.v, mtpCastFlags(msg.vflags.v), ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) { if (msg.has_reply_to_msg_id()) { UpdateInterfaces(HistoryServicePinned::Bit()); MsgId pinnedMsgId = Get()->msgId = msg.vreply_to_msg_id.v; diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 5520aeccd..c10ed01fd 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -346,6 +346,10 @@ public: bool updateTyping(uint64 ms, bool force = false); void clearLastKeyboard(); + // optimization for userpics displayed on the left + // if this returns false there is no need to even try to handle them + bool canHaveFromPhotos() const; + typedef QList Blocks; Blocks blocks; @@ -2717,8 +2721,8 @@ protected: bool updatePinned(bool force = false); bool updatePinnedText(const QString *pfrom = nullptr, QString *ptext = nullptr); - Text _text; - HistoryMedia *_media; + Text _text = { int(st::msgMinWidth) }; + HistoryMedia *_media = nullptr; int32 _textWidth, _textHeight; }; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 61a2557c0..8ff4d8d75 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -94,32 +94,53 @@ void HistoryInner::repaintItem(const HistoryItem *item) { } } +namespace { + // helper binary search for an item in a list that is not completely below the given bottom of the visible area + // is applied once for blocks list in a history and once for items list in the found block + template + int binarySearchBlocksOrItems(const T &list, int bottom) { + int start = 0, end = list.size(); + while (end - start > 1) { + int middle = (start + end) / 2; + if (list.at(middle)->y >= bottom) { + end = middle; + } else { + start = middle; + } + } + return start; + } +} + template void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method method) { // no displayed messages in this history - if (htop < 0) return; + if (htop < 0 || h->isEmpty() || !h->canHaveFromPhotos() || _visibleAreaBottom <= htop) { + return; + } // find and remember the bottom of an attached messages pack // -1 means we didn't find an attached to previous message yet int lowestAttachedItemBottom = -1; - int blockIndex = h->blocks.size(); - int itemIndex = 0; - while (blockIndex > 0) { - HistoryBlock *block = h->blocks.at(--blockIndex); - itemIndex = block->items.size(); + // binary search for blockIndex of the first block that is not completely below the visible area + int blockIndex = binarySearchBlocksOrItems(h->blocks, _visibleAreaBottom - htop); - int blocktop = htop + block->y; - while (itemIndex > 0) { - HistoryItem *item = block->items.at(--itemIndex); + // binary search for itemIndex of the first item that is not completely below the visible area + HistoryBlock *block = h->blocks.at(blockIndex); + int blocktop = htop + block->y; + int itemIndex = binarySearchBlocksOrItems(block->items, _visibleAreaBottom - blocktop); + + while (true) { + while (itemIndex >= 0) { + HistoryItem *item = block->items.at(itemIndex--); int itemtop = blocktop + item->y; int itembottom = itemtop + item->height(); - // skip items that are below the visible area - if (itemtop >= _visibleAreaBottom) { - continue; - } + // binary search should've skipped all the items that are below the visible area + t_assert(itemtop < _visibleAreaBottom); + // skip all service messages if (HistoryMessage *message = item->toHistoryMessage()) { if (lowestAttachedItemBottom < 0 && message->isAttachedToPrevious()) { lowestAttachedItemBottom = itembottom - message->marginBottom(); @@ -131,15 +152,21 @@ void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method metho if (lowestAttachedItemBottom < 0) { lowestAttachedItemBottom = itembottom - message->marginBottom(); } - int userpicTop = qMin(qMax(itemtop + message->marginTop(), _visibleAreaTop + st::msgMargin.left()), lowestAttachedItemBottom - int(st::msgPhotoSize)); + // attach userpic to the top of the visible area with the same margin as it is from the left side + int userpicTop = qMax(itemtop + message->marginTop(), _visibleAreaTop + st::msgMargin.left()); + + // do not let the userpic go below the attached messages pack bottom line + userpicTop = qMin(userpicTop, lowestAttachedItemBottom - int(st::msgPhotoSize)); // call the template callback function that was passed // and return if it finished everything it needed if (!method(message, userpicTop)) { return; } + } - // forget the found bottom of the pack, search for the next one from scratch + // forget the found bottom of the pack, search for the next one from scratch + if (!message->isAttachedToPrevious()) { lowestAttachedItemBottom = -1; } } @@ -154,6 +181,14 @@ void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method metho if (blocktop <= _visibleAreaTop) { return; } + + if (--blockIndex < 0) { + return; + } else { + block = h->blocks.at(blockIndex); + blocktop = htop + block->y; + itemIndex = block->items.size() - 1; + } } } diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index ab7c34696..87998c2fc 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -1066,12 +1066,7 @@ namespace { } } -LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(OverviewItemInfo::Bit(), parent) -, _titlew(0) -, _page(0) -, _pixw(0) -, _pixh(0) -, _text(st::msgMinWidth) { +LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(OverviewItemInfo::Bit(), parent) { QString text = _parent->originalText(); EntitiesInText entities = _parent->originalEntities(); diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 9cd624127..d52d1e3eb 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -440,10 +440,11 @@ private: TextLinkPtr _photol; QString _title, _letter; - int32 _titlew; - WebPageData *_page; - int32 _pixw, _pixh; - Text _text; + int _titlew = 0; + WebPageData *_page = nullptr; + int _pixw = 0; + int _pixh = 0; + Text _text = { int(st::msgMinWidth) }; struct Link { Link() : width(0) { diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index df873ef61..529a6b36a 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -89,6 +89,7 @@ LIBCMT $(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib + /ignore:4099 %(AdditionalOptions)