From 9d00ec273bba1c1b6c43d2e30bf06e4ed4c2fab8 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 18 Mar 2016 22:05:08 +0300 Subject: [PATCH] removed Date service messages, removed UnreadBar service message, started adding them to HistoryItems, saving item index in block to keep an eye on the previous message --- Telegram/SourceFiles/facades.cpp | 89 ++-- Telegram/SourceFiles/facades.h | 4 + Telegram/SourceFiles/history.cpp | 579 +++++++++---------------- Telegram/SourceFiles/history.h | 316 +++++++++----- Telegram/SourceFiles/historywidget.cpp | 30 +- Telegram/SourceFiles/historywidget.h | 3 + Telegram/SourceFiles/mainwidget.cpp | 4 +- Telegram/SourceFiles/types.h | 31 +- 8 files changed, 517 insertions(+), 539 deletions(-) diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index e26e44f528..f928fe630d 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -226,14 +226,22 @@ void Set##Name(const Type &Name) { \ Namespace##Data->Name = Name; \ } -struct SandboxDataStruct { - QString LangSystemISO; - int32 LangSystem = languageDefault; +namespace Sandbox { - QByteArray LastCrashDump; - ConnectionProxy PreLaunchProxy; -}; -SandboxDataStruct *SandboxData = 0; + namespace internal { + + struct Data { + QString LangSystemISO; + int32 LangSystem = languageDefault; + + QByteArray LastCrashDump; + ConnectionProxy PreLaunchProxy; + }; + + } + +} +Sandbox::internal::Data *SandboxData = 0; uint64 SandboxUserTag = 0; namespace Sandbox { @@ -320,7 +328,7 @@ namespace Sandbox { } void start() { - SandboxData = new SandboxDataStruct(); + SandboxData = new internal::Data(); SandboxData->LangSystemISO = psCurrentLanguage(); if (SandboxData->LangSystemISO.isEmpty()) SandboxData->LangSystemISO = qstr("en"); @@ -349,36 +357,46 @@ namespace Sandbox { } -struct GlobalDataStruct { - uint64 LaunchId = 0; +namespace Global { + namespace internal { - Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout; - bool AdaptiveForWide = true; + struct Data { + uint64 LaunchId = 0; - int32 DebugLoggingFlags = 0; + Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout; + bool AdaptiveForWide = true; - // config - int32 ChatSizeMax = 200; - int32 MegagroupSizeMax = 1000; - int32 ForwardedCountMax = 100; - int32 OnlineUpdatePeriod = 120000; - int32 OfflineBlurTimeout = 5000; - int32 OfflineIdleTimeout = 30000; - int32 OnlineFocusTimeout = 1000; - int32 OnlineCloudTimeout = 300000; - int32 NotifyCloudDelay = 30000; - int32 NotifyDefaultDelay = 1500; - int32 ChatBigSize = 10; - int32 PushChatPeriod = 60000; - int32 PushChatLimit = 2; - int32 SavedGifsLimit = 200; - int32 EditTimeLimit = 172800; + int32 DebugLoggingFlags = 0; - Global::HiddenPinnedMessagesMap HiddenPinnedMessages; + // config + int32 ChatSizeMax = 200; + int32 MegagroupSizeMax = 1000; + int32 ForwardedCountMax = 100; + int32 OnlineUpdatePeriod = 120000; + int32 OfflineBlurTimeout = 5000; + int32 OfflineIdleTimeout = 30000; + int32 OnlineFocusTimeout = 1000; + int32 OnlineCloudTimeout = 300000; + int32 NotifyCloudDelay = 30000; + int32 NotifyDefaultDelay = 1500; + int32 ChatBigSize = 10; + int32 PushChatPeriod = 60000; + int32 PushChatLimit = 2; + int32 SavedGifsLimit = 200; + int32 EditTimeLimit = 172800; - Global::CircleMasksMap CircleMasks; -}; -GlobalDataStruct *GlobalData = 0; + HiddenPinnedMessagesMap HiddenPinnedMessages; + + PendingItemsMap PendingInitDimensionsItems; + PendingItemsMap PendingRepaintItems; + + CircleMasksMap CircleMasks; + }; + + } +} + +Global::internal::Data *GlobalData = 0; namespace Global { @@ -387,7 +405,7 @@ namespace Global { } void start() { - GlobalData = new GlobalDataStruct(); + GlobalData = new internal::Data(); memset_rand(&GlobalData->LaunchId, sizeof(GlobalData->LaunchId)); } @@ -423,6 +441,9 @@ namespace Global { DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages); + DefineRefVar(Global, PendingItemsMap, PendingInitDimensionsItems); + DefineRefVar(Global, PendingItemsMap, PendingRepaintItems); + DefineRefVar(Global, CircleMasksMap, CircleMasks); }; diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index d0f2737d23..37139dfa35 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -170,6 +170,10 @@ namespace Global { typedef QMap HiddenPinnedMessagesMap; DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages); + typedef OrderedSet PendingItemsMap; + DeclareRefVar(PendingItemsMap, PendingInitDimensionsItems); + DeclareRefVar(PendingItemsMap, PendingRepaintItems); + typedef QMap CircleMasksMap; DeclareRefVar(CircleMasksMap, CircleMasks); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 5eb4d1c4e5..df3f9790da 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -493,8 +493,8 @@ void ChannelHistory::insertCollapseItem(MsgId wasMinId) { for (int32 itemIndex = 0, itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) { HistoryItem *item = block->items.at(itemIndex); if (insertAfter || item->id > wasMinId || (item->id == wasMinId && !item->isImportant())) { - _collapseMessage = new HistoryCollapse(this, block, wasMinId, item->date); - if (!addNewInTheMiddle(regItem(_collapseMessage), blockIndex, itemIndex)) { + _collapseMessage = HistoryCollapse::create((History*)this, wasMinId, item->date); + if (!addNewInTheMiddle(_collapseMessage, blockIndex, itemIndex)) { _collapseMessage = 0; } return; @@ -563,7 +563,7 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) { _otherNewLoaded = false; } else if (_otherNewLoaded) { if (_otherList.isEmpty() || _otherList.back()->type() != HistoryItemGroup) { - _otherList.push_back(regItem(new HistoryGroup(this, 0, d, _otherList.isEmpty() ? date(d.vdate) : _otherList.back()->date))); + _otherList.push_back(HistoryGroup::create(this, d, _otherList.isEmpty() ? date(d.vdate) : _otherList.back()->date)); } else { static_cast(_otherList.back())->uniteWith(d.vmin_id.v, d.vmax_id.v, d.vcount.v); } @@ -571,8 +571,8 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) { if (onlyImportant()) { if (newLoaded) { - HistoryItem *prev = blocks.isEmpty() ? 0 : blocks.back()->items.back(); - HistoryBlock *to = 0; + HistoryItem *prev = blocks.isEmpty() ? nullptr : blocks.back()->items.back(); + HistoryBlock *to = nullptr; bool newBlock = blocks.isEmpty(); if (newBlock) { to = new HistoryBlock(this); @@ -583,18 +583,6 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) { } prev = addMessageGroupAfterPrevToBlock(d, prev, to); height += to->height; - if (newBlock) { - HistoryBlock *dateBlock = new HistoryBlock(this); - HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, blocks.front()->items.front()->date); - dateBlock->items.push_back(dayItem); - int32 dh = dayItem->resize(width); - dateBlock->height = dh; - for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) { - (*i)->y += dh; - } - blocks.push_front(dateBlock); // date block CHECK - height += dh; - } } } else { setNotLoadedAtBottom(); @@ -616,13 +604,12 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { if (isEmpty()) { HistoryBlock *to = new HistoryBlock(this); bool newBlock = true; - _joinedMessage = new HistoryJoined(this, to, inviteDate, inviter, flags); - if (!addNewItem(to, newBlock, regItem(_joinedMessage), unread)) { + _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); + if (!addNewItem(to, newBlock, _joinedMessage, unread)) { _joinedMessage = 0; } return _joinedMessage; } - HistoryItem *lastSeenDateItem = 0; for (int32 blockIndex = blocks.size(); blockIndex > 1;) { HistoryBlock *block = blocks.at(--blockIndex); for (int32 itemIndex = block->items.size(); itemIndex > 0;) { @@ -636,19 +623,10 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } ++itemIndex; - if (item->date.date() != inviteDate.date()) { - HistoryDateMsg *joinedDateItem = new HistoryDateMsg(this, block, inviteDate.date()); - if (addNewInTheMiddle(regItem(joinedDateItem), blockIndex, itemIndex)) { - ++itemIndex; - } - } - _joinedMessage = new HistoryJoined(this, block, inviteDate, inviter, flags); - if (!addNewInTheMiddle(regItem(_joinedMessage), blockIndex, itemIndex)) { + _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); + if (!addNewInTheMiddle(_joinedMessage, blockIndex, itemIndex)) { _joinedMessage = 0; } - if (lastSeenDateItem && lastSeenDateItem->date.date() == inviteDate.date()) { - lastSeenDateItem->destroy(); - } if (lastMsgDate.isNull() || inviteDate >= lastMsgDate) { setLastMessage(_joinedMessage); if (unread) { @@ -656,39 +634,21 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } } return _joinedMessage; - } else { - lastSeenDateItem = 0; } - } else if (type == HistoryItemDate) { - lastSeenDateItem = item; } } } // adding new item to new block int32 addToH = 0, skip = 0; - if (!blocks.isEmpty()) { // remove date block - if (width) addToH = -blocks.front()->height; - HistoryBlock *dateblock = blocks.front(); - blocks.pop_front(); - delete dateblock; - } HistoryItem *till = blocks.isEmpty() ? 0 : blocks.front()->items.front(); HistoryBlock *block = new HistoryBlock(this); - _joinedMessage = new HistoryJoined(this, block, inviteDate, inviter, flags); - addItemAfterPrevToBlock(regItem(_joinedMessage), 0, block); - if (till && _joinedMessage && inviteDate.date() != till->date.date()) { - HistoryItem *dayItem = createDayServiceMsg(this, block, till->date); - block->items.push_back(dayItem); - if (width) { - dayItem->y = block->height; - block->height += dayItem->resize(width); - } - } + _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); + addItemAfterPrevToBlock(_joinedMessage, 0, block); if (!block->items.isEmpty()) { - blocks.push_front(block); // CHECK + blocks.push_front(block); if (width) { addToH += block->height; ++skip; @@ -696,21 +656,6 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } else { delete block; } - if (!blocks.isEmpty()) { - HistoryBlock *dateBlock = new HistoryBlock(this); - HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, blocks.front()->items.front()->date); - dateBlock->items.push_back(dayItem); - if (width) { - int32 dh = dayItem->resize(width); - dateBlock->height = dh; - if (skip) { - blocks.front()->y += dh; - } - addToH += dh; - ++skip; - } - blocks.push_front(dateBlock); // date block CHECK - } if (width && addToH) { for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) { if (skip) { @@ -861,7 +806,6 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp t_assert(!newBlock); return item; } - item->attach(to); } return addNewItem(to, newBlock, item, (type == NewMessageUnread)); } @@ -877,7 +821,7 @@ void ChannelHistory::addNewToOther(HistoryItem *item, NewMessageType type) { } } else { if (_otherList.isEmpty() || _otherList.back()->type() != HistoryItemGroup) { - _otherList.push_back(regItem(new HistoryGroup(this, 0, item, _otherList.isEmpty() ? item->date : _otherList.back()->date))); + _otherList.push_back(HistoryGroup::create(this, item, _otherList.isEmpty() ? item->date : _otherList.back()->date)); } else { static_cast(_otherList.back())->uniteWith(item); } @@ -910,7 +854,6 @@ void ChannelHistory::switchMode() { oldLoaded = _otherOldLoaded; if (int32 count = _otherList.size()) { blocks.reserve(qCeil(count / float64(MessagesPerPage)) + 1); - createInitialDateBlock(_otherList.front()->date); HistoryItem *prev = 0; for (int32 i = 0; i < count;) { @@ -918,11 +861,9 @@ void ChannelHistory::switchMode() { int32 willAddToBlock = qMin(int32(MessagesPerPage), count - i); block->items.reserve(willAddToBlock); for (int32 till = i + willAddToBlock; i < till; ++i) { - HistoryItem *item = _otherList.at(i); - item->attach(block); - prev = addItemAfterPrevToBlock(item, prev, block); + prev = addItemAfterPrevToBlock(_otherList.at(i), prev, block); } - blocks.push_back(block); // CHECK + blocks.push_back(block); if (width) { block->y = height; height += block->height; @@ -1310,7 +1251,6 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo if (!result->detached()) { result->detach(); } - result->attach(block); } if (msg.type() == mtpc_message) { result->updateMedia(msg.c_message().has_media() ? (&msg.c_message().vmedia) : 0); @@ -1327,7 +1267,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo switch (msg.type()) { case mtpc_messageEmpty: - result = new HistoryServiceMsg(this, block, msg.c_messageEmpty().vid.v, date(), lang(lng_message_empty)); + result = HistoryServiceMsg::create(this, msg.c_messageEmpty().vid.v, date(), lang(lng_message_empty)); break; case mtpc_message: { @@ -1379,14 +1319,14 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo QString text(lng_message_unsupported(lt_link, qsl("https://desktop.telegram.org"))); EntitiesInText entities = textParseEntities(text, _historyTextNoMonoOptions.flags); entities.push_front(EntityInText(EntityInTextItalic, 0, text.size())); - result = new HistoryMessage(this, block, m.vid.v, m.vflags.v, m.vvia_bot_id.v, date(m.vdate), m.vfrom_id.v, text, entities); + result = HistoryMessage::create(this, m.vid.v, m.vflags.v, m.vvia_bot_id.v, date(m.vdate), m.vfrom_id.v, text, entities); } else if (badMedia) { - result = new HistoryServiceMsg(this, block, m.vid.v, date(m.vdate), lang(lng_message_empty), m.vflags.v, 0, m.has_from_id() ? m.vfrom_id.v : 0); + result = HistoryServiceMsg::create(this, m.vid.v, date(m.vdate), lang(lng_message_empty), m.vflags.v, nullptr, m.has_from_id() ? m.vfrom_id.v : 0); } else { if (m.has_reply_to_msg_id() && m.vreply_to_msg_id.v > 0) { - result = new HistoryReply(this, block, m); + result = HistoryReply::create(this, m); } else { - result = new HistoryMessage(this, block, m); + result = HistoryMessage::create(this, m); } if (m.has_reply_markup()) { App::feedReplyMarkup(channelId(), msgId, m.vreply_markup); @@ -1396,7 +1336,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo case mtpc_messageService: { const MTPDmessageService &d(msg.c_messageService()); - result = new HistoryServiceMsg(this, block, d); + result = HistoryServiceMsg::create(this, d); if (applyServiceAction) { const MTPmessageAction &action(d.vaction); @@ -1539,35 +1479,25 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo App::checkSavedGif(result); } - return regItem(result); + return result; } -HistoryItem *History::createItemForwarded(HistoryBlock *block, MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *msg) { - return regItem(new HistoryMessage(this, block, id, flags, date, from, msg)); +HistoryItem *History::createItemForwarded(MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *msg) { + return HistoryMessage::create(this, id, flags, date, from, msg); } -HistoryItem *History::createItemDocument(HistoryBlock *block, MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { - HistoryItem *result = 0; - +HistoryItem *History::createItemDocument(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { if ((flags & MTPDmessage::flag_reply_to_msg_id) && replyTo > 0) { - result = new HistoryReply(this, block, id, flags, viaBotId, replyTo, date, from, doc, caption); - } else { - result = new HistoryMessage(this, block, id, flags, viaBotId, date, from, doc, caption); + return HistoryReply::create(this, id, flags, viaBotId, replyTo, date, from, doc, caption); } - - return regItem(result); + return HistoryMessage::create(this, id, flags, viaBotId, date, from, doc, caption); } -HistoryItem *History::createItemPhoto(HistoryBlock *block, MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { - HistoryItem *result = 0; - +HistoryItem *History::createItemPhoto(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { if ((flags & MTPDmessage::flag_reply_to_msg_id) && replyTo > 0) { - result = new HistoryReply(this, block, id, flags, viaBotId, replyTo, date, from, photo, caption); - } else { - result = new HistoryMessage(this, block, id, flags, viaBotId, date, from, photo, caption); + return HistoryReply::create(this, id, flags, viaBotId, replyTo, date, from, photo, caption); } - - return regItem(result); + return HistoryMessage::create(this, id, flags, viaBotId, date, from, photo, caption); } HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString &text, int32 flags, HistoryMedia *media, bool newMsg) { @@ -1581,8 +1511,8 @@ HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString & t_assert(to->items.back() != nullptr); } - HistoryItem *result = new HistoryServiceMsg(this, to, msgId, date, text, flags, media); - return addNewItem(to, newBlock, regItem(result), newMsg); + HistoryItem *result = HistoryServiceMsg::create(this, msgId, date, text, flags, media); + return addNewItem(to, newBlock, result, newMsg); } HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type) { @@ -1615,7 +1545,6 @@ HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type) t_assert(!newBlock); return item; } - item->attach(to); } return addNewItem(to, newBlock, item, (type == NewMessageUnread)); } @@ -1634,7 +1563,7 @@ HistoryItem *History::addNewForwarded(MsgId id, int32 flags, QDateTime date, int t_assert(!to->items.isEmpty()); t_assert(to->items.back() != nullptr); } - return addNewItem(to, newBlock, createItemForwarded(to, id, flags, date, from, item), true); + return addNewItem(to, newBlock, createItemForwarded(id, flags, date, from, item), true); } HistoryItem *History::addNewDocument(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { @@ -1647,7 +1576,7 @@ HistoryItem *History::addNewDocument(MsgId id, int32 flags, int32 viaBotId, MsgI t_assert(!to->items.isEmpty()); t_assert(to->items.back() != nullptr); } - return addNewItem(to, newBlock, createItemDocument(to, id, flags, viaBotId, replyTo, date, from, doc, caption), true); + return addNewItem(to, newBlock, createItemDocument(id, flags, viaBotId, replyTo, date, from, doc, caption), true); } HistoryItem *History::addNewPhoto(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { @@ -1660,24 +1589,7 @@ HistoryItem *History::addNewPhoto(MsgId id, int32 flags, int32 viaBotId, MsgId r t_assert(!to->items.isEmpty()); t_assert(to->items.back() != nullptr); } - return addNewItem(to, newBlock, createItemPhoto(to, id, flags, viaBotId, replyTo, date, from, photo, caption), true); -} - -void History::createInitialDateBlock(const QDateTime &date) { - HistoryBlock *dateBlock = new HistoryBlock(this); // date block - HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, date); - dateBlock->items.push_back(dayItem); - if (width) { - dateBlock->height += dayItem->resize(width); - } - - blocks.push_front(dateBlock); - if (width) { - height += dateBlock->height; - for (int32 i = 1, l = blocks.size(); i < l; ++i) { - blocks.at(i)->y += dateBlock->height; - } - } + return addNewItem(to, newBlock, createItemPhoto(id, flags, viaBotId, replyTo, date, from, photo, caption), true); } bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMethod method) { @@ -1730,21 +1642,10 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a } if (newBlock) { - createInitialDateBlock(adding->date); - to->y = height; blocks.push_back(to); - } else if (to->items.back()->date.date() != adding->date.date()) { - HistoryItem *dayItem = createDayServiceMsg(this, to, adding->date); - to->items.push_back(dayItem); - if (width) { - dayItem->y = to->height; - - int32 dh = dayItem->resize(width); - to->height += dh; - height += dh; - } } + adding->attachToBlock(to, to->items.size()); to->items.push_back(adding); setLastMessage(adding); @@ -1850,7 +1751,7 @@ void History::newItemAdded(HistoryItem *item) { item->from()->asUser()->madeAction(); } if (item->out()) { - if (unreadBar) unreadBar->destroy(); + if (unreadBar) unreadBar->destroyUnreadBar(); if (!item->unread()) { outboxRead(item); } @@ -1866,17 +1767,7 @@ void History::newItemAdded(HistoryItem *item) { } HistoryItem *History::addItemAfterPrevToBlock(HistoryItem *item, HistoryItem *prev, HistoryBlock *block) { - if (prev && prev->date.date() != item->date.date()) { - HistoryItem *dayItem = createDayServiceMsg(this, prev->block(), item->date); - prev->block()->items.push_back(dayItem); - if (width) { - dayItem->y = prev->block()->height; - prev->block()->height += dayItem->resize(width); - if (prev->block() != block) { - height += dayItem->height(); - } - } - } + item->attachToBlock(block, block->items.size()); block->items.push_back(item); if (width) { item->y = block->height; @@ -1890,7 +1781,7 @@ HistoryItem *History::addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &gr static_cast(prev)->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v); return prev; } - return addItemAfterPrevToBlock(regItem(new HistoryGroup(this, block, group, prev ? prev->date : date(group.vdate))), prev, block); + return addItemAfterPrevToBlock(HistoryGroup::create(this, group, prev ? prev->date : date(group.vdate)), prev, block); } HistoryItem *History::addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem *prev) { @@ -1902,15 +1793,13 @@ HistoryItem *History::addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem QDateTime date = prev ? prev->date : newItem->date; HistoryBlock *block = prev ? prev->block() : 0; if (!block) { - createInitialDateBlock(date); - block = new HistoryBlock(this); - blocks.push_back(block); // CHECK + blocks.push_back(block); if (width) { block->y = height; } } - return addItemAfterPrevToBlock(regItem(new HistoryGroup(this, block, newItem, date)), prev, block); + return addItemAfterPrevToBlock(HistoryGroup::create(this, newItem, date), prev, block); } void History::addOlderSlice(const QVector &slice, const QVector *collapsed) { @@ -1927,7 +1816,7 @@ void History::addOlderSlice(const QVector &slice, const QVectorconstData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0; - HistoryItem *oldFirst = nullptr, *last = nullptr; + HistoryItem *last = nullptr; HistoryBlock *block = new HistoryBlock(this); block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0)); for (auto i = slice.cend(), e = slice.cbegin(); i != e;) { @@ -1952,10 +1841,7 @@ void History::addOlderSlice(const QVector &slice, const QVector 1); - oldFirst = blocks.at(1)->items.front(); - } + HistoryItem *oldFirst = blocks.isEmpty() ? nullptr : blocks.front()->items.front(); while (oldFirst && last && oldFirst->type() == HistoryItemGroup && last->type() == HistoryItemGroup) { static_cast(last)->uniteWith(static_cast(oldFirst)); oldFirst->destroy(); @@ -1966,36 +1852,24 @@ void History::addOlderSlice(const QVector &slice, const QVectoritems.front(); } } - if (oldFirst && last && last->date.date() != oldFirst->date.date()) { - HistoryItem *dayItem = createDayServiceMsg(this, block, oldFirst->date); - block->items.push_back(dayItem); - if (width) { - dayItem->y = block->height; - block->height += dayItem->resize(width); - } - } if (block->items.isEmpty()) { oldLoaded = true; delete block; } else { if (oldFirst) { - HistoryBlock *initial = blocks.at(0); - blocks[0] = block; - blocks.push_front(initial); + blocks.push_front(block); if (width) { - block->y = initial->height; - for (int32 i = 2, l = blocks.size(); i < l; ++i) { + block->y = 0; + for (int32 i = 1, l = blocks.size(); i < l; ++i) { blocks.at(i)->y += block->height; } height += block->height; } - initial->items.at(0)->setDate(block->items.at(0)->date); } else { blocks.push_front(block); if (width) { height = block->height; } - createInitialDateBlock(block->items.at(0)->date); } if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants @@ -2129,9 +2003,6 @@ void History::addNewerSlice(const QVector &slice, const QVectory = height; height += block->height; } - if (blocks.size() == 1) { - createInitialDateBlock(block->items.at(0)->date); - } } } @@ -2272,7 +2143,11 @@ void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) { count += h->unreadCount; } } - unreadBar->setCount(count); + if (count > 0) { + unreadBar->setUnreadBarCount(count); + } else { + unreadBar->setUnreadBarFreezed(); + } } } } @@ -2323,10 +2198,13 @@ void History::addUnreadBar() { count += h->unreadCount; } } - HistoryBlock *block = showFrom->block(); - unreadBar = new HistoryUnreadBar(this, block, count, showFrom->date); - if (!addNewInTheMiddle(regItem(unreadBar), blocks.indexOf(block), block->items.indexOf(showFrom))) { - unreadBar = 0; + showFrom->setUnreadBarCount(count); + unreadBar = showFrom; +} + +void History::destroyUnreadBar() { + if (unreadBar) { + unreadBar->destroyUnreadBar(); } } @@ -2338,7 +2216,12 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, HistoryBlock *block = blocks.at(blockIndex); newItem->y = (itemIndex < block->items.size()) ? block->items.at(itemIndex)->y : block->height; + + newItem->attachToBlock(block, itemIndex); block->items.insert(itemIndex, newItem); + for (int i = itemIndex + 1, l = block->items.size(); i < l; ++i) { + block->items.at(i)->setIndexInBlock(i); + } if (width) { int32 dh = newItem->resize(width), l = block->items.size(); @@ -2539,13 +2422,13 @@ const ChannelHistory *History::asChannelHistory() const { void History::clear(bool leaveItems) { if (unreadBar) { - unreadBar->destroy(); + unreadBar = nullptr; } if (showFrom) { - showFrom = 0; + showFrom = nullptr; } if (!leaveItems) { - setLastMessage(0); + setLastMessage(nullptr); } for (int32 i = 0; i < OverviewCount; ++i) { if (!overview[i].isEmpty() || !overviewIds[i].isEmpty()) { @@ -2802,14 +2685,15 @@ void HistoryBlock::removeItem(HistoryItem *item) { if (history->showFrom == item) { history->getNextShowFrom(this, i); } + if (history->unreadBar == item) { + history->unreadBar = nullptr; + } if (i < 0) { return; } - bool createInitialDate = false; - QDateTime initialDateTime; int32 myIndex = history->blocks.indexOf(this); - if (myIndex >= 0 && item->type() != HistoryItemDate) { // fix message groups and date items + if (myIndex >= 0) { // fix message groups and date items if (item->isImportant()) { // unite message groups around this important message HistoryGroup *nextGroup = 0, *prevGroup = 0; HistoryCollapse *nextCollapse = 0; @@ -2862,72 +2746,20 @@ void HistoryBlock::removeItem(HistoryItem *item) { nextCollapse->destroy(); } } - - // fix date items - HistoryItem *nextItem = (i < items.size() - 1) ? items[i + 1] : ((myIndex < history->blocks.size() - 1) ? history->blocks[myIndex + 1]->items[0] : 0); - if (nextItem && nextItem == history->unreadBar) { // skip unread bar - if (i < items.size() - 2) { - nextItem = items[i + 2]; - } else if (i < items.size() - 1) { - nextItem = ((myIndex < history->blocks.size() - 1) ? history->blocks[myIndex + 1]->items[0] : 0); - } else if (myIndex < history->blocks.size() - 1) { - if (0 < history->blocks[myIndex + 1]->items.size() - 1) { - nextItem = history->blocks[myIndex + 1]->items[1]; - } else if (myIndex < history->blocks.size() - 2) { - nextItem = history->blocks[myIndex + 2]->items[0]; - } else { - nextItem = 0; - } - } else { - nextItem = 0; - } - } - if (!nextItem || nextItem->type() == HistoryItemDate) { // only if there is no next item or it is a date item - HistoryItem *prevItem = (i > 0) ? items[i - 1] : 0; - if (prevItem && prevItem == history->unreadBar) { // skip unread bar - prevItem = (i > 1) ? items[i - 2] : 0; - } - if (prevItem) { - if (prevItem->type() == HistoryItemDate) { - prevItem->destroy(); - --i; - } - } else if (myIndex > 0) { - HistoryBlock *prevBlock = history->blocks[myIndex - 1]; - if (prevBlock->items.isEmpty() || ((myIndex == 1) && (prevBlock->items.size() != 1 || prevBlock->items.front()->type() != HistoryItemDate))) { - LOG(("App Error: Found bad history, with no first date block: %1").arg(history->blocks[0]->items.size())); - } else if (prevBlock->items[prevBlock->items.size() - 1]->type() == HistoryItemDate) { - prevBlock->items[prevBlock->items.size() - 1]->destroy(); - if (nextItem && myIndex == 1) { // destroy next date (for creating initial then) - initialDateTime = nextItem->date; - createInitialDate = true; - nextItem->destroy(); - } - } - } - } } // myIndex can be invalid now, because of destroying previous blocks dh = item->height(); items.remove(i); - int32 l = items.size(); if ((!item->out() || item->isPost()) && item->unread() && history->unreadCount) { history->setUnreadCount(history->unreadCount - 1); } - int32 itemType = item->type(); - if (itemType == HistoryItemUnreadBar) { - if (history->unreadBar == item) { - history->unreadBar = 0; - } - } - if (createInitialDate) { - history->createInitialDateBlock(initialDateTime); - } + History *h = history; - if (l) { + if (int32 l = items.size()) { for (; i < l; ++i) { - items[i]->y -= dh; + items.at(i)->y -= dh; + items.at(i)->setIndexInBlock(i); } height -= dh; history->blockResized(this, dh); @@ -2942,16 +2774,38 @@ void HistoryDependentItemCallback::call(ChannelData *channel, MsgId msgId) const } } -HistoryItem::HistoryItem(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime msgDate, int32 from) : y(0) +HistoryMessageUnreadBar::HistoryMessageUnreadBar(Interfaces*) : _width(0), _freezed(false) { +} + +void HistoryMessageUnreadBar::init(int count) { + if (_freezed) return; + _text = lng_unread_bar(lt_count, count); + _width = st::semiboldFont->width(_text); +} + +HistoryMessageDate::HistoryMessageDate(Interfaces*) : _width(0) { +} + +void HistoryMessageDate::init(const QDateTime &date) { + _text = langDayOfMonthFull(date.date()); + _width = st::semiboldFont->width(_text); +} + +HistoryItem::HistoryItem(History *history, MsgId msgId, int32 flags, QDateTime msgDate, int32 from) : HistoryElem() +, y(0) , id(msgId) , date(msgDate) , _from(from ? App::user(from) : history->peer) , _history(history) -, _block(block) , _flags(flags) , _authorNameVersion(author()->nameVersion) { } +void HistoryItem::finishCreate() { + App::historyRegItem(this); + initDimensions(); +} + void HistoryItem::destroy() { bool wasAtBottom = history()->loadedAtBottom(); _history->removeNotification(this); @@ -2990,13 +2844,24 @@ void HistoryItem::detach() { _history->showFrom = 0; } } - if (_history && _history->unreadBar && _history->blocks.back()->items.back() == _history->unreadBar) { - _history->unreadBar->destroy(); - } } void HistoryItem::detachFast() { _block = 0; + _indexInBlock = -1; +} + +void HistoryItem::previousItemChanged() { + if (displayDate()) { + if (!Is()) { + AddInterfaces(HistoryMessageDate::Bit()); + Get()->init(date); + Global::RefPendingInitDimensionsItems().insert(this); + } + } else if (Is()) { + RemoveInterfaces(HistoryMessageDate::Bit()); + Global::RefPendingInitDimensionsItems().insert(this); + } } void HistoryItem::setId(MsgId newId) { @@ -3036,6 +2901,42 @@ bool HistoryItem::canEdit(const QDateTime &cur) const { return false; } +void HistoryItem::destroyUnreadBar() { + if (Is()) { + RemoveInterfaces(HistoryMessageUnreadBar::Bit()); + Global::RefPendingInitDimensionsItems().insert(this); + if (_history->unreadBar == this) { + _history->unreadBar = nullptr; + } + } +} + +void HistoryItem::setUnreadBarCount(int count) { + if (count > 0) { + HistoryMessageUnreadBar *bar; + if (!Is()) { + AddInterfaces(HistoryMessageUnreadBar::Bit()); + Global::RefPendingInitDimensionsItems().insert(this); + bar = Get(); + } else { + bar = Get(); + if (bar->_freezed) { + return; + } + Global::RefPendingRepaintItems().insert(this); + } + bar->init(count); + } else { + destroyUnreadBar(); + } +} + +void HistoryItem::setUnreadBarFreezed() { + if (auto *bar = Get()) { + bar->_freezed = true; + } +} + void HistoryItem::clipCallback(ClipReaderNotification notification) { HistoryMedia *media = getMedia(); if (!media) return; @@ -3079,14 +2980,6 @@ HistoryItem::~HistoryItem() { } } -HistoryItem *regItem(HistoryItem *item) { - if (item) { - App::historyRegItem(item); - item->initDimensions(); - } - return item; -} - RadialAnimation::RadialAnimation(AnimationCreator creator) : _firstStart(0) , _lastStart(0) @@ -3586,11 +3479,11 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent) } } -void HistoryPhoto::regItem(HistoryItem *item) { +void HistoryPhoto::attachToItem(HistoryItem *item) { App::regPhotoItem(_data, item); } -void HistoryPhoto::unregItem(HistoryItem *item) { +void HistoryPhoto::detachFromItem(HistoryItem *item) { App::unregPhotoItem(_data, item); } @@ -3865,11 +3758,11 @@ void HistoryVideo::updateStatusText(const HistoryItem *parent) const { } } -void HistoryVideo::regItem(HistoryItem *item) { +void HistoryVideo::attachToItem(HistoryItem *item) { App::regDocumentItem(_data, item); } -void HistoryVideo::unregItem(HistoryItem *item) { +void HistoryVideo::detachFromItem(HistoryItem *item) { App::unregDocumentItem(_data, item); } @@ -3909,7 +3802,7 @@ void HistoryDocumentVoice::checkPlaybackFinished() const { HistoryDocument::HistoryDocument(DocumentData *document, const QString &caption, const HistoryItem *parent) : HistoryFileMedia() , _parent(0) , _data(document) { - create(!caption.isEmpty()); + createInterfaces(!caption.isEmpty()); if (HistoryDocumentNamed *named = Get()) { named->_name = documentName(_data); named->_namew = st::semiboldFont->width(named->_name); @@ -3929,7 +3822,7 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi , _parent(0) , _data(other._data) { const HistoryDocumentCaptioned *captioned = other.Get(); - create(captioned != 0); + createInterfaces(captioned != 0); if (HistoryDocumentNamed *named = Get()) { if (const HistoryDocumentNamed *oin = other.Get()) { named->_name = oin->_name; @@ -3949,7 +3842,7 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi } } -void HistoryDocument::create(bool caption) { +void HistoryDocument::createInterfaces(bool caption) { uint64 mask = 0; if (_data->voice()) { mask |= HistoryDocumentVoice::Bit(); @@ -4450,11 +4343,11 @@ void HistoryDocument::step_voiceProgress(float64 ms, bool timer) { } } -void HistoryDocument::regItem(HistoryItem *item) { +void HistoryDocument::attachToItem(HistoryItem *item) { App::regDocumentItem(_data, item); } -void HistoryDocument::unregItem(HistoryItem *item) { +void HistoryDocument::detachFromItem(HistoryItem *item) { App::unregDocumentItem(_data, item); } @@ -4800,11 +4693,11 @@ void HistoryGif::updateStatusText(const HistoryItem *parent) const { } } -void HistoryGif::regItem(HistoryItem *item) { +void HistoryGif::attachToItem(HistoryItem *item) { App::regDocumentItem(_data, item); } -void HistoryGif::unregItem(HistoryItem *item) { +void HistoryGif::detachFromItem(HistoryItem *item) { App::unregDocumentItem(_data, item); } @@ -4992,11 +4885,11 @@ const QString HistorySticker::inHistoryText() const { return qsl("[ ") + inDialogsText() + qsl(" ]"); } -void HistorySticker::regItem(HistoryItem *item) { +void HistorySticker::attachToItem(HistoryItem *item) { App::regDocumentItem(_data, item); } -void HistorySticker::unregItem(HistoryItem *item) { +void HistorySticker::detachFromItem(HistoryItem *item) { App::unregDocumentItem(_data, item); } @@ -5160,13 +5053,13 @@ const QString HistoryContact::inHistoryText() const { return qsl("[ ") + lang(lng_in_dlg_contact) + qsl(" : ") + _name.original() + qsl(", ") + _phone + qsl(" ]"); } -void HistoryContact::regItem(HistoryItem *item) { +void HistoryContact::attachToItem(HistoryItem *item) { if (_userId) { App::regSharedContactItem(_userId, item); } } -void HistoryContact::unregItem(HistoryItem *item) { +void HistoryContact::detachFromItem(HistoryItem *item) { if (_userId) { App::unregSharedContactItem(_userId, item); } @@ -5175,9 +5068,9 @@ void HistoryContact::unregItem(HistoryItem *item) { void HistoryContact::updateFrom(const MTPMessageMedia &media, HistoryItem *parent) { if (media.type() == mtpc_messageMediaContact) { if (_userId != media.c_messageMediaContact().vuser_id.v) { - unregItem(parent); + detachFromItem(parent); _userId = media.c_messageMediaContact().vuser_id.v; - regItem(parent); + attachToItem(parent); } } } @@ -5630,14 +5523,14 @@ void HistoryWebPage::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { } } -void HistoryWebPage::regItem(HistoryItem *item) { +void HistoryWebPage::attachToItem(HistoryItem *item) { App::regWebPageItem(_data, item); - if (_attach) _attach->regItem(item); + if (_attach) _attach->attachToItem(item); } -void HistoryWebPage::unregItem(HistoryItem *item) { +void HistoryWebPage::detachFromItem(HistoryItem *item) { App::unregWebPageItem(_data, item); - if (_attach) _attach->unregItem(item); + if (_attach) _attach->detachFromItem(item); } const QString HistoryWebPage::inDialogsText() const { @@ -6146,8 +6039,8 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const { } } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg) : - HistoryItem(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) +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) , _textWidth(0) , _textHeight(0) @@ -6162,15 +6055,15 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPD if (f.has_channel_post()) originalId = f.vchannel_post.v; } } - create(msg.has_via_bot_id() ? msg.vvia_bot_id.v : 0, msg.has_views() ? msg.vviews.v : -1, authorOriginalId, fromOriginalId, originalId); + createInterfaces(msg.has_via_bot_id() ? msg.vvia_bot_id.v : 0, msg.has_views() ? msg.vviews.v : -1, authorOriginalId, fromOriginalId, originalId); QString text(textClean(qs(msg.vmessage))); initMedia(msg.has_media() ? (&msg.vmedia) : 0, text); setText(text, msg.has_entities() ? entitiesFromMTP(msg.ventities.c_vector().v) : EntitiesInText()); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *fwd) -: HistoryItem(history, block, id, newForwardedFlags(history->peer, from, fwd) | flags, date, from) +HistoryMessage::HistoryMessage(History *history, MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *fwd) +: HistoryItem(history, id, newForwardedFlags(history->peer, from, fwd) | flags, date, from) , _text(st::msgMinWidth) , _textWidth(0) , _textHeight(0) @@ -6178,52 +6071,52 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId id, UserData *fwdViaBot = fwd->viaBot(); int32 viaBotId = fwdViaBot ? peerToUser(fwdViaBot->id) : 0; int32 fwdViewsCount = fwd->viewsCount(), views = (fwdViewsCount > 0) ? fwdViewsCount : (isPost() ? 1 : -1); - create(viaBotId, views, fwd->authorOriginal()->id, fwd->fromOriginal()->id, fwd->authorOriginal()->isChannel() ? fwd->id : 0); + createInterfaces(viaBotId, views, fwd->authorOriginal()->id, fwd->fromOriginal()->id, fwd->authorOriginal()->isChannel() ? fwd->id : 0); if (HistoryMedia *mediaOriginal = fwd->getMedia()) { _media = mediaOriginal->clone(); - _media->regItem(this); + _media->attachToItem(this); } setText(fwd->originalText(), fwd->originalEntities()); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId id, int32 flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) - : HistoryItem(history, block, id, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) +HistoryMessage::HistoryMessage(History *history, MsgId id, int32 flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) + : HistoryItem(history, id, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) , _text(st::msgMinWidth) , _textWidth(0) , _textHeight(0) , _media(nullptr) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); + createInterfaces((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); setText(msg, entities); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) : -HistoryItem(history, block, msgId, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) +HistoryMessage::HistoryMessage(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) : +HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) , _text(st::msgMinWidth) , _textWidth(0) , _textHeight(0) , _media(nullptr) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); + createInterfaces((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); initMediaFromDocument(doc, caption); setText(QString(), EntitiesInText()); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) : -HistoryItem(history, block, msgId, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) +HistoryMessage::HistoryMessage(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) : +HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::flag_from_id) ? from : 0) , _text(st::msgMinWidth) , _textWidth(0) , _textHeight(0) , _media(nullptr) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); + createInterfaces((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); _media = new HistoryPhoto(photo, caption, this); - _media->regItem(this); + _media->attachToItem(this); setText(QString(), EntitiesInText()); } -void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal, MsgId originalId) { +void HistoryMessage::createInterfaces(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal, MsgId originalId) { uint64 mask = 0; if (viaBotId) { mask |= HistoryMessageVia::Bit(); @@ -6332,7 +6225,7 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media, QString ¤tTex } } break; }; - if (_media) _media->regItem(this); + if (_media) _media->attachToItem(this); } void HistoryMessage::initMediaFromDocument(DocumentData *doc, const QString &caption) { @@ -6345,7 +6238,7 @@ void HistoryMessage::initMediaFromDocument(DocumentData *doc, const QString &cap } else { _media = new HistoryDocument(doc, caption, this); } - _media->regItem(this); + _media->attachToItem(this); } int32 HistoryMessage::plainMaxWidth() const { @@ -6512,7 +6405,7 @@ void HistoryMessage::setMedia(const MTPMessageMedia *media) { if (_media) { mediaWasDisplayed = _media->isDisplayed(); - _media->unregItem(this); + _media->detachFromItem(this); delete _media; _media = nullptr; } @@ -7067,7 +6960,7 @@ QString HistoryMessage::notificationText() const { HistoryMessage::~HistoryMessage() { if (_media) { - _media->unregItem(this); + _media->detachFromItem(this); deleteAndMark(_media); } if (_flags & MTPDmessage::flag_reply_markup) { @@ -7075,7 +6968,7 @@ HistoryMessage::~HistoryMessage() { } } -HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg) +HistoryReply::HistoryReply(History *history, const MTPDmessage &msg) : HistoryMessage(history, msg) , replyToMsgId(msg.vreply_to_msg_id.v) , replyToMsg(0) , replyToVersion(0) @@ -7086,8 +6979,8 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmess } } -HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) -: HistoryMessage(history, block, msgId, flags, viaBotId, date, from, doc, caption) +HistoryReply::HistoryReply(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) +: HistoryMessage(history, msgId, flags, viaBotId, date, from, doc, caption) , replyToMsgId(replyTo) , replyToMsg(0) , replyToVersion(0) @@ -7098,8 +6991,8 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, i } } -HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) -: HistoryMessage(history, block, msgId, flags, viaBotId, date, from, photo, caption) +HistoryReply::HistoryReply(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) +: HistoryMessage(history, msgId, flags, viaBotId, date, from, photo, caption) , replyToMsgId(replyTo) , replyToMsg(0) , replyToVersion(0) @@ -7501,7 +7394,7 @@ void HistoryServiceMsg::setMessageByAction(const MTPmessageAction &action) { const MTPDmessageActionChatEditPhoto &d(action.c_messageActionChatEditPhoto()); if (d.vphoto.type() == mtpc_photo) { _media = new HistoryPhoto(history()->peer, d.vphoto.c_photo(), st::msgServicePhotoWidth); - _media->regItem(this); + _media->attachToItem(this); } text = isPost() ? lang(lng_action_changed_photo_channel) : lng_action_changed_photo(lt_from, from); } break; @@ -7666,8 +7559,8 @@ bool HistoryServiceMsg::updatePinnedText(const QString *pfrom, QString *ptext) { return result; } -HistoryServiceMsg::HistoryServiceMsg(History *history, HistoryBlock *block, const MTPDmessageService &msg) : - HistoryItem(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) +HistoryServiceMsg::HistoryServiceMsg(History *history, const MTPDmessageService &msg) : + HistoryItem(history, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) , _text(st::msgMinWidth) , _media(0) { if (msg.has_reply_to_msg_id()) { @@ -7680,8 +7573,8 @@ HistoryServiceMsg::HistoryServiceMsg(History *history, HistoryBlock *block, cons setMessageByAction(msg.vaction); } -HistoryServiceMsg::HistoryServiceMsg(History *history, HistoryBlock *block, MsgId msgId, QDateTime date, const QString &msg, int32 flags, HistoryMedia *media, int32 from) : - HistoryItem(history, block, msgId, flags, date, from) +HistoryServiceMsg::HistoryServiceMsg(History *history, MsgId msgId, QDateTime date, const QString &msg, int32 flags, HistoryMedia *media, int32 from) : + HistoryItem(history, msgId, flags, date, from) , _text(st::msgServiceFont, msg, _historySrvOptions, st::dlgMinWidth) , _media(media) { } @@ -7878,33 +7771,18 @@ HistoryServiceMsg::~HistoryServiceMsg() { } } if (_media) { - _media->unregItem(this); + _media->detachFromItem(this); deleteAndMark(_media); } } -HistoryDateMsg::HistoryDateMsg(History *history, HistoryBlock *block, const QDate &date) : -HistoryServiceMsg(history, block, clientMsgId(), QDateTime(date), langDayOfMonthFull(date)) { -} - -void HistoryDateMsg::setDate(const QDateTime &date) { - if (this->date.date() != date.date()) { - setServiceText(langDayOfMonthFull(date.date())); - } - HistoryServiceMsg::setDate(date); -} - -HistoryItem *createDayServiceMsg(History *history, HistoryBlock *block, QDateTime date) { - return regItem(new HistoryDateMsg(history, block, date.date())); -} - -HistoryGroup::HistoryGroup(History *history, HistoryBlock *block, const MTPDmessageGroup &group, const QDateTime &date) : -HistoryServiceMsg(history, block, clientMsgId(), date, lng_channel_comments_count(lt_count, group.vcount.v)/* + qsl(" (%1 .. %2)").arg(group.vmin_id.v).arg(group.vmax_id.v)*/), +HistoryGroup::HistoryGroup(History *history, const MTPDmessageGroup &group, const QDateTime &date) : +HistoryServiceMsg(history, clientMsgId(), date, lng_channel_comments_count(lt_count, group.vcount.v)/* + qsl(" (%1 .. %2)").arg(group.vmin_id.v).arg(group.vmax_id.v)*/), _minId(group.vmin_id.v), _maxId(group.vmax_id.v), _count(group.vcount.v), _lnk(new CommentsLink(this)) { } -HistoryGroup::HistoryGroup(History *history, HistoryBlock *block, HistoryItem *newItem, const QDateTime &date) : -HistoryServiceMsg(history, block, clientMsgId(), date, lng_channel_comments_count(lt_count, 1)/* + qsl(" (%1 .. %2)").arg(newItem->id - 1).arg(newItem->id + 1)*/), +HistoryGroup::HistoryGroup(History *history, HistoryItem *newItem, const QDateTime &date) : +HistoryServiceMsg(history, clientMsgId(), date, lng_channel_comments_count(lt_count, 1)/* + qsl(" (%1 .. %2)").arg(newItem->id - 1).arg(newItem->id + 1)*/), _minId(newItem->id - 1), _maxId(newItem->id + 1), _count(1), _lnk(new CommentsLink(this)) { } @@ -7970,8 +7848,8 @@ void HistoryGroup::updateText() { setServiceText(lng_channel_comments_count(lt_count, _count)/* + qsl(" (%1 .. %2)").arg(_minId).arg(_maxId)*/); } -HistoryCollapse::HistoryCollapse(History *history, HistoryBlock *block, MsgId wasMinId, const QDateTime &date) : -HistoryServiceMsg(history, block, clientMsgId(), date, qsl("-")), +HistoryCollapse::HistoryCollapse(History *history, MsgId wasMinId, const QDateTime &date) : +HistoryServiceMsg(history, clientMsgId(), date, qsl("-")), _wasMinId(wasMinId) { } @@ -7983,8 +7861,8 @@ void HistoryCollapse::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3 state = HistoryDefaultCursorState; } -HistoryJoined::HistoryJoined(History *history, HistoryBlock *block, const QDateTime &inviteDate, UserData *inviter, int32 flags) : -HistoryServiceMsg(history, block, clientMsgId(), inviteDate, QString(), flags) { +HistoryJoined::HistoryJoined(History *history, const QDateTime &inviteDate, UserData *inviter, int32 flags) : +HistoryServiceMsg(history, clientMsgId(), inviteDate, QString(), flags) { textstyleSet(&st::serviceTextStyle); if (peerToUser(inviter->id) == MTP::authedId()) { _text.setText(st::msgServiceFont, lang(history->isMegagroup() ? lng_action_you_joined_group : lng_action_you_joined), _historySrvOptions); @@ -7994,40 +7872,3 @@ HistoryServiceMsg(history, block, clientMsgId(), inviteDate, QString(), flags) { } textstyleRestore(); } - -HistoryUnreadBar::HistoryUnreadBar(History *history, HistoryBlock *block, int32 count, const QDateTime &date) : HistoryItem(history, block, clientMsgId(), 0, date, 0), freezed(false) { - setCount(count); - initDimensions(); -} - -void HistoryUnreadBar::initDimensions() { - _maxw = st::msgPadding.left() + st::msgPadding.right() + 1; - _minh = st::unreadBarHeight; -} - -void HistoryUnreadBar::setCount(int32 count) { - if (!count) freezed = true; - if (freezed) return; - text = lng_unread_bar(lt_count, count); -} - -void HistoryUnreadBar::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const { - p.fillRect(0, st::lineWidth, _history->width, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG->b); - p.fillRect(0, st::unreadBarHeight - st::lineWidth, _history->width, st::lineWidth, st::unreadBarBorder->b); - p.setFont(st::unreadBarFont->f); - p.setPen(st::unreadBarColor->p); - p.drawText(QRect(0, 0, _history->width, st::unreadBarHeight - st::lineWidth), text, style::al_center); -} - -int32 HistoryUnreadBar::resize(int32 width) { - _height = st::unreadBarHeight; - return _height; -} - -void HistoryUnreadBar::drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const { -} - -QString HistoryUnreadBar::notificationText() const { - return QString(); -} - diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index e029752e1c..d8697decb7 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -56,7 +56,6 @@ public: } HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type); - // HistoryItem *addToBack(const MTPgeoChatMessage &msg, bool newMsg = true); typedef QMap TypingHistories; // when typing in this history started TypingHistories typing; @@ -208,7 +207,6 @@ struct HistoryEditDraft : public HistoryDraft { class HistoryMedia; class HistoryMessage; -class HistoryUnreadBar; enum AddToOverviewMethod { AddToOverviewNew, // when new message is added to history @@ -244,9 +242,9 @@ public: virtual ~History(); HistoryItem *createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction); - HistoryItem *createItemForwarded(HistoryBlock *block, MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *msg); - HistoryItem *createItemDocument(HistoryBlock *block, MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); - HistoryItem *createItemPhoto(HistoryBlock *block, MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); + HistoryItem *createItemForwarded(MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *msg); + HistoryItem *createItemDocument(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); + HistoryItem *createItemPhoto(MsgId id, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); HistoryItem *addNewService(MsgId msgId, QDateTime date, const QString &text, int32 flags = 0, HistoryMedia *media = 0, bool newMsg = true); HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type); @@ -276,6 +274,7 @@ public: void setMute(bool newMute); void getNextShowFrom(HistoryBlock *block, int32 i); void addUnreadBar(); + void destroyUnreadBar(); void clearNotifications(); bool loadedAtBottom() const; // last message is in the list @@ -347,7 +346,7 @@ public: int32 width, height, msgCount, unreadCount; int32 inboxReadBefore, outboxReadBefore; HistoryItem *showFrom; - HistoryUnreadBar *unreadBar; + HistoryItem *unreadBar; PeerData *peer; bool oldLoaded, newLoaded; @@ -446,7 +445,6 @@ private: friend class HistoryBlock; friend class ChannelHistory; - void createInitialDateBlock(const QDateTime &date); 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); @@ -809,9 +807,12 @@ struct DialogsIndexed { class HistoryBlock { public: - HistoryBlock(History *hist) : y(0), height(0), history(hist) { + HistoryBlock(History *hist) : y(0), height(0), history(hist), _indexInHistory(-1) { } + HistoryBlock(const HistoryBlock &) = delete; + HistoryBlock &operator=(const HistoryBlock &) = delete; + typedef QVector Items; Items items; @@ -825,8 +826,14 @@ public: int32 y, height; History *history; - HistoryBlock(const HistoryBlock &) = delete; - HistoryBlock &operator=(const HistoryBlock &) = delete; + HistoryBlock *previous() const { + return (_indexInHistory > 0) ? history->blocks.at(_indexInHistory - 1) : nullptr; + } + +protected: + + int _indexInHistory; + }; class HistoryElem { @@ -876,8 +883,6 @@ inline bool isImportantChannelMessage(MsgId id, int32 flags) { // client-side im enum HistoryItemType { HistoryItemMsg = 0, - HistoryItemDate, - HistoryItemUnreadBar, HistoryItemGroup, HistoryItemCollapse, HistoryItemJoined @@ -931,11 +936,40 @@ private: }; +// any HistoryItem can have this Interface for +// displaying the day mark above the message +struct HistoryMessageDate : public BasicInterface { + HistoryMessageDate(Interfaces *); + void init(const QDateTime &date); + + QString _text; + int _width; +}; + +// any HistoryItem can have this Interface for +// displaying the unread messages bar above the message +struct HistoryMessageUnreadBar : public BasicInterface { + HistoryMessageUnreadBar(Interfaces *); + void init(int count); + + QString _text; + int _width; + + // if unread bar is freezed the new messages do not + // increment the counter displayed by this bar + // + // it happens when we've opened the conversation and + // we've seen the bar and new messages are marked as read + // as soon as they are added to the chat history + bool _freezed; +}; + class HistoryMedia; class HistoryItem : public HistoryElem, public Interfaces { public: - HistoryItem(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime msgDate, int32 from); + HistoryItem(const HistoryItem &) = delete; + HistoryItem &operator=(const HistoryItem &) = delete; virtual void initDimensions() = 0; virtual int32 resize(int32 width) = 0; // return new height @@ -975,8 +1009,13 @@ public: bool detached() const { return !_block; } - void attach(HistoryBlock *block) { + void attachToBlock(HistoryBlock *block, int index) { + t_assert(_block == nullptr && _indexInBlock < 0); _block = block; + _indexInBlock = index; + } + void setIndexInBlock(int index) { + _indexInBlock = index; } bool out() const { return _flags & MTPDmessage::flag_out; @@ -1064,6 +1103,7 @@ public: virtual bool hasBubble() const { return false; } + virtual void previousItemChanged(); virtual QString selectedText(uint32 selection) const { return qsl("[-]"); @@ -1204,21 +1244,73 @@ public: return author(); } + // count > 0 - creates the unread bar if necessary and + // sets unread messages count if bar is not freezed yet + // count <= 0 - destroys the unread bar + void setUnreadBarCount(int count); + void destroyUnreadBar(); + + // marks the unread bar as freezed so that unread + // messages count will not change for this bar + // when the new messages arrive in this chat history + void setUnreadBarFreezed(); + void clipCallback(ClipReaderNotification notification); virtual ~HistoryItem(); protected: + HistoryItem(History *history, MsgId msgId, int32 flags, QDateTime msgDate, int32 from); + + // to completely create history item we need to + // call a virtual initDimensions() method, + // that can not be done from constructor + void finishCreate(); + PeerData *_from; History *_history; - HistoryBlock *_block; + HistoryBlock *_block = nullptr; + int _indexInBlock = -1; int32 _flags; mutable int32 _authorNameVersion; - HistoryItem(const HistoryItem &) = delete; - HistoryItem &operator=(const HistoryItem &) = delete; + HistoryItem *previous() const { + if (_block && _indexInBlock >= 0) { + if (_indexInBlock > 0) return _block->items.at(_indexInBlock - 1); + if (HistoryBlock *previousBlock = _block->previous()) { + return previousBlock->items.back(); + } + } + return nullptr; + } + + // this should be used only in initDimensions() + // to add required bits to the Interfaces mask + // after that always use Is() + bool displayDate() const { + if (HistoryItem *prev = previous()) { + return prev->date.date().day() != date.date().day(); + } + return true; + } + +}; + +// make all the constructors in HistoryItem children protected +// and wrapped with a static create() call with the same args +// so that history item can not be created directly, without +// a finishCreate() call, which calls a virtual method initDimensions() +template +class HistoryItemInstantiated { +public: + template + static T *_create(Args ... args) { + T *result = new T(args ...); + result->finishCreate(); + return result; + } }; class MessageLink : public ITextLink { @@ -1254,8 +1346,6 @@ private: HistoryItem *_item; }; -HistoryItem *regItem(HistoryItem *item); - class RadialAnimation { public: @@ -1338,10 +1428,10 @@ public: virtual void stopInline(HistoryItem *item) { } - virtual void regItem(HistoryItem *item) { + virtual void attachToItem(HistoryItem *item) { } - virtual void unregItem(HistoryItem *item) { + virtual void detachFromItem(HistoryItem *item) { } virtual void updateFrom(const MTPMessageMedia &media, HistoryItem *parent) { @@ -1495,8 +1585,8 @@ public: void updateFrom(const MTPMessageMedia &media, HistoryItem *parent); - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; bool hasReplyPreview() const { return !_data->thumb->isNull(); @@ -1564,8 +1654,8 @@ public: return _data->uploading(); } - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; bool hasReplyPreview() const { return !_data->thumb->isNull(); @@ -1675,8 +1765,8 @@ public: return _data; } - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; void updateFrom(const MTPMessageMedia &media, HistoryItem *parent); @@ -1720,7 +1810,7 @@ protected: private: - void create(bool caption); + void createInterfaces(bool caption); const HistoryItem *_parent; DocumentData *_data; @@ -1764,8 +1854,8 @@ public: bool playInline(HistoryItem *item); void stopInline(HistoryItem *item); - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; void updateFrom(const MTPMessageMedia &media, HistoryItem *parent); @@ -1839,8 +1929,8 @@ public: return _data; } - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; void updateFrom(const MTPMessageMedia &media, HistoryItem *parent); @@ -1898,8 +1988,8 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; void updateFrom(const MTPMessageMedia &media, HistoryItem *parent); @@ -1974,8 +2064,8 @@ public: if (_attach) _attach->stopInline(item); } - void regItem(HistoryItem *item); - void unregItem(HistoryItem *item); + void attachToItem(HistoryItem *item) override; + void detachFromItem(HistoryItem *item) override; bool hasReplyPreview() const { return (_data->photo && !_data->photo->thumb->isNull()) || (_data->doc && !_data->doc->thumb->isNull()); @@ -2113,19 +2203,29 @@ private: }; -class HistoryMessage : public HistoryItem { +class HistoryMessage : public HistoryItem, private HistoryItemInstantiated { public: - HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg); - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, HistoryMessage *fwd); // local forwarded - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities); // local message - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption); // local document - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption); // local photo + static HistoryMessage *create(History *history, const MTPDmessage &msg) { + return _create(history, msg); + } + static HistoryMessage *create(History *history, MsgId msgId, int32 flags, QDateTime date, int32 from, HistoryMessage *fwd) { + return _create(history, msgId, flags, date, from, fwd); + } + static HistoryMessage *create(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) { + return _create(history, msgId, flags, viaBotId, date, from, msg, entities); + } + static HistoryMessage *create(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { + return _create(history, msgId, flags, viaBotId, date, from, doc, caption); + } + static HistoryMessage *create(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { + return _create(history, msgId, flags, viaBotId, date, from, photo, caption); + } void initTime(); void initMedia(const MTPMessageMedia *media, QString ¤tText); void initMediaFromDocument(DocumentData *doc, const QString &caption); - void initDimensions(); + void initDimensions() override; void fromNameUpdated(int32 width) const; virtual UserData *viaBot() const { @@ -2157,7 +2257,7 @@ public: void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const; void setViewsCount(int32 count, bool reinit = true); void setId(MsgId newId); - void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const; + void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override; virtual void drawMessageText(Painter &p, QRect trect, uint32 selection) const; @@ -2247,7 +2347,14 @@ public: protected: - void create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal = 0, const PeerId &fromIdOriginal = 0, MsgId originalId = 0); + HistoryMessage(History *history, const MTPDmessage &msg); + HistoryMessage(History *history, MsgId msgId, int32 flags, QDateTime date, int32 from, HistoryMessage *fwd); // local forwarded + HistoryMessage(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities); // local message + HistoryMessage(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption); // local document + HistoryMessage(History *history, MsgId msgId, int32 flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption); // local photo + friend class HistoryItemInstantiated; + + void createInterfaces(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal = 0, const PeerId &fromIdOriginal = 0, MsgId originalId = 0); bool displayForwardedFrom() const { if (const HistoryMessageForwarded *fwd = Get()) { @@ -2267,12 +2374,18 @@ protected: }; -class HistoryReply : public HistoryMessage { +class HistoryReply : public HistoryMessage, private HistoryItemInstantiated { public: - HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg); - HistoryReply(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); - HistoryReply(History *history, HistoryBlock *block, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); + static HistoryReply *create(History *history, const MTPDmessage &msg) { + return _create(history, msg); + } + static HistoryReply *create(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) { + return _create(history, msgId, flags, viaBotId, replyTo, date, from, doc, caption); + } + static HistoryReply *create(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) { + return _create(history, msgId, flags, viaBotId, replyTo, date, from, photo, caption); + } void initDimensions() override; @@ -2316,6 +2429,12 @@ public: protected: + HistoryReply(History *history, const MTPDmessage &msg); + HistoryReply(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); + HistoryReply(History *history, MsgId msgId, int32 flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); + using HistoryItemInstantiated::_create; + friend class HistoryItemInstantiated; + bool updateReplyTo(bool force = false); void replyToNameUpdated() const; @@ -2358,11 +2477,15 @@ struct HistoryServicePinned : public BasicInterface { TextLinkPtr lnk; }; -class HistoryServiceMsg : public HistoryItem { +class HistoryServiceMsg : public HistoryItem, private HistoryItemInstantiated { public: - HistoryServiceMsg(History *history, HistoryBlock *block, const MTPDmessageService &msg); - HistoryServiceMsg(History *history, HistoryBlock *block, MsgId msgId, QDateTime date, const QString &msg, int32 flags = 0, HistoryMedia *media = 0, int32 from = 0); + static HistoryServiceMsg *create(History *history, const MTPDmessageService &msg) { + return _create(history, msg); + } + static HistoryServiceMsg *create(History *history, MsgId msgId, QDateTime date, const QString &msg, int32 flags = 0, HistoryMedia *media = 0, int32 from = 0) { + return _create(history, msgId, date, msg, flags, media, from); + } void initDimensions() override; @@ -2421,6 +2544,10 @@ public: protected: + HistoryServiceMsg(History *history, const MTPDmessageService &msg); + HistoryServiceMsg(History *history, MsgId msgId, QDateTime date, const QString &msg, int32 flags = 0, HistoryMedia *media = 0, int32 from = 0); + friend class HistoryItemInstantiated; + void setMessageByAction(const MTPmessageAction &action); bool updatePinned(bool force = false); bool updatePinnedText(const QString *pfrom = nullptr, QString *ptext = nullptr); @@ -2431,33 +2558,16 @@ protected: int32 _textWidth, _textHeight; }; -class HistoryDateMsg : public HistoryServiceMsg { +class HistoryGroup : public HistoryServiceMsg, private HistoryItemInstantiated { public: - HistoryDateMsg(History *history, HistoryBlock *block, const QDate &date); - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const { - lnk = TextLinkPtr(); - state = HistoryDefaultCursorState; + static HistoryGroup *create(History *history, const MTPDmessageGroup &group, const QDateTime &date) { + return _create(history, group, date); } - void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { - symbol = 0xFFFF; - after = false; - upon = false; + static HistoryGroup *create(History *history, HistoryItem *newItem, const QDateTime &date) { + return _create(history, newItem, date); } - void setDate(const QDateTime &date); - QString selectedText(uint32 selection) const { - return QString(); - } - HistoryItemType type() const { - return HistoryItemDate; - } -}; -class HistoryGroup : public HistoryServiceMsg { -public: - - HistoryGroup(History *history, HistoryBlock *block, const MTPDmessageGroup &group, const QDateTime &date); - HistoryGroup(History *history, HistoryBlock *block, HistoryItem *newItem, const QDateTime &date); void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { symbol = 0xFFFF; @@ -2487,6 +2597,13 @@ public: return _maxId; } +protected: + + HistoryGroup(History *history, const MTPDmessageGroup &group, const QDateTime &date); + HistoryGroup(History *history, HistoryItem *newItem, const QDateTime &date); + using HistoryItemInstantiated::_create; + friend class HistoryItemInstantiated; + private: MsgId _minId, _maxId; int32 _count; @@ -2497,10 +2614,13 @@ private: }; -class HistoryCollapse : public HistoryServiceMsg { +class HistoryCollapse : public HistoryServiceMsg, private HistoryItemInstantiated { public: - HistoryCollapse(History *history, HistoryBlock *block, MsgId wasMinId, const QDateTime &date); + static HistoryCollapse *create(History *history, MsgId wasMinId, const QDateTime &date) { + return _create(history, wasMinId, date); + } + void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const; void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { @@ -2518,46 +2638,32 @@ public: return _wasMinId; } +protected: + + HistoryCollapse(History *history, MsgId wasMinId, const QDateTime &date); + using HistoryItemInstantiated::_create; + friend class HistoryItemInstantiated; + private: MsgId _wasMinId; }; -class HistoryJoined : public HistoryServiceMsg { +class HistoryJoined : public HistoryServiceMsg, private HistoryItemInstantiated { public: - HistoryJoined(History *history, HistoryBlock *block, const QDateTime &date, UserData *from, int32 flags); + static HistoryJoined *create(History *history, const QDateTime &date, UserData *from, int32 flags) { + return _create(history, date, from, flags); + } + HistoryItemType type() const { return HistoryItemJoined; } -}; - -HistoryItem *createDayServiceMsg(History *history, HistoryBlock *block, QDateTime date); - -class HistoryUnreadBar : public HistoryItem { -public: - - HistoryUnreadBar(History *history, HistoryBlock *block, int32 count, const QDateTime &date); - - void initDimensions(); - - void setCount(int32 count); - - void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const; - int32 resize(int32 width); - - void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const; - QString notificationText() const; - - QString selectedText(uint32 selection) const { - return QString(); - } - HistoryItemType type() const { - return HistoryItemUnreadBar; - } protected: - QString text; - bool freezed; + HistoryJoined(History *history, const QDateTime &date, UserData *from, int32 flags); + using HistoryItemInstantiated::_create; + friend class HistoryItemInstantiated; + }; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index ecbdfcb6ad..dfede8936e 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -3601,16 +3601,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re _history->lastShowAtMsgId = ShowAtUnreadMsgId; } _history->lastScrollTop = _scroll.scrollTop(); - if (_history->unreadBar) { - _history->unreadBar->destroy(); - } - if (_migrated && _migrated->unreadBar) { - _migrated->unreadBar->destroy(); - } - if (_pinnedBar) { - destroyPinnedBar(); - } - _history = _migrated = 0; + destroyUnreadBar(); + if (_pinnedBar) destroyPinnedBar(); + _history = _migrated = nullptr; updateBotKeyboard(); } @@ -4132,12 +4125,17 @@ void HistoryWidget::updateMouseTracking() { setMouseTracking(trackMouse); } +void HistoryWidget::destroyUnreadBar() { + if (_history) _history->destroyUnreadBar(); + if (_migrated) _migrated->destroyUnreadBar(); +} + void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) { if (App::wnd()->historyIsActive()) { if (_history == history) { historyWasRead(); if (_scroll.scrollTop() + 1 > _scroll.scrollTopMax()) { - if (history->unreadBar) history->unreadBar->destroy(); + destroyUnreadBar(); } } else { App::wnd()->notifySchedule(history, item); @@ -4146,8 +4144,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) { } else { if (_history == history) { if (_scroll.scrollTop() + 1 > _scroll.scrollTopMax()) { - if (history->unreadBar) history->unreadBar->destroy(); - if (_migrated && _migrated->unreadBar) _migrated->unreadBar->destroy(); + destroyUnreadBar(); } } App::wnd()->notifySchedule(history, item); @@ -4332,12 +4329,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages void HistoryWidget::historyLoaded() { countHistoryShowFrom(); - if (_history->unreadBar) { - _history->unreadBar->destroy(); - } - if (_migrated && _migrated->unreadBar) { - _migrated->unreadBar->destroy(); - } + destroyUnreadBar(); doneShow(); } diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 1ee9fc014b..cc94d93a3a 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -754,6 +754,9 @@ private: void updateMouseTracking(); + // destroys _history and _migrated unread bars + void destroyUnreadBar(); + mtpRequestId _saveEditMsgRequestId; void saveEditMsg(); void saveEditMsgDone(History *history, const MTPUpdates &updates, mtpRequestId req); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 5c02a99e4b..5681ca6854 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1685,9 +1685,9 @@ void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &re void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) { if (!MTP::authedId()) return; if (peer->isChannel()) { - _readRequests.insert(peer, qMakePair(MTP::send(MTPchannels_ReadHistory(peer->asChannel()->inputChannel, MTP_int(upTo)), rpcDone(&MainWidget::channelWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo)); +// _readRequests.insert(peer, qMakePair(MTP::send(MTPchannels_ReadHistory(peer->asChannel()->inputChannel, MTP_int(upTo)), rpcDone(&MainWidget::channelWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo)); } else { - _readRequests.insert(peer, qMakePair(MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo)), rpcDone(&MainWidget::historyWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo)); +// _readRequests.insert(peer, qMakePair(MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo)), rpcDone(&MainWidget::historyWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo)); } } diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 9adbd6b08a..70c9a75588 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -533,21 +533,21 @@ inline void destroyImplementation(I *&ptr) { class Interfaces; typedef void(*InterfaceConstruct)(void *location, Interfaces *interfaces); typedef void(*InterfaceDestruct)(void *location); -typedef void(*InterfaceAssign)(void *location, void *waslocation); +typedef void(*InterfaceMove)(void *location, void *waslocation); struct InterfaceWrapStruct { InterfaceWrapStruct() : Size(0), Construct(0), Destruct(0) { } - InterfaceWrapStruct(int size, InterfaceConstruct construct, InterfaceDestruct destruct, InterfaceAssign assign) + InterfaceWrapStruct(int size, InterfaceConstruct construct, InterfaceDestruct destruct, InterfaceMove move) : Size(size) , Construct(construct) , Destruct(destruct) - , Assign(assign) { + , Move(move) { } int Size; InterfaceConstruct Construct; InterfaceDestruct Destruct; - InterfaceAssign Assign; + InterfaceMove Move; }; template @@ -564,8 +564,8 @@ struct InterfaceWrapTemplate { static void Destruct(void *location) { ((Type*)location)->~Type(); } - static void Assign(void *location, void *waslocation) { - *((Type*)location) = *((Type*)waslocation); + static void Move(void *location, void *waslocation) { + *(Type*)location = *(Type*)waslocation; } }; @@ -585,7 +585,7 @@ public: if (InterfaceIndexLast.testAndSetOrdered(last, last + 1)) { t_assert(last < 64); if (_index.testAndSetOrdered(0, last + 1)) { - InterfaceWraps[last] = InterfaceWrapStruct(InterfaceWrapTemplate::Size, InterfaceWrapTemplate::Construct, InterfaceWrapTemplate::Destruct, InterfaceWrapTemplate::Assign); + InterfaceWraps[last] = InterfaceWrapStruct(InterfaceWrapTemplate::Size, InterfaceWrapTemplate::Construct, InterfaceWrapTemplate::Destruct, InterfaceWrapTemplate::Move); } break; } @@ -634,9 +634,15 @@ public: int size, last; int offsets[64]; - bool equals(const uint64 &mask) const { + bool equals(uint64 mask) const { return _mask == mask; } + uint64 maskadd(uint64 mask) const { + return _mask | mask; + } + uint64 maskremove(uint64 mask) const { + return _mask & (~mask); + } private: uint64 _mask; @@ -682,18 +688,23 @@ public: if (!_meta()->equals(mask)) { Interfaces tmp(mask); tmp.swap(*this); - if (_data != zerodata() && tmp._data != zerodata()) { const InterfacesMetadata *meta = _meta(), *wasmeta = tmp._meta(); for (int i = 0; i < meta->last; ++i) { int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i]; if (offset >= 0 && wasoffset >= 0) { - InterfaceWraps[i].Assign(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset)); + InterfaceWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset)); } } } } } + void AddInterfaces(uint64 mask = 0) { + UpdateInterfaces(_meta()->maskadd(mask)); + } + void RemoveInterfaces(uint64 mask = 0) { + UpdateInterfaces(_meta()->maskremove(mask)); + } ~Interfaces() { if (_data != zerodata()) { const InterfacesMetadata *meta = _meta();