diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 5322f4e34..37a6aef07 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -679,6 +679,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) { } if (hasPendingResizedItems()) { return; + } else if (_recountedAfterPendingResizedItems) { + _recountedAfterPendingResizedItems = false; + mouseActionUpdate(); } const auto guard = gsl::finally([&] { @@ -2370,6 +2373,11 @@ void HistoryInner::checkHistoryActivation() { void HistoryInner::recountHistoryGeometry() { _contentWidth = _scroll->width(); + if (_history->hasPendingResizedItems() + || (_migrated && _migrated->hasPendingResizedItems())) { + _recountedAfterPendingResizedItems = true; + } + const auto visibleHeight = _scroll->height(); int oldHistoryPaddingTop = qMax(visibleHeight - historyHeight() - st::historyPaddingBottom, 0); if (_botAbout && !_botAbout->info->text.isEmpty()) { @@ -3003,7 +3011,11 @@ void HistoryInner::mouseActionUpdate() { : nullptr; const auto item = view ? view->data().get() : nullptr; if (view) { - App::mousedItem(view); + if (App::mousedItem() != view) { + repaintItem(App::mousedItem()); + App::mousedItem(view); + repaintItem(App::mousedItem()); + } m = mapPointToItem(point, view); _reactionsManager->updateButton(reactionButtonParameters( view, @@ -3020,6 +3032,10 @@ void HistoryInner::mouseActionUpdate() { App::hoveredItem(nullptr); } } else { + if (App::mousedItem()) { + repaintItem(App::mousedItem()); + App::mousedItem(nullptr); + } _reactionsManager->updateButton({}); } if (_mouseActionItem && !_mouseActionItem->mainView()) { @@ -3745,7 +3761,7 @@ not_null HistoryInner::ElementDelegate() { } bool elementUnderCursor( not_null view) override { - return (App::hoveredItem() == view); + return (App::mousedItem() == view); } crl::time elementHighlightTime( not_null item) override { diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index c3391a6cd..e03150843 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -417,6 +417,7 @@ private: CursorState _mouseCursorState = CursorState(); uint16 _mouseTextSymbol = 0; bool _pressWasInactive = false; + bool _recountedAfterPendingResizedItems = false; QPoint _trippleClickPoint; base::Timer _trippleClickTimer; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 9479db3fa..d00c33b29 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -605,7 +605,7 @@ void Message::draw(Painter &p, const PaintContext &context) const { if (_reactions && !reactionsInBubble) { const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height(); const auto reactionsLeft = (!bubble && mediaDisplayed) - ? media->contentRectForReactionButton().x() + ? media->contentRectForReactions().x() : 0; g.setHeight(g.height() - reactionsHeight); const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip); @@ -1281,7 +1281,7 @@ TextState Message::textState( if (_reactions && !reactionsInBubble) { const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height(); const auto reactionsLeft = (!bubble && mediaDisplayed) - ? media->contentRectForReactionButton().x() + ? media->contentRectForReactions().x() : 0; g.setHeight(g.height() - reactionsHeight); const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip); @@ -1856,19 +1856,17 @@ Reactions::ButtonParameters Message::reactionButtonParameters( const auto innerHeight = geometry.height() - keyboardHeight - reactionsHeight; - const auto contentRect = (result.style == ButtonStyle::Service - && !drawBubble()) - ? media()->contentRectForReactionButton().translated( - geometry.topLeft()) - : geometry; - result.center = contentRect.topLeft() + (onTheLeft - ? (QPoint(0, innerHeight) + QPoint( - -st::reactionCornerCenter.x(), - st::reactionCornerCenter.y())) - : (QPoint(contentRect.width(), innerHeight) - + st::reactionCornerCenter)); + const auto maybeRelativeCenter = (result.style == ButtonStyle::Service) + ? media()->reactionButtonCenterOverride() + : std::nullopt; + const auto relativeCenter = QPoint( + maybeRelativeCenter.value_or(onTheLeft + ? -st::reactionCornerCenter.x() + : (geometry.width() + st::reactionCornerCenter.x())), + innerHeight + st::reactionCornerCenter.y()); + result.center = geometry.topLeft() + relativeCenter; if (reactionState.itemId != result.context - && !contentRect.contains(position)) { + && !geometry.contains(position)) { result.outside = true; } const auto minSkip = (st::reactionCornerShadow.left() @@ -2794,7 +2792,7 @@ int Message::resizeContentGetHeight(int newWidth) { } if (_reactions && !reactionsInBubble) { const auto reactionsWidth = (!bubble && mediaDisplayed) - ? media->contentRectForReactionButton().width() + ? media->contentRectForReactions().width() : contentWidth; newHeight += st::mediaInBubbleSkip + _reactions->resizeGetHeight(reactionsWidth); diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index c7c56c6c2..454842d4b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -1170,7 +1170,7 @@ bool Gif::needsBubble() const { return false; } -QRect Gif::contentRectForReactionButton() const { +QRect Gif::contentRectForReactions() const { if (!isSeparateRoundVideo()) { return QRect(0, 0, width(), height()); } @@ -1191,6 +1191,31 @@ QRect Gif::contentRectForReactionButton() const { return style::rtlrect(usex + paintx, painty, usew, painth, width()); } +std::optional Gif::reactionButtonCenterOverride() const { + if (!isSeparateRoundVideo()) { + return std::nullopt; + } + const auto inner = contentRectForReactions(); + auto fullRight = inner.x() + inner.width(); + auto maxRight = _parent->width() - st::msgMargin.left(); + if (_parent->hasFromPhoto()) { + maxRight -= st::msgMargin.right(); + } else { + maxRight -= st::msgMargin.left(); + } + const auto infoWidth = _parent->infoWidth(); + if (!_parent->hasOutLayout()) { + // This is just some arbitrary point, + // the main idea is to make info left aligned here. + fullRight += infoWidth - st::normalFont->height; + if (fullRight > maxRight) { + fullRight = maxRight; + } + } + const auto right = fullRight - infoWidth - 3 * st::msgDateImgPadding.x(); + return right - st::reactionCornerSize.width() / 2; +} + int Gif::additionalWidth() const { const auto item = _parent->data(); return additionalWidth( diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index 6161662a5..84cc5c91b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -96,7 +96,8 @@ public: bool customInfoLayout() const override { return _caption.isEmpty(); } - QRect contentRectForReactionButton() const override; + QRect contentRectForReactions() const override; + std::optional reactionButtonCenterOverride() const override; QString additionalInfoString() const override; bool skipBubbleTail() const override { diff --git a/Telegram/SourceFiles/history/view/media/history_view_location.cpp b/Telegram/SourceFiles/history/view/media/history_view_location.cpp index 446a7aa3e..cc80266ec 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_location.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_location.cpp @@ -345,10 +345,6 @@ bool Location::needsBubble() const { || _parent->displayFromName(); } -QRect Location::contentRectForReactionButton() const { - return QRect(0, 0, width(), height()); -} - int Location::fullWidth() const { return st::locationSize.width(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_location.h b/Telegram/SourceFiles/history/view/media/history_view_location.h index ab7882e75..7c182bb99 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_location.h +++ b/Telegram/SourceFiles/history/view/media/history_view_location.h @@ -53,7 +53,6 @@ public: bool customInfoLayout() const override { return true; } - QRect contentRectForReactionButton() const override; bool skipBubbleTail() const override { return isRoundedInBubbleBottom(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 5dbe00a65..fae4e342c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -205,8 +205,12 @@ public: } [[nodiscard]] virtual bool needsBubble() const = 0; [[nodiscard]] virtual bool customInfoLayout() const = 0; - [[nodiscard]] virtual QRect contentRectForReactionButton() const { - Unexpected("Media::contentRectForReactionButton"); + [[nodiscard]] virtual QRect contentRectForReactions() const { + return QRect(0, 0, width(), height()); + } + [[nodiscard]] virtual auto reactionButtonCenterOverride() const + -> std::optional { + return std::nullopt; } [[nodiscard]] virtual QMargins bubbleMargins() const { return QMargins(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp index a1b22471c..87ce0df1a 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -730,10 +730,6 @@ bool GroupedMedia::needsBubble() const { return _needBubble; } -QRect GroupedMedia::contentRectForReactionButton() const { - return QRect(0, 0, width(), height()); -} - bool GroupedMedia::computeNeedBubble() const { if (!_caption.isEmpty() || _mode == Mode::Column) { return true; diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h index 4680758aa..f31b69971 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h @@ -84,7 +84,6 @@ public: bool customInfoLayout() const override { return _caption.isEmpty() && (_mode != Mode::Column); } - QRect contentRectForReactionButton() const override; bool allowsFastShare() const override { return true; } diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index 3bce0244d..479a12c02 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -401,7 +401,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const { return result; } -QRect UnwrappedMedia::contentRectForReactionButton() const { +QRect UnwrappedMedia::contentRectForReactions() const { const auto inWebPage = (_parent->media() != this); if (inWebPage) { return QRect(0, 0, width(), height()); @@ -432,6 +432,15 @@ QRect UnwrappedMedia::contentRectForReactionButton() const { return QRect(usex, usey, usew, useh); } +std::optional UnwrappedMedia::reactionButtonCenterOverride() const { + const auto fullRight = calculateFullRight(contentRectForReactions()); + const auto right = fullRight + - _parent->infoWidth() + - st::msgDateImgPadding.x() * 2 + - st::msgReplyPadding.left(); + return right - st::reactionCornerSize.width() / 2; +} + std::unique_ptr UnwrappedMedia::stickerTakeLottie( not_null data, const Lottie::ColorReplacements *replacements) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h index 9c8b0cf58..1c374c386 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h @@ -81,7 +81,8 @@ public: bool customInfoLayout() const override { return true; } - QRect contentRectForReactionButton() const override; + QRect contentRectForReactions() const override; + std::optional reactionButtonCenterOverride() const override; void stickerClearLoopPlayed() override { _content->stickerClearLoopPlayed(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index 1949d82e9..0d0b308e5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -831,10 +831,6 @@ bool Photo::needsBubble() const { || _parent->displayFromName()); } -QRect Photo::contentRectForReactionButton() const { - return QRect(0, 0, width(), height()); -} - bool Photo::isReadyForOpen() const { ensureDataMediaCreated(); return _dataMedia->loaded(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.h b/Telegram/SourceFiles/history/view/media/history_view_photo.h index 4c4ea720d..3c60661ec 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.h +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.h @@ -82,7 +82,6 @@ public: bool customInfoLayout() const override { return _caption.isEmpty(); } - QRect contentRectForReactionButton() const override; bool skipBubbleTail() const override { return isRoundedInBubbleBottom() && _caption.isEmpty(); }