diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 07b2e8ce46..c8bacef0bc 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -586,6 +586,7 @@ HistoryItem *History::addNewToLastBlock( applyMessageChanges(item, msg); } const auto result = addNewItem(item, newUnreadMessage); + checkForLoadedAtTop(result); if (type == NewMessageLast) { // When we add just one last item, like we do while loading dialogs, // we want to remove a single added grouped media, otherwise it will @@ -599,6 +600,22 @@ HistoryItem *History::addNewToLastBlock( return result; } +void History::checkForLoadedAtTop(not_null added) { + if (peer->isChat()) { + if (added->isGroupEssential() && !added->isGroupMigrate()) { + // We added the first message about group creation. + _loadedAtTop = true; + addEdgesToSharedMedia(); + } + } else if (peer->isChannel()) { + if (added->id == 1) { + _loadedAtTop = true; + checkJoinedMessage(); + addEdgesToSharedMedia(); + } + } +} + HistoryItem *History::addToHistory(const MTPMessage &msg) { const auto detachExistingItem = false; return createItem(msg, detachExistingItem); @@ -2130,7 +2147,7 @@ auto History::computeChatListMessageFromLast() const // about migration in the chats list and display the last // non-migration message from the original legacy group. const auto last = lastMessage(); - if (!last || !last->isGroupEssential() || !last->isEmpty()) { + if (!last || !last->isGroupMigrate()) { return _lastMessage; } if (const auto chat = peer->asChat()) { @@ -2216,7 +2233,7 @@ void History::setFakeChatListMessageFrom(const MTPmessages_Messages &data) { } }); const auto last = lastMessage(); - if (!last || !last->isGroupEssential() || !last->isEmpty()) { + if (!last || !last->isGroupMigrate()) { // Last message is good enough. return; } @@ -2239,7 +2256,7 @@ void History::setFakeChatListMessageFrom(const MTPmessages_Messages &data) { return; } const auto item = owner().addNewMessage(*other, NewMessageExisting); - if (!item || (item->isGroupEssential() && item->isEmpty())) { + if (!item || item->isGroupMigrate()) { // Not better than the last one. return; } @@ -2732,19 +2749,37 @@ bool History::isEmpty() const { } bool History::isDisplayedEmpty() const { + if (!loadedAtTop() || !loadedAtBottom()) { + return false; + } const auto first = findFirstNonEmpty(); if (!first) { return true; - } else if (!first->data()->isGroupEssential()) { - return false; - } else if (const auto chat = peer->asChat()) { - // For legacy chats we want to show the chat with only first - // message about you creating the group as an empty chat with - // a nice information about the group features. - return chat->amCreator() && (findLastNonEmpty() == first); - } else { + } + const auto chat = peer->asChat(); + if (!chat || !chat->amCreator()) { return false; } + + // For legacy chats we want to show the chat with only + // messages about you creating the group and maybe about you + // changing the group photo as an empty chat with + // a nice information about the group features. + if (nonEmptyCountMoreThan(2)) { + return false; + } + const auto isChangePhoto = [](not_null item) { + if (const auto media = item->media()) { + return (media->photo() != nullptr) && !item->toHistoryMessage(); + } + return false; + }; + const auto last = findLastNonEmpty(); + if (first == last) { + return first->data()->isGroupEssential() + || isChangePhoto(first->data()); + } + return first->data()->isGroupEssential() && isChangePhoto(last->data()); } auto History::findFirstNonEmpty() const -> Element* { @@ -2769,6 +2804,21 @@ auto History::findLastNonEmpty() const -> Element* { return nullptr; } +bool History::nonEmptyCountMoreThan(int count) const { + Expects(count >= 0); + + for (const auto &block : blocks) { + for (const auto &element : block->messages) { + if (!element->data()->isEmpty()) { + if (!count--) { + return true; + } + } + } + } + return false; +} + bool History::hasOrphanMediaGroupPart() const { if (loadedAtTop() || !loadedAtBottom()) { return false; diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 7eedaede2b..e84cfe5925 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -396,6 +396,7 @@ private: return _buildingFrontBlock != nullptr; } + void checkForLoadedAtTop(not_null added); void mainViewRemoved( not_null block, not_null view); @@ -439,6 +440,7 @@ private: HistoryItem *lastAvailableMessage() const; void getNextFirstUnreadMessage(); + bool nonEmptyCountMoreThan(int count) const; // Creates if necessary a new block for adding item. // Depending on isBuildingFrontBlock() gets front or back block. diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 13d522d2a1..01aea3b829 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -543,7 +543,8 @@ void HistoryInner::paintEvent(QPaintEvent *e) { auto clip = e->rect(); auto ms = getms(); - bool historyDisplayedEmpty = (_history->isDisplayedEmpty() && (!_migrated || _migrated->isDisplayedEmpty())); + const auto historyDisplayedEmpty = _history->isDisplayedEmpty() + && (!_migrated || _migrated->isDisplayedEmpty()); bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty; if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) { @@ -561,6 +562,8 @@ void HistoryInner::paintEvent(QPaintEvent *e) { } } else if (historyDisplayedEmpty) { paintEmpty(p, width(), height()); + } else { + _emptyPainter = nullptr; } if (!noHistoryDisplayed) { auto readMentions = base::flat_set>(); diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 17c5874425..154f0f385d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -55,7 +55,6 @@ public: void messagesReceivedDown(PeerData *peer, const QVector &messages); TextWithEntities getSelectedText() const; - void paintEmpty(Painter &p, int width, int height); void touchScrollUpdated(const QPoint &screenPos); @@ -201,6 +200,8 @@ private: std::unique_ptr prepareDrag(); void performDrag(); + void paintEmpty(Painter &p, int width, int height); + QPoint mapPointToItem(QPoint p, const Element *view) const; QPoint mapPointToItem(QPoint p, const HistoryItem *item) const; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index edfa2026e6..de62261904 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -462,7 +462,7 @@ bool HistoryItem::canDelete() const { } auto channel = _history->peer->asChannel(); if (!channel) { - return !(_flags & MTPDmessage_ClientFlag::f_is_group_essential); + return !isGroupMigrate(); } if (id == 1) { diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 79dd524793..5710d1409e 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -137,6 +137,9 @@ public: bool isGroupEssential() const { return _flags & MTPDmessage_ClientFlag::f_is_group_essential; } + bool isGroupMigrate() const { + return isGroupEssential() && isEmpty(); + } bool hasViews() const { return _flags & MTPDmessage::Flag::f_views; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 958de686cd..4c1c29b356 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6554,13 +6554,6 @@ void HistoryWidget::paintEvent(QPaintEvent *e) { if (_pinnedBar && !_pinnedBar->cancel->isHidden()) { drawPinnedBar(p); } - if (_scroll->isHidden() && _history) { - p.setClipRect(_scroll->geometry()); - _list->paintEmpty( - p, - width(), - height() - _field->height() - 2 * st::historySendPadding); - } } else { const auto w = st::msgServiceFont->width(lang(lng_willbe_history)) + st::msgPadding.left() diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.cpp b/Telegram/SourceFiles/history/view/history_view_service_message.cpp index aebc919945..698a794a10 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_service_message.cpp @@ -557,7 +557,7 @@ void EmptyPainter::fillAboutGroup() { text.setText( st::serviceTextStyle, content, - Ui::ItemTextServiceOptions()); + Ui::NameTextOptions()); }; setText(_header, lang(lng_group_about_header)); setText(_text, lang(lng_group_about_text)); @@ -603,7 +603,7 @@ void EmptyPainter::paint(Painter &p, int width, int height) { + st::historyGroupAboutSkip * int(_phrases.size() - 1) + padding.bottom(); const auto bubbleLeft = (width - bubbleWidth) / 2; - const auto bubbleTop = (height - bubbleHeight) / 3; + const auto bubbleTop = (height - bubbleHeight) / 2; ServiceMessagePainter::paintBubble( p,