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: public:
AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {} AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {}
AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {} AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {}
AnimationImplementation *create() const { return exchange(_ptr); } AnimationImplementation *create() const { return getPointerAndReset(_ptr); }
~AnimationCreator() { deleteAndMark(_ptr); } ~AnimationCreator() { deleteAndMark(_ptr); }
private: private:
AnimationCreator &operator=(const AnimationCreator &other); AnimationCreator &operator=(const AnimationCreator &other);

View File

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

View File

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

View File

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