From ef2aa051978bf7d17d5a15fb3a70cad3c96ccc8d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 2 May 2024 19:39:19 +0400 Subject: [PATCH] Allow HistoryView::ListWidget without SessionController. --- .../history/view/history_view_list_widget.cpp | 314 ++++++++++++------ .../history/view/history_view_list_widget.h | 73 +++- .../view/history_view_pinned_section.cpp | 3 +- .../view/history_view_pinned_section.h | 2 +- .../view/history_view_replies_section.cpp | 3 +- .../view/history_view_replies_section.h | 2 +- .../view/history_view_scheduled_section.cpp | 3 +- .../view/history_view_scheduled_section.h | 2 +- .../view/history_view_sublist_section.cpp | 3 +- .../view/history_view_sublist_section.h | 2 +- .../business/settings_shortcut_messages.cpp | 10 +- Telegram/SourceFiles/ui/chat/chat_style.h | 8 + .../window/window_session_controller.cpp | 2 +- .../window/window_session_controller.h | 10 +- 14 files changed, 312 insertions(+), 125 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index e31188605..538606339 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -90,6 +90,95 @@ constexpr auto kClearUserpicsAfter = 50; } // namespace +const crl::time ListWidget::kItemRevealDuration = crl::time(150); + +WindowListDelegate::WindowListDelegate( + not_null window) +: _window(window) { +} + +not_null WindowListDelegate::listWindow() { + return _window; +} + +not_null WindowListDelegate::listChatStyle() { + return _window->chatStyle(); +} + +rpl::producer WindowListDelegate::listChatWideValue() { + return _window->adaptive().chatWideValue(); +} + +auto WindowListDelegate::listMakeReactionsManager( + QWidget *wheelEventsTarget, + Fn update) +-> std::unique_ptr { + return std::make_unique( + wheelEventsTarget, + std::move(update), + _window->cachedReactionIconFactory().createMethod()); +} + +void WindowListDelegate::listVisibleAreaUpdated() { + _window->floatPlayerAreaUpdated(); +} + +std::shared_ptr WindowListDelegate::listUiShow() { + return _window->uiShow(); +} + +void WindowListDelegate::listShowPollResults( + not_null poll, + FullMsgId context) { + _window->showPollResults(poll, context); +} + +void WindowListDelegate::listCancelUploadLayer(not_null item) { + _window->cancelUploadLayer(item); +} + +bool WindowListDelegate::listAnimationsPaused() { + return _window->isGifPausedAtLeastFor(Window::GifPauseReason::Any); +} + +auto WindowListDelegate::listSendingAnimation() +-> Ui::MessageSendingAnimationController * { + return &_window->sendingAnimation(); +} + +Ui::ChatPaintContext WindowListDelegate::listPreparePaintContext( + Ui::ChatPaintContextArgs &&args) { + return _window->preparePaintContext(std::move(args)); +} + +bool WindowListDelegate::listMarkingContentRead() { + return _window->widget()->markingAsRead(); +} + +bool WindowListDelegate::listIgnorePaintEvent(QWidget *w, QPaintEvent *e) { + return _window->contentOverlapped(w, e); +} + +bool WindowListDelegate::listShowReactPremiumError( + not_null item, + const Data::ReactionId &id) { + return Window::ShowReactPremiumError(_window, item, id); +} + +void WindowListDelegate::listWindowSetInnerFocus() { + _window->widget()->setInnerFocus(); +} + +bool WindowListDelegate::listAllowsDragForward() { + return _window->adaptive().isOneColumn(); +} + +void WindowListDelegate::listLaunchDrag( + std::unique_ptr data, + Fn finished) { + _window->widget()->launchDrag(std::move(data), std::move(finished)); +} + ListWidget::MouseState::MouseState() : pointState(PointState::Outside) { } @@ -104,8 +193,6 @@ ListWidget::MouseState::MouseState( , pointState(pointState) { } -const crl::time ListWidget::kItemRevealDuration = crl::time(150); - template void ListWidget::enumerateItems(Method method) { constexpr auto TopToBottom = (direction == EnumItemsDirection::TopToBottom); @@ -283,31 +370,29 @@ void ListWidget::enumerateDates(Method method) { ListWidget::ListWidget( QWidget *parent, - not_null controller, + not_null session, not_null delegate) : RpWidget(parent) , _delegate(delegate) -, _controller(controller) +, _session(session) , _emojiInteractions(std::make_unique( - &controller->session(), + session, [=](not_null view) { return itemTop(view); })) , _context(_delegate->listContext()) , _itemAverageHeight(itemMinimalHeight()) , _pathGradient( MakePathShiftGradient( - controller->chatStyle(), + _delegate->listChatStyle(), [=] { update(); })) -, _reactionsManager( - std::make_unique( - this, - [=](QRect updated) { update(updated); }, - controller->cachedReactionIconFactory().createMethod())) +, _reactionsManager(_delegate->listMakeReactionsManager( + this, + [=](QRect updated) { update(updated); })) , _translateTracker(MaybeTranslateTracker(_delegate->listTranslateHistory())) , _scrollDateCheck([this] { scrollDateCheck(); }) , _applyUpdatedScrollState([this] { applyUpdatedScrollState(); }) , _selectEnabled(_delegate->listAllowsMultiSelect()) , _highlighter( - &session().data(), + &_session->data(), [=](const HistoryItem *item) { return viewForItem(item); }, [=](const Element *view) { repaintItem(view); }) , _touchSelectTimer([=] { onTouchSelect(); }) @@ -315,25 +400,25 @@ ListWidget::ListWidget( setAttribute(Qt::WA_AcceptTouchEvents); setMouseTracking(true); _scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); }); - session().data().viewRepaintRequest( + _session->data().viewRepaintRequest( ) | rpl::start_with_next([this](auto view) { if (view->delegate() == this) { repaintItem(view); } }, lifetime()); - session().data().viewResizeRequest( + _session->data().viewResizeRequest( ) | rpl::start_with_next([this](auto view) { if (view->delegate() == this) { resizeItem(view); } }, lifetime()); - session().data().itemViewRefreshRequest( + _session->data().itemViewRefreshRequest( ) | rpl::start_with_next([this](auto item) { if (const auto view = viewForItem(item)) { refreshItem(view); } }, lifetime()); - session().data().viewLayoutChanged( + _session->data().viewLayoutChanged( ) | rpl::start_with_next([this](auto view) { if (view->delegate() == this) { if (view->isUnderCursor()) { @@ -341,37 +426,37 @@ ListWidget::ListWidget( } } }, lifetime()); - session().data().itemDataChanges( + _session->data().itemDataChanges( ) | rpl::start_with_next([=](not_null item) { if (const auto view = viewForItem(item)) { view->itemDataChanged(); } }, lifetime()); - session().downloaderTaskFinished( + _session->downloaderTaskFinished( ) | rpl::start_with_next([=] { update(); }, lifetime()); - session().data().peerDecorationsUpdated( + _session->data().peerDecorationsUpdated( ) | rpl::start_with_next([=] { update(); }, lifetime()); - session().data().itemRemoved( + _session->data().itemRemoved( ) | rpl::start_with_next([=](not_null item) { itemRemoved(item); }, lifetime()); using MessageUpdateFlag = Data::MessageUpdate::Flag; - session().changes().realtimeMessageUpdates( + _session->changes().realtimeMessageUpdates( MessageUpdateFlag::NewUnreadReaction ) | rpl::start_with_next([=](const Data::MessageUpdate &update) { maybeMarkReactionsRead(update.item); }, lifetime()); if (const auto history = _delegate->listTranslateHistory()) { - session().changes().historyUpdates( + _session->changes().historyUpdates( history, Data::HistoryUpdate::Flag::TranslatedTo ) | rpl::start_with_next([=] { @@ -379,7 +464,7 @@ ListWidget::ListWidget( }, lifetime()); } - session().data().itemVisibilityQueries( + _session->data().itemVisibilityQueries( ) | rpl::start_with_next([=]( const Data::Session::ItemVisibilityQuery &query) { if (const auto view = viewForItem(query.item)) { @@ -392,25 +477,27 @@ ListWidget::ListWidget( } }, lifetime()); - _reactionsManager->chosen( - ) | rpl::start_with_next([=](ChosenReaction reaction) { - _reactionsManager->updateButton({}); - reactionChosen(reaction); - }, lifetime()); - - Reactions::SetupManagerList( - _reactionsManager.get(), - _reactionsItem.value()); - - Core::App().settings().cornerReactionValue( - ) | rpl::start_with_next([=](bool value) { - _useCornerReaction = value; - if (!value) { + if (_reactionsManager) { + _reactionsManager->chosen( + ) | rpl::start_with_next([=](ChosenReaction reaction) { _reactionsManager->updateButton({}); - } - }, lifetime()); + reactionChosen(reaction); + }, lifetime()); - controller->adaptive().chatWideValue( + Reactions::SetupManagerList( + _reactionsManager.get(), + _reactionsItem.value()); + + Core::App().settings().cornerReactionValue( + ) | rpl::start_with_next([=](bool value) { + _useCornerReaction = value; + if (!value) { + _reactionsManager->updateButton({}); + } + }, lifetime()); + } + + _delegate->listChatWideValue( ) | rpl::start_with_next([=](bool wide) { _isChatWide = wide; }, lifetime()); @@ -427,11 +514,11 @@ ListWidget::ListWidget( } Main::Session &ListWidget::session() const { - return _controller->session(); + return *_session; } not_null ListWidget::controller() const { - return _controller; + return _delegate->listWindow(); } not_null ListWidget::delegate() const { @@ -1006,7 +1093,7 @@ void ListWidget::visibleTopBottomUpdated( } else { scrollDateHideByTimer(); } - _controller->floatPlayerAreaUpdated(); + _delegate->listVisibleAreaUpdated(); session().data().itemVisibilitiesUpdated(); _applyUpdatedScrollState.call(); @@ -1439,7 +1526,7 @@ bool ListWidget::showCopyRestriction(HistoryItem *item) { if (type == CopyRestrictionType::None) { return false; } - _controller->showToast((type == CopyRestrictionType::Channel) + _delegate->listUiShow()->showToast((type == CopyRestrictionType::Channel) ? tr::lng_error_nocopy_channel(tr::now) : tr::lng_error_nocopy_group(tr::now)); return true; @@ -1450,7 +1537,7 @@ bool ListWidget::showCopyMediaRestriction(not_null item) { if (type == CopyRestrictionType::None) { return false; } - _controller->showToast((type == CopyRestrictionType::Channel) + _delegate->listUiShow()->showToast((type == CopyRestrictionType::Channel) ? tr::lng_error_nocopy_channel(tr::now) : tr::lng_error_nocopy_group(tr::now)); return true; @@ -1676,7 +1763,7 @@ void ListWidget::elementStartStickerLoop(not_null view) { void ListWidget::elementShowPollResults( not_null poll, FullMsgId context) { - _controller->showPollResults(poll, context); + _delegate->listShowPollResults(poll, context); } void ListWidget::elementOpenPhoto( @@ -1694,7 +1781,7 @@ void ListWidget::elementOpenDocument( void ListWidget::elementCancelUpload(const FullMsgId &context) { if (const auto item = session().data().message(context)) { - _controller->cancelUploadLayer(item); + _delegate->listCancelUploadLayer(item); } } @@ -1706,7 +1793,7 @@ void ListWidget::elementShowTooltip( } bool ListWidget::elementAnimationsPaused() { - return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); + return _delegate->listAnimationsPaused(); } bool ListWidget::elementHideReply(not_null view) { @@ -1838,8 +1925,8 @@ void ListWidget::startItemRevealAnimations() { void ListWidget::startMessageSendingAnimation( not_null item) { - auto &sendingAnimation = controller()->sendingAnimation(); - if (!sendingAnimation.checkExpectedType(item)) { + const auto sendingAnimation = _delegate->listSendingAnimation(); + if (!sendingAnimation || !sendingAnimation->checkExpectedType(item)) { return; } @@ -1855,7 +1942,7 @@ void ListWidget::startMessageSendingAnimation( return mapToGlobal(QPoint(0, itemTop(view) - additional)); }); - sendingAnimation.startAnimation({ + sendingAnimation->startAnimation({ .globalEndTopLeft = std::move(globalEndTopLeft), .view = [=] { return viewForItem(item); }, .paintContext = [=] { return preparePaintContext({}); }, @@ -2010,7 +2097,7 @@ TextSelection ListWidget::itemRenderSelection( Ui::ChatPaintContext ListWidget::preparePaintContext( const QRect &clip) const { - return controller()->preparePaintContext({ + return _delegate->listPreparePaintContext({ .theme = _delegate->listChatTheme(), .clip = clip, .visibleAreaPositionGlobal = mapToGlobal(QPoint(0, _visibleTop)), @@ -2022,7 +2109,7 @@ Ui::ChatPaintContext ListWidget::preparePaintContext( bool ListWidget::markingContentsRead() const { return _showFinished && !_refreshingViewer - && controller()->widget()->markingAsRead(); + && _delegate->listMarkingContentRead(); } bool ListWidget::markingMessagesRead() const { @@ -2053,12 +2140,9 @@ void ListWidget::checkActivation() { } void ListWidget::paintEvent(QPaintEvent *e) { - if ((_context != Context::ShortcutMessages) - && _controller->contentOverlapped(this, e)) { + if (_delegate->listIgnorePaintEvent(this, e)) { return; - } - - if (_translateTracker) { + } else if (_translateTracker) { _translateTracker->startBunch(); } auto readTill = (HistoryItem*)nullptr; @@ -2100,20 +2184,25 @@ void ListWidget::paintEvent(QPaintEvent *e) { _delegate->listPaintEmpty(p, context); return; } - _reactionsManager->startEffectsCollection(); + if (_reactionsManager) { + _reactionsManager->startEffectsCollection(); + } - const auto session = &controller()->session(); + const auto session = &this->session(); auto top = itemTop(from->get()); context = context.translated(0, -top); p.translate(0, top); - const auto &sendingAnimation = _controller->sendingAnimation(); + const auto sendingAnimation = _delegate->listSendingAnimation(); for (auto i = from; i != to; ++i) { const auto view = *i; const auto item = view->data(); const auto height = view->height(); - if (!sendingAnimation.hasAnimatedMessage(item)) { - context.reactionInfo - = _reactionsManager->currentReactionPaintInfo(); + if (!sendingAnimation + || !sendingAnimation->hasAnimatedMessage(item)) { + if (_reactionsManager) { + context.reactionInfo + = _reactionsManager->currentReactionPaintInfo(); + } context.outbg = view->hasOutLayout(); context.selection = itemRenderSelection(view); context.highlight = _highlighter.state(item); @@ -2125,17 +2214,19 @@ void ListWidget::paintEvent(QPaintEvent *e) { const auto isSponsored = item->isSponsored(); const auto isUnread = _delegate->listElementShownUnread(view) && item->isRegular(); - const auto withReaction = item->hasUnreadReaction(); + const auto withReaction = context.reactionInfo + && item->hasUnreadReaction(); const auto yShown = [&](int y) { return (_visibleBottom >= y && _visibleTop <= y); }; - const auto markShown = isSponsored - ? view->markSponsoredViewed(_visibleBottom - top) - : withReaction - ? yShown(top + context.reactionInfo->position.y()) - : isUnread - ? yShown(top + height) - : yShown(top + height / 2); + const auto markShown = (_context != Context::ChatPreview) + && (isSponsored + ? view->markSponsoredViewed(_visibleBottom - top) + : withReaction + ? yShown(top + context.reactionInfo->position.y()) + : isUnread + ? yShown(top + height) + : yShown(top + height / 2)); if (markShown) { if (isSponsored) { session->sponsoredMessages().view(item->fullId()); @@ -2157,9 +2248,11 @@ void ListWidget::paintEvent(QPaintEvent *e) { if (item->hasExtendedMediaPreview()) { session->api().views().pollExtendedMedia(item); } - _reactionsManager->recordCurrentReactionEffect( - item->fullId(), - QPoint(0, top)); + if (_reactionsManager) { + _reactionsManager->recordCurrentReactionEffect( + item->fullId(), + QPoint(0, top)); + } top += height; context.translate(0, -height); p.translate(0, height); @@ -2170,7 +2263,9 @@ void ListWidget::paintEvent(QPaintEvent *e) { paintUserpics(p, context, clip); paintDates(p, context, clip); - _reactionsManager->paint(p, context); + if (_reactionsManager) { + _reactionsManager->paint(p, context); + } _emojiInteractions->paint(p); } @@ -2181,7 +2276,7 @@ void ListWidget::paintUserpics( if (_context == Context::ShortcutMessages) { return; } - const auto session = &controller()->session(); + const auto session = &this->session(); enumerateUserpics([&](not_null view, int userpicTop) { // stop the enumeration if the userpic is below the painted rect if (userpicTop >= clip.top() + clip.height()) { @@ -2530,7 +2625,7 @@ void ListWidget::toggleFavoriteReaction(not_null view) const { Data::LookupPossibleReactions(item).recent, favorite, &Data::Reaction::id) - || Window::ShowReactPremiumError(_controller, item, favorite)) { + || _delegate->listShowReactPremiumError(item, favorite)) { return; } else if (!ranges::contains(item->chosenReactions(), favorite)) { if (const auto top = itemTop(view); top >= 0) { @@ -2599,6 +2694,7 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (link && !link->property( kSendReactionEmojiProperty).value().empty() + && _reactionsManager && _reactionsManager->showContextMenu( this, e, @@ -2624,13 +2720,13 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { this, overItem, clickedReaction, - _controller, + controller(), _whoReactedMenuLifetime); e->accept(); return; } - auto request = ContextMenuRequest(_controller); + auto request = ContextMenuRequest(controller()); request.link = link; request.view = _overElement; @@ -2666,12 +2762,12 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { const auto attached = reactItem ? AttachSelectorToMenu( _menu.get(), - _controller, + controller(), desiredPosition, reactItem, [=](ChosenReaction reaction) { reactionChosen(reaction); }, ItemReactionsAbout(reactItem), - _controller->cachedReactionIconFactory().createMethod()) + controller()->cachedReactionIconFactory().createMethod()) : AttachSelectorResult::Skipped; if (attached == AttachSelectorResult::Failed) { _menu = nullptr; @@ -2688,10 +2784,7 @@ void ListWidget::reactionChosen(ChosenReaction reaction) { const auto item = session().data().message(reaction.context); if (!item) { return; - } else if (Window::ShowReactPremiumError( - _controller, - item, - reaction.id)) { + } else if (_delegate->listShowReactPremiumError(item, reaction.id)) { if (_menu) { _menu->hideMenu(); } @@ -2945,7 +3038,9 @@ void ListWidget::enterEventHook(QEnterEvent *e) { } void ListWidget::leaveEventHook(QEvent *e) { - _reactionsManager->updateButton({ .cursorLeft = true }); + if (_reactionsManager) { + _reactionsManager->updateButton({ .cursorLeft = true }); + } if (const auto view = _overElement) { if (_overState.pointState != PointState::Outside) { repaintItem(view); @@ -3160,9 +3255,9 @@ void ListWidget::mouseActionStart( const auto pressElement = _overElement; _mouseAction = MouseAction::None; - _pressWasInactive = Ui::WasInactivePress(_controller->widget()); + _pressWasInactive = Ui::WasInactivePress(window()); if (_pressWasInactive) { - Ui::MarkInactivePress(_controller->widget(), false); + Ui::MarkInactivePress(window(), false); } if (ClickHandler::getPressed()) { @@ -3334,7 +3429,7 @@ void ListWidget::mouseActionFinish( } else if (_selectedTextItem && !_pressWasInactive) { if (_selectedTextRange.from == _selectedTextRange.to) { clearTextSelection(); - _controller->widget()->setInnerFocus(); + _delegate->listWindowSetInnerFocus(); } } } @@ -3362,7 +3457,7 @@ ClickHandlerContext ListWidget::prepareClickHandlerContext(FullMsgId id) { ? (ElementDelegate*)weak : nullptr; }, - .sessionWindow = base::make_weak(_controller), + .sessionWindow = base::make_weak(controller()), }; } @@ -3372,7 +3467,9 @@ void ListWidget::mouseActionUpdate() { std::clamp(mousePosition.x(), 0, width()), std::clamp(mousePosition.y(), _visibleTop, _visibleBottom)); - const auto reactionState = _reactionsManager->buttonTextState(point); + const auto reactionState = _reactionsManager + ? _reactionsManager->buttonTextState(point) + : TextState(); const auto reactionItem = session().data().message(reactionState.itemId); const auto reactionView = viewForItem(reactionItem); const auto view = reactionView @@ -3392,12 +3489,14 @@ void ListWidget::mouseActionUpdate() { _overElement = view; repaintItem(_overElement); } - _reactionsManager->updateButton(view - ? reactionButtonParameters( - view, - itemPoint, - reactionState) - : Reactions::ButtonParameters()); + if (_reactionsManager) { + _reactionsManager->updateButton(view + ? reactionButtonParameters( + view, + itemPoint, + reactionState) + : Reactions::ButtonParameters()); + } if (viewChanged && view) { _reactionsItem = item; } @@ -3624,7 +3723,7 @@ std::unique_ptr ListWidget::prepareDrag() { if (!urls.isEmpty()) { mimeData->setUrls(urls); } - if (uponSelected && !_controller->adaptive().isOneColumn()) { + if (uponSelected && !_delegate->listAllowsDragForward()) { const auto canForwardAll = [&] { for (const auto &[itemId, data] : _selected) { if (!data.canForward) { @@ -3689,8 +3788,10 @@ std::unique_ptr ListWidget::prepareDrag() { void ListWidget::performDrag() { if (auto mimeData = prepareDrag()) { // This call enters event loop and can destroy any QObject. - _reactionsManager->updateButton({}); - _controller->widget()->launchDrag( + if (_reactionsManager) { + _reactionsManager->updateButton({}); + } + _delegate->listLaunchDrag( std::move(mimeData), crl::guard(this, [=] { mouseActionUpdate(QCursor::pos()); })); } @@ -3708,7 +3809,10 @@ void ListWidget::repaintItem(const Element *view) { const auto range = view->verticalRepaintRange(); update(0, top + range.top, width(), range.height); const auto id = view->data()->fullId(); - if (const auto area = _reactionsManager->lookupEffectArea(id)) { + const auto area = _reactionsManager + ? _reactionsManager->lookupEffectArea(id) + : std::nullopt; + if (area) { update(*area); } } @@ -3866,7 +3970,9 @@ void ListWidget::itemRemoved(not_null item) { viewReplaced(view, nullptr); _views.erase(i); - _reactionsManager->remove(item->fullId()); + if (_reactionsManager) { + _reactionsManager->remove(item->fullId()); + } updateItemsGeometry(); } @@ -3992,7 +4098,7 @@ void ConfirmDeleteSelectedItems(not_null widget) { } } auto box = Box( - &widget->controller()->session(), + &widget->session(), widget->getSelectedIds()); box->setDeleteConfirmedCallback(crl::guard(widget, [=] { widget->cancelSelection(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 7770341d9..f88582722 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -25,11 +25,14 @@ class Session; } // namespace Main namespace Ui { +class Show; class PopupMenu; class ChatTheme; struct ChatPaintContext; +struct ChatPaintContextArgs; enum class TouchScrollState; struct PeerUserpicView; +class MessageSendingAnimationController; } // namespace Ui namespace Window { @@ -40,6 +43,7 @@ namespace Data { struct Group; struct Reaction; struct AllowedReactions; +struct ReactionId; } // namespace Data namespace HistoryView::Reactions { @@ -154,6 +158,71 @@ public: virtual History *listTranslateHistory() = 0; virtual void listAddTranslatedItems( not_null tracker) = 0; + + // Methods that use Window::SessionController by default. + virtual not_null listWindow() = 0; + virtual not_null listChatStyle() = 0; + virtual rpl::producer listChatWideValue() = 0; + virtual std::unique_ptr listMakeReactionsManager( + QWidget *wheelEventsTarget, + Fn update) = 0; + virtual void listVisibleAreaUpdated() = 0; + virtual std::shared_ptr listUiShow() = 0; + virtual void listShowPollResults( + not_null poll, + FullMsgId context) = 0; + virtual void listCancelUploadLayer(not_null item) = 0; + virtual bool listAnimationsPaused() = 0; + virtual auto listSendingAnimation() + -> Ui::MessageSendingAnimationController* = 0; + virtual Ui::ChatPaintContext listPreparePaintContext( + Ui::ChatPaintContextArgs &&args) = 0; + virtual bool listMarkingContentRead() = 0; + virtual bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) = 0; + virtual bool listShowReactPremiumError( + not_null item, + const Data::ReactionId &id) = 0; + virtual void listWindowSetInnerFocus() = 0; + virtual bool listAllowsDragForward() = 0; + virtual void listLaunchDrag( + std::unique_ptr data, + Fn finished) = 0; +}; + +class WindowListDelegate : public ListDelegate { +public: + explicit WindowListDelegate(not_null window); + + not_null listWindow() override; + not_null listChatStyle() override; + rpl::producer listChatWideValue() override; + std::unique_ptr listMakeReactionsManager( + QWidget *wheelEventsTarget, + Fn update) override; + void listVisibleAreaUpdated() override; + std::shared_ptr listUiShow() override; + void listShowPollResults( + not_null poll, + FullMsgId context) override; + void listCancelUploadLayer(not_null item) override; + bool listAnimationsPaused() override; + Ui::MessageSendingAnimationController *listSendingAnimation() override; + Ui::ChatPaintContext listPreparePaintContext( + Ui::ChatPaintContextArgs &&args) override; + bool listMarkingContentRead() override; + bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) override; + bool listShowReactPremiumError( + not_null item, + const Data::ReactionId &id) override; + void listWindowSetInnerFocus() override; + bool listAllowsDragForward() override; + void listLaunchDrag( + std::unique_ptr data, + Fn finished) override; + +private: + const not_null _window; + }; struct SelectionData { @@ -211,7 +280,7 @@ class ListWidget final public: ListWidget( QWidget *parent, - not_null controller, + not_null session, not_null delegate); static const crl::time kItemRevealDuration; @@ -648,7 +717,7 @@ private: static constexpr auto kMinimalIdsLimit = 24; const not_null _delegate; - const not_null _controller; + const not_null _session; const std::unique_ptr _emojiInteractions; const Context _context; diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index 0051aecea..51a3101eb 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -94,6 +94,7 @@ PinnedWidget::PinnedWidget( not_null controller, not_null thread) : Window::SectionWidget(parent, controller, thread->peer()) +, WindowListDelegate(controller) , _thread(thread->migrateToOrMe()) , _history(thread->owningHistory()) , _migratedPeer(thread->asHistory() @@ -161,7 +162,7 @@ PinnedWidget::PinnedWidget( _inner = _scroll->setOwnedWidget(object_ptr( this, - controller, + &controller->session(), static_cast(this))); _scroll->move(0, _topBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.h b/Telegram/SourceFiles/history/view/history_view_pinned_section.h index 88a592a1b..2c54e0684 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.h @@ -36,7 +36,7 @@ class TranslateBar; class PinnedWidget final : public Window::SectionWidget - , private ListDelegate + , private WindowListDelegate , private CornerButtonsDelegate { public: PinnedWidget( diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 02d9c8412..b1dcb13db 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -205,6 +205,7 @@ RepliesWidget::RepliesWidget( not_null history, MsgId rootId) : Window::SectionWidget(parent, controller, history->peer) +, WindowListDelegate(controller) , _history(history) , _rootId(rootId) , _root(lookupRoot()) @@ -299,7 +300,7 @@ RepliesWidget::RepliesWidget( _inner = _scroll->setOwnedWidget(object_ptr( this, - controller, + &controller->session(), static_cast(this))); _scroll->move(0, _topBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index 33b7859b4..e3d05920e 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -71,7 +71,7 @@ class TranslateBar; class RepliesWidget final : public Window::SectionWidget - , private ListDelegate + , private WindowListDelegate , private CornerButtonsDelegate { public: RepliesWidget( diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 887d16e09..3fe205b3c 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -97,6 +97,7 @@ ScheduledWidget::ScheduledWidget( not_null history, const Data::ForumTopic *forumTopic) : Window::SectionWidget(parent, controller, history->peer) +, WindowListDelegate(controller) , _history(history) , _forumTopic(forumTopic) , _scroll( @@ -167,7 +168,7 @@ ScheduledWidget::ScheduledWidget( _inner = _scroll->setOwnedWidget(object_ptr( this, - controller, + &controller->session(), static_cast(this))); _scroll->move(0, _topBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index 6685c113a..9f181d231 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -52,7 +52,7 @@ class StickerToast; class ScheduledWidget final : public Window::SectionWidget - , private ListDelegate + , private WindowListDelegate , private CornerButtonsDelegate { public: ScheduledWidget( diff --git a/Telegram/SourceFiles/history/view/history_view_sublist_section.cpp b/Telegram/SourceFiles/history/view/history_view_sublist_section.cpp index f4116fd15..df4f4ea04 100644 --- a/Telegram/SourceFiles/history/view/history_view_sublist_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_sublist_section.cpp @@ -67,6 +67,7 @@ SublistWidget::SublistWidget( not_null controller, not_null sublist) : Window::SectionWidget(parent, controller, sublist->peer()) +, WindowListDelegate(controller) , _sublist(sublist) , _history(sublist->owner().history(sublist->session().user())) , _topBar(this, controller) @@ -133,7 +134,7 @@ SublistWidget::SublistWidget( _inner = _scroll->setOwnedWidget(object_ptr( this, - controller, + &controller->session(), static_cast(this))); _scroll->move(0, _topBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/history/view/history_view_sublist_section.h b/Telegram/SourceFiles/history/view/history_view_sublist_section.h index 7ce880439..eff71d50c 100644 --- a/Telegram/SourceFiles/history/view/history_view_sublist_section.h +++ b/Telegram/SourceFiles/history/view/history_view_sublist_section.h @@ -37,7 +37,7 @@ class ComposeSearch; class SublistWidget final : public Window::SectionWidget - , private ListDelegate + , private WindowListDelegate , private CornerButtonsDelegate { public: SublistWidget( diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index ca82da329..22e419efa 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -72,7 +72,7 @@ using namespace HistoryView; class ShortcutMessages : public AbstractSection - , private ListDelegate + , private WindowListDelegate , private CornerButtonsDelegate { public: ShortcutMessages( @@ -164,6 +164,7 @@ private: History *listTranslateHistory() override; void listAddTranslatedItems( not_null tracker) override; + bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) override; // CornerButtonsDelegate delegate. void cornerButtonsShowAtPosition( @@ -330,6 +331,7 @@ ShortcutMessages::ShortcutMessages( rpl::producer containerValue, BusinessShortcutId shortcutId) : AbstractSection(parent) +, WindowListDelegate(controller) , _controller(controller) , _session(&controller->session()) , _scroll(scroll) @@ -370,7 +372,7 @@ ShortcutMessages::ShortcutMessages( _inner = Ui::CreateChild( this, - controller, + &controller->session(), static_cast(this)); _inner->overrideIsChatWide(false); @@ -1053,6 +1055,10 @@ void ShortcutMessages::listAddTranslatedItems( not_null tracker) { } +bool ShortcutMessages::listIgnorePaintEvent(QWidget *w, QPaintEvent *e) { + return false; +} + void ShortcutMessages::cornerButtonsShowAtPosition( Data::MessagePosition position) { showAtPosition(position); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index 6b8cc459b..f7499a2d0 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -223,6 +223,14 @@ struct ChatPaintContext { }; +struct ChatPaintContextArgs { + not_null theme; + QRect clip; + QPoint visibleAreaPositionGlobal; + int visibleAreaTop = 0; + int visibleAreaWidth = 0; +}; + [[nodiscard]] int HistoryServiceMsgRadius(); [[nodiscard]] int HistoryServiceMsgInvertedRadius(); [[nodiscard]] int HistoryServiceMsgInvertedShrink(); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 4580991e7..0162d7169 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -2951,7 +2951,7 @@ void SessionController::openPeerStories( } HistoryView::PaintContext SessionController::preparePaintContext( - PaintContextArgs &&args) { + Ui::ChatPaintContextArgs &&args) { const auto visibleAreaTopLocal = content()->mapFromGlobal( args.visibleAreaPositionGlobal).y(); const auto viewport = QRect( diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 4ff92675f..9888dc1c4 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -64,6 +64,7 @@ struct ChatThemeBackground; struct ChatThemeBackgroundData; class MessageSendingAnimationController; struct BoostCounters; +struct ChatPaintContextArgs; } // namespace Ui namespace Data { @@ -586,15 +587,8 @@ public: PeerId peerId, std::optional list = std::nullopt); - struct PaintContextArgs { - not_null theme; - QRect clip; - QPoint visibleAreaPositionGlobal; - int visibleAreaTop = 0; - int visibleAreaWidth = 0; - }; [[nodiscard]] Ui::ChatPaintContext preparePaintContext( - PaintContextArgs &&args); + Ui::ChatPaintContextArgs &&args); [[nodiscard]] not_null chatStyle() const { return _chatStyle.get(); }