optimized enumeration of userpics

This commit is contained in:
John Preston 2016-03-23 14:47:32 +03:00
parent e45de88bd6
commit 02ca81ac64
6 changed files with 76 additions and 34 deletions

View File

@ -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<HistoryServicePinned>()->msgId = msg.vreply_to_msg_id.v;

View File

@ -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<HistoryBlock*> 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;
};

View File

@ -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 <typename T>
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 <typename Method>
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;
}
}
}

View File

@ -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();

View File

@ -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) {

View File

@ -89,6 +89,7 @@
<ImageHasSafeExceptionHandlers />
<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
<CustomBuildStep>
</CustomBuildStep>