fixed history block index bug

This commit is contained in:
John Preston 2016-03-22 12:51:20 +03:00
parent fd7a30f143
commit f662067a68
4 changed files with 67 additions and 57 deletions

View File

@ -208,7 +208,7 @@ class AnimationCreator {
public:
AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {}
AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {}
AnimationImplementation *create() const { return exchange(_ptr); }
AnimationImplementation *create() const { return getPointerAndReset(_ptr); }
~AnimationCreator() { deleteAndMark(_ptr); }
private:
AnimationCreator &operator=(const AnimationCreator &other);

View File

@ -572,15 +572,9 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) {
if (onlyImportant()) {
if (newLoaded) {
HistoryBlock *block = blocks.isEmpty() ? nullptr : blocks.back();
HistoryItem *prev = nullptr;
if (block) {
prev = block->items.back();
} else {
block = new HistoryBlock(this);
block->setIndexInHistory(blocks.size());
blocks.push_back(block);
}
HistoryBlock *block = blocks.isEmpty() ? addNewLastBlock() : blocks.back();
HistoryItem *prev = block->items.isEmpty() ? nullptr : block->items.back();
prev = addMessageGroupAfterPrevToBlock(d, prev, block);
if (block->items.isEmpty()) {
blocks.pop_back();
@ -643,12 +637,7 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
}
// adding new item to new block
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);
}
HistoryBlock *block = addNewFirstBlock();
_joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags);
addItemAfterPrevToBlock(_joinedMessage, nullptr, block);
@ -827,9 +816,7 @@ 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);
HistoryBlock *block = addNewLastBlock();
int32 willAddToBlock = qMin(int32(MessagesPerPage), count - i);
block->items.reserve(willAddToBlock);
@ -1560,11 +1547,7 @@ HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
t_assert(adding != nullptr);
t_assert(adding->detached());
if (blocks.isEmpty()) {
blocks.push_back(new HistoryBlock(this));
blocks.back()->setIndexInHistory(blocks.size());
}
HistoryBlock *block = blocks.back();
HistoryBlock *block = blocks.isEmpty() ? addNewLastBlock() : blocks.back();
adding->attachToBlock(block, block->items.size());
block->items.push_back(adding);
@ -1726,13 +1709,8 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
HistoryItem *last = nullptr;
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);
}
HistoryItem *prev = nullptr;
HistoryBlock *block = addNewFirstBlock();
block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
@ -1745,16 +1723,16 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
if (group.vmin_id.v >= adding->id) break;
last = addMessageGroupAfterPrevToBlock(group, last, block);
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
}
last = addItemAfterPrevToBlock(adding, last, block);
prev = addItemAfterPrevToBlock(adding, prev, block);
}
for (; groupsIt != groupsEnd; ++groupsIt) {
if (groupsIt->type() != mtpc_messageGroup) continue;
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
last = addMessageGroupAfterPrevToBlock(group, last, block);
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
}
if (block->items.isEmpty()) {
@ -1839,17 +1817,26 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
}
}
// 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<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last));
last->destroy();
// some checks if there was some message history already
if (block && blocks.size() > 1) {
HistoryItem *last = block->items.back(); // .. item, item, item, last ], [ first, item, item ..
HistoryItem *first = blocks.at(1)->items.front();
// last->destroy() could've destroyed this new block
// so we can't rely on this pointer any more
block = nullptr;
// we've added a new front block, so previous item for
// the old first item of a first block was changed
first->previousItemChanged();
// we've added a new front block, now we check if both
// last message of the first block and first message of
// the second block are groups, if they are - unite them
if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) {
static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(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()) {
@ -1872,9 +1859,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
HistoryItem *prev = blocks.isEmpty() ? nullptr : blocks.back()->items.back();
HistoryBlock *block = new HistoryBlock(this);
block->setIndexInHistory(blocks.size());
blocks.push_back(block);
HistoryBlock *block = addNewLastBlock();
block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
@ -2205,6 +2190,23 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex,
return newItem;
}
HistoryBlock *History::addNewLastBlock() {
HistoryBlock *result = new HistoryBlock(this);
result->setIndexInHistory(blocks.size());
blocks.push_back(result);
return result;
}
HistoryBlock *History::addNewFirstBlock() {
HistoryBlock *result = new HistoryBlock(this);
result->setIndexInHistory(0);
blocks.push_front(result);
for (int i = 1, l = blocks.size(); i < l; ++i) {
blocks.at(i)->setIndexInHistory(i);
}
return result;
}
void History::clearNotifications() {
notifies.clear();
}
@ -6605,8 +6607,12 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle));
if (displayFromPhoto()) {
int32 photoleft = left + ((outbg && !Adaptive::Wide()) ? (width + (st::msgPhotoSkip - st::msgPhotoSize)) : (-st::msgPhotoSkip));
author()->paintUserpic(p, st::msgPhotoSize, photoleft, marginTop());
int photoleft = left + ((outbg && !Adaptive::Wide()) ? (width + (st::msgPhotoSkip - st::msgPhotoSize)) : (-st::msgPhotoSkip));
int phototop = marginTop();
// if (history()->scrollTopItem == this) {
// phototop = qMax(qMin(history()->scrollTopOffset, _height - marginBottom() - int(st::msgPhotoSize)), phototop);
// }
author()->paintUserpic(p, st::msgPhotoSize, photoleft, phototop);
}
if (bubble) {

View File

@ -220,6 +220,9 @@ class History {
public:
History(const PeerId &peerId);
History(const History &) = delete;
History &operator=(const History &) = delete;
ChannelId channelId() const {
return peerToChannel(peer->id);
}
@ -503,9 +506,10 @@ private:
HistoryItem *addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem *prev);
HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
History(const History &) = delete;
History &operator=(const History &) = delete;
};
HistoryBlock *addNewLastBlock();
HistoryBlock *addNewFirstBlock();
};
class HistoryGroup;
class HistoryCollapse;

View File

@ -27,8 +27,8 @@ void deleteAndMark(T *&link) {
}
template <typename T>
T *exchange(T *&ptr) {
T *result = 0;
T *getPointerAndReset(T *&ptr) {
T *result = nullptr;
qSwap(result, ptr);
return result;
}
@ -792,7 +792,7 @@ class FunctionCreator {
public:
FunctionCreator(FunctionImplementation<R> *ptr) : _ptr(ptr) {}
FunctionCreator(const FunctionCreator<R> &other) : _ptr(other.create()) {}
FunctionImplementation<R> *create() const { return exchange(_ptr); }
FunctionImplementation<R> *create() const { return getPointerAndReset(_ptr); }
~FunctionCreator() { destroyImplementation(_ptr); }
private:
FunctionCreator<R> &operator=(const FunctionCreator<R> &other);
@ -861,7 +861,7 @@ class Function1Creator {
public:
Function1Creator(Function1Implementation<R, A1> *ptr) : _ptr(ptr) {}
Function1Creator(const Function1Creator<R, A1> &other) : _ptr(other.create()) {}
Function1Implementation<R, A1> *create() const { return exchange(_ptr); }
Function1Implementation<R, A1> *create() const { return getPointerAndReset(_ptr); }
~Function1Creator() { destroyImplementation(_ptr); }
private:
Function1Creator<R, A1> &operator=(const Function1Creator<R, A1> &other);
@ -930,7 +930,7 @@ class Function2Creator {
public:
Function2Creator(Function2Implementation<R, A1, A2> *ptr) : _ptr(ptr) {}
Function2Creator(const Function2Creator<R, A1, A2> &other) : _ptr(other.create()) {}
Function2Implementation<R, A1, A2> *create() const { return exchange(_ptr); }
Function2Implementation<R, A1, A2> *create() const { return getPointerAndReset(_ptr); }
~Function2Creator() { destroyImplementation(_ptr); }
private:
Function2Creator<R, A1, A2> &operator=(const Function2Creator<R, A1, A2> &other);