diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index c427185d90..136243a7ae 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1423,6 +1423,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_feed_ungroup" = "Ungroup from feed"; "lng_feed_channel_added" = "Channel added to your feed."; "lng_feed_channel_removed" = "Channel removed from your feed."; +"lng_feed_no_messages" = "No messages in this feed yet"; "lng_info_feed_title" = "Feed Info"; diff --git a/Telegram/SourceFiles/data/data_messages.cpp b/Telegram/SourceFiles/data/data_messages.cpp index f3ab4a6fd3..4603894693 100644 --- a/Telegram/SourceFiles/data/data_messages.cpp +++ b/Telegram/SourceFiles/data/data_messages.cpp @@ -332,6 +332,7 @@ bool MessagesSliceBuilder::removeFromChannel(ChannelId channelId) { } } _skippedBefore = _skippedAfter = base::none; + checkInsufficient(); return true; } diff --git a/Telegram/SourceFiles/data/data_sparse_ids.cpp b/Telegram/SourceFiles/data/data_sparse_ids.cpp index 774f9d28d2..bf55cb4cb1 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.cpp +++ b/Telegram/SourceFiles/data/data_sparse_ids.cpp @@ -237,6 +237,9 @@ bool SparseIdsSliceBuilder::removeOne(MsgId messageId) { changed = true; } } + if (changed) { + checkInsufficient(); + } return changed; } diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.cpp b/Telegram/SourceFiles/history/feed/history_feed_section.cpp index d8bf5b0755..a8c91d2e52 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.cpp +++ b/Telegram/SourceFiles/history/feed/history_feed_section.cpp @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_message.h" #include "history/view/history_view_service_message.h" #include "history/history_item.h" +#include "history/history_service.h" +#include "history/history_inner_widget.h" #include "core/event_filter.h" #include "lang/lang_keys.h" #include "ui/widgets/buttons.h" @@ -380,7 +382,34 @@ base::optional Widget::listUnreadBarView( return base::make_optional(int(minimal - begin(elements))); } +void Widget::validateEmptyTextItem() { + if (!_inner->isEmpty()) { + _emptyTextView = nullptr; + _emptyTextItem = nullptr; + update(); + return; + } else if (_emptyTextItem) { + return; + } + const auto channels = _feed->channels(); + if (channels.empty()) { + return; + } + const auto history = channels[0]; + _emptyTextItem.reset(new HistoryService( + history, + clientMsgId(), + unixtime(), + { lang(lng_feed_no_messages) })); + _emptyTextView = _emptyTextItem->createView( + HistoryInner::ElementDelegate()); + updateControlsGeometry(); + update(); +} + void Widget::listContentRefreshed() { + validateEmptyTextItem(); + if (!_nextAnimatedScrollPosition) { return; } @@ -457,6 +486,10 @@ void Widget::updateControlsGeometry() { contentWidth, _showNext->height()); _showNext->setGeometry(fullWidthButtonRect); + + if (_emptyTextView) { + _emptyTextView->resizeGetHeight(width()); + } } void Widget::paintEvent(QPaintEvent *e) { @@ -475,6 +508,22 @@ void Widget::paintEvent(QPaintEvent *e) { _scrollDownShown.step(ms); SectionWidget::PaintBackground(this, e); + + if (_emptyTextView) { + Painter p(this); + + const auto clip = e->rect(); + const auto left = 0; + const auto top = (height() + - _showNext->height() + - _emptyTextView->height()) / 2; + p.translate(left, top); + _emptyTextView->draw( + p, + clip.translated(-left, -top), + TextSelection(), + getms()); + } } void Widget::onScroll() { diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.h b/Telegram/SourceFiles/history/feed/history_feed_section.h index 08ebe68499..ea119c9e6f 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.h +++ b/Telegram/SourceFiles/history/feed/history_feed_section.h @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/section_widget.h" #include "window/section_memento.h" #include "data/data_feed.h" +#include "history/history_item.h" +#include "history/admin_log/history_admin_log_item.h" namespace Ui { class ScrollArea; @@ -103,6 +105,7 @@ private: void restoreState(not_null memento); void showAtPosition(Data::MessagePosition position); bool showAtPositionNow(Data::MessagePosition position); + void validateEmptyTextItem(); void setupScrollDownButton(); void scrollDownClicked(); @@ -122,6 +125,8 @@ private: object_ptr _showNext; bool _skipScrollEvent = false; bool _undefinedAroundPosition = false; + std::unique_ptr _emptyTextItem; + std::unique_ptr _emptyTextView; base::optional _nextAnimatedScrollPosition; int _nextAnimatedScrollDelta = 0; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index ef20a27cda..71014e4e62 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -71,6 +71,12 @@ not_null CreateUnsupportedMessage( } // namespace +void HistoryItem::HistoryItem::Destroyer::operator()(HistoryItem *value) { + if (value) { + value->destroy(); + } +} + HistoryItem::HistoryItem( not_null history, MsgId id, diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 177096626d..e697ead2a4 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -60,6 +60,11 @@ public: not_null history, const MTPMessage &message); + struct Destroyer { + void operator()(HistoryItem *value); + + }; + virtual void dependencyItemRemoved(HistoryItem *dependency) { } virtual bool updateDependencyItem() { diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index f911b8f047..d6a3ceaa16 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6690,14 +6690,27 @@ void HistoryWidget::paintEvent(QPaintEvent *e) { HistoryView::paintEmpty(p, width(), height() - _field->height() - 2 * st::historySendPadding); } } else { - style::font font(st::msgServiceFont); - int32 w = font->width(lang(lng_willbe_history)) + st::msgPadding.left() + st::msgPadding.right(), h = font->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + 2; - QRect tr((width() - w) / 2, (height() - _field->height() - 2 * st::historySendPadding - h) / 2, w, h); + const auto w = st::msgServiceFont->width(lang(lng_willbe_history)) + + st::msgPadding.left() + + st::msgPadding.right(); + const auto h = st::msgServiceFont->height + + st::msgServicePadding.top() + + st::msgServicePadding.bottom(); + const auto tr = QRect( + (width() - w) / 2, + st::msgServiceMargin.top() + (height() + - _field->height() + - 2 * st::historySendPadding + - h + - st::msgServiceMargin.top() + - st::msgServiceMargin.bottom()) / 2, + w, + h); HistoryView::ServiceMessagePainter::paintBubble(p, tr.x(), tr.y(), tr.width(), tr.height()); p.setPen(st::msgServiceFg); - p.setFont(font->f); - p.drawText(tr.left() + st::msgPadding.left(), tr.top() + st::msgServicePadding.top() + 1 + font->ascent, lang(lng_willbe_history)); + p.setFont(st::msgServiceFont->f); + p.drawTextLeft(tr.left() + st::msgPadding.left(), tr.top() + st::msgServicePadding.top(), width(), lang(lng_willbe_history)); } } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 3effa75fea..ebe2e1fd41 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -463,7 +463,11 @@ not_null ListWidget::enforceViewForItem( void ListWidget::updateAroundPositionFromRows() { _aroundIndex = findNearestItem(_aroundPosition); if (_aroundIndex >= 0) { - _aroundPosition = _items[_aroundIndex]->data()->position(); + const auto newPosition = _items[_aroundIndex]->data()->position(); + if (_aroundPosition != newPosition) { + _aroundPosition = newPosition; + crl::on_main(this, [=] { refreshViewer(); }); + } } } @@ -923,6 +927,10 @@ bool ListWidget::loadedAtBottom() const { return _slice.skippedAfter && (*_slice.skippedAfter == 0); } +bool ListWidget::isEmpty() const { + return loadedAtTop() && loadedAtBottom() && (_itemsHeight == 0); +} + int ListWidget::itemMinimalHeight() const { return st::msgMarginTopAttached + st::msgPhotoSize @@ -2235,6 +2243,7 @@ void ListWidget::refreshAttachmentsFromTill(int from, int till) { Expects(from >= 0 && from <= till && till <= int(_items.size())); if (from == till) { + updateSize(); return; } auto view = _items[from].get(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 36682c249c..b9a908e8af 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -159,6 +159,7 @@ public: bool loadedAtTop() const; bool loadedAtBottomKnown() const; bool loadedAtBottom() const; + bool isEmpty() const; // AbstractTooltipShower interface QString tooltipText() const override; diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index affd69847d..98c045e453 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -860,10 +860,11 @@ void FeedUserpicButton::checkParts() { bool FeedUserpicButton::partsAreValid() const { const auto &channels = _feed->channels(); - if (std::min(int(channels.size()), 4) != _parts.size()) { + const auto count = std::min(int(channels.size()), 4); + if (count != _parts.size()) { return false; } - for (auto i = 0; i != 4; ++i) { + for (auto i = 0; i != count; ++i) { if (channels[i]->peer != _parts[i].channel) { return false; }