For non-bubble messages reaction to the left of info.

This commit is contained in:
John Preston 2021-12-31 02:17:34 +03:00
parent 5bb90679a8
commit cd0db53bac
14 changed files with 78 additions and 38 deletions

View file

@ -679,6 +679,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
} }
if (hasPendingResizedItems()) { if (hasPendingResizedItems()) {
return; return;
} else if (_recountedAfterPendingResizedItems) {
_recountedAfterPendingResizedItems = false;
mouseActionUpdate();
} }
const auto guard = gsl::finally([&] { const auto guard = gsl::finally([&] {
@ -2370,6 +2373,11 @@ void HistoryInner::checkHistoryActivation() {
void HistoryInner::recountHistoryGeometry() { void HistoryInner::recountHistoryGeometry() {
_contentWidth = _scroll->width(); _contentWidth = _scroll->width();
if (_history->hasPendingResizedItems()
|| (_migrated && _migrated->hasPendingResizedItems())) {
_recountedAfterPendingResizedItems = true;
}
const auto visibleHeight = _scroll->height(); const auto visibleHeight = _scroll->height();
int oldHistoryPaddingTop = qMax(visibleHeight - historyHeight() - st::historyPaddingBottom, 0); int oldHistoryPaddingTop = qMax(visibleHeight - historyHeight() - st::historyPaddingBottom, 0);
if (_botAbout && !_botAbout->info->text.isEmpty()) { if (_botAbout && !_botAbout->info->text.isEmpty()) {
@ -3003,7 +3011,11 @@ void HistoryInner::mouseActionUpdate() {
: nullptr; : nullptr;
const auto item = view ? view->data().get() : nullptr; const auto item = view ? view->data().get() : nullptr;
if (view) { if (view) {
App::mousedItem(view); if (App::mousedItem() != view) {
repaintItem(App::mousedItem());
App::mousedItem(view);
repaintItem(App::mousedItem());
}
m = mapPointToItem(point, view); m = mapPointToItem(point, view);
_reactionsManager->updateButton(reactionButtonParameters( _reactionsManager->updateButton(reactionButtonParameters(
view, view,
@ -3020,6 +3032,10 @@ void HistoryInner::mouseActionUpdate() {
App::hoveredItem(nullptr); App::hoveredItem(nullptr);
} }
} else { } else {
if (App::mousedItem()) {
repaintItem(App::mousedItem());
App::mousedItem(nullptr);
}
_reactionsManager->updateButton({}); _reactionsManager->updateButton({});
} }
if (_mouseActionItem && !_mouseActionItem->mainView()) { if (_mouseActionItem && !_mouseActionItem->mainView()) {
@ -3745,7 +3761,7 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
} }
bool elementUnderCursor( bool elementUnderCursor(
not_null<const Element*> view) override { not_null<const Element*> view) override {
return (App::hoveredItem() == view); return (App::mousedItem() == view);
} }
crl::time elementHighlightTime( crl::time elementHighlightTime(
not_null<const HistoryItem*> item) override { not_null<const HistoryItem*> item) override {

View file

@ -417,6 +417,7 @@ private:
CursorState _mouseCursorState = CursorState(); CursorState _mouseCursorState = CursorState();
uint16 _mouseTextSymbol = 0; uint16 _mouseTextSymbol = 0;
bool _pressWasInactive = false; bool _pressWasInactive = false;
bool _recountedAfterPendingResizedItems = false;
QPoint _trippleClickPoint; QPoint _trippleClickPoint;
base::Timer _trippleClickTimer; base::Timer _trippleClickTimer;

View file

@ -605,7 +605,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
if (_reactions && !reactionsInBubble) { if (_reactions && !reactionsInBubble) {
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height(); const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
const auto reactionsLeft = (!bubble && mediaDisplayed) const auto reactionsLeft = (!bubble && mediaDisplayed)
? media->contentRectForReactionButton().x() ? media->contentRectForReactions().x()
: 0; : 0;
g.setHeight(g.height() - reactionsHeight); g.setHeight(g.height() - reactionsHeight);
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip); const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
@ -1281,7 +1281,7 @@ TextState Message::textState(
if (_reactions && !reactionsInBubble) { if (_reactions && !reactionsInBubble) {
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height(); const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
const auto reactionsLeft = (!bubble && mediaDisplayed) const auto reactionsLeft = (!bubble && mediaDisplayed)
? media->contentRectForReactionButton().x() ? media->contentRectForReactions().x()
: 0; : 0;
g.setHeight(g.height() - reactionsHeight); g.setHeight(g.height() - reactionsHeight);
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip); 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() const auto innerHeight = geometry.height()
- keyboardHeight - keyboardHeight
- reactionsHeight; - reactionsHeight;
const auto contentRect = (result.style == ButtonStyle::Service const auto maybeRelativeCenter = (result.style == ButtonStyle::Service)
&& !drawBubble()) ? media()->reactionButtonCenterOverride()
? media()->contentRectForReactionButton().translated( : std::nullopt;
geometry.topLeft()) const auto relativeCenter = QPoint(
: geometry; maybeRelativeCenter.value_or(onTheLeft
result.center = contentRect.topLeft() + (onTheLeft ? -st::reactionCornerCenter.x()
? (QPoint(0, innerHeight) + QPoint( : (geometry.width() + st::reactionCornerCenter.x())),
-st::reactionCornerCenter.x(), innerHeight + st::reactionCornerCenter.y());
st::reactionCornerCenter.y())) result.center = geometry.topLeft() + relativeCenter;
: (QPoint(contentRect.width(), innerHeight)
+ st::reactionCornerCenter));
if (reactionState.itemId != result.context if (reactionState.itemId != result.context
&& !contentRect.contains(position)) { && !geometry.contains(position)) {
result.outside = true; result.outside = true;
} }
const auto minSkip = (st::reactionCornerShadow.left() const auto minSkip = (st::reactionCornerShadow.left()
@ -2794,7 +2792,7 @@ int Message::resizeContentGetHeight(int newWidth) {
} }
if (_reactions && !reactionsInBubble) { if (_reactions && !reactionsInBubble) {
const auto reactionsWidth = (!bubble && mediaDisplayed) const auto reactionsWidth = (!bubble && mediaDisplayed)
? media->contentRectForReactionButton().width() ? media->contentRectForReactions().width()
: contentWidth; : contentWidth;
newHeight += st::mediaInBubbleSkip newHeight += st::mediaInBubbleSkip
+ _reactions->resizeGetHeight(reactionsWidth); + _reactions->resizeGetHeight(reactionsWidth);

View file

@ -1170,7 +1170,7 @@ bool Gif::needsBubble() const {
return false; return false;
} }
QRect Gif::contentRectForReactionButton() const { QRect Gif::contentRectForReactions() const {
if (!isSeparateRoundVideo()) { if (!isSeparateRoundVideo()) {
return QRect(0, 0, width(), height()); return QRect(0, 0, width(), height());
} }
@ -1191,6 +1191,31 @@ QRect Gif::contentRectForReactionButton() const {
return style::rtlrect(usex + paintx, painty, usew, painth, width()); return style::rtlrect(usex + paintx, painty, usew, painth, width());
} }
std::optional<int> 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 { int Gif::additionalWidth() const {
const auto item = _parent->data(); const auto item = _parent->data();
return additionalWidth( return additionalWidth(

View file

@ -96,7 +96,8 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return _caption.isEmpty(); return _caption.isEmpty();
} }
QRect contentRectForReactionButton() const override; QRect contentRectForReactions() const override;
std::optional<int> reactionButtonCenterOverride() const override;
QString additionalInfoString() const override; QString additionalInfoString() const override;
bool skipBubbleTail() const override { bool skipBubbleTail() const override {

View file

@ -345,10 +345,6 @@ bool Location::needsBubble() const {
|| _parent->displayFromName(); || _parent->displayFromName();
} }
QRect Location::contentRectForReactionButton() const {
return QRect(0, 0, width(), height());
}
int Location::fullWidth() const { int Location::fullWidth() const {
return st::locationSize.width(); return st::locationSize.width();
} }

View file

@ -53,7 +53,6 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return true; return true;
} }
QRect contentRectForReactionButton() const override;
bool skipBubbleTail() const override { bool skipBubbleTail() const override {
return isRoundedInBubbleBottom(); return isRoundedInBubbleBottom();

View file

@ -205,8 +205,12 @@ public:
} }
[[nodiscard]] virtual bool needsBubble() const = 0; [[nodiscard]] virtual bool needsBubble() const = 0;
[[nodiscard]] virtual bool customInfoLayout() const = 0; [[nodiscard]] virtual bool customInfoLayout() const = 0;
[[nodiscard]] virtual QRect contentRectForReactionButton() const { [[nodiscard]] virtual QRect contentRectForReactions() const {
Unexpected("Media::contentRectForReactionButton"); return QRect(0, 0, width(), height());
}
[[nodiscard]] virtual auto reactionButtonCenterOverride() const
-> std::optional<int> {
return std::nullopt;
} }
[[nodiscard]] virtual QMargins bubbleMargins() const { [[nodiscard]] virtual QMargins bubbleMargins() const {
return QMargins(); return QMargins();

View file

@ -730,10 +730,6 @@ bool GroupedMedia::needsBubble() const {
return _needBubble; return _needBubble;
} }
QRect GroupedMedia::contentRectForReactionButton() const {
return QRect(0, 0, width(), height());
}
bool GroupedMedia::computeNeedBubble() const { bool GroupedMedia::computeNeedBubble() const {
if (!_caption.isEmpty() || _mode == Mode::Column) { if (!_caption.isEmpty() || _mode == Mode::Column) {
return true; return true;

View file

@ -84,7 +84,6 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return _caption.isEmpty() && (_mode != Mode::Column); return _caption.isEmpty() && (_mode != Mode::Column);
} }
QRect contentRectForReactionButton() const override;
bool allowsFastShare() const override { bool allowsFastShare() const override {
return true; return true;
} }

View file

@ -401,7 +401,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
return result; return result;
} }
QRect UnwrappedMedia::contentRectForReactionButton() const { QRect UnwrappedMedia::contentRectForReactions() const {
const auto inWebPage = (_parent->media() != this); const auto inWebPage = (_parent->media() != this);
if (inWebPage) { if (inWebPage) {
return QRect(0, 0, width(), height()); return QRect(0, 0, width(), height());
@ -432,6 +432,15 @@ QRect UnwrappedMedia::contentRectForReactionButton() const {
return QRect(usex, usey, usew, useh); return QRect(usex, usey, usew, useh);
} }
std::optional<int> 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<Lottie::SinglePlayer> UnwrappedMedia::stickerTakeLottie( std::unique_ptr<Lottie::SinglePlayer> UnwrappedMedia::stickerTakeLottie(
not_null<DocumentData*> data, not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) { const Lottie::ColorReplacements *replacements) {

View file

@ -81,7 +81,8 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return true; return true;
} }
QRect contentRectForReactionButton() const override; QRect contentRectForReactions() const override;
std::optional<int> reactionButtonCenterOverride() const override;
void stickerClearLoopPlayed() override { void stickerClearLoopPlayed() override {
_content->stickerClearLoopPlayed(); _content->stickerClearLoopPlayed();
} }

View file

@ -831,10 +831,6 @@ bool Photo::needsBubble() const {
|| _parent->displayFromName()); || _parent->displayFromName());
} }
QRect Photo::contentRectForReactionButton() const {
return QRect(0, 0, width(), height());
}
bool Photo::isReadyForOpen() const { bool Photo::isReadyForOpen() const {
ensureDataMediaCreated(); ensureDataMediaCreated();
return _dataMedia->loaded(); return _dataMedia->loaded();

View file

@ -82,7 +82,6 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return _caption.isEmpty(); return _caption.isEmpty();
} }
QRect contentRectForReactionButton() const override;
bool skipBubbleTail() const override { bool skipBubbleTail() const override {
return isRoundedInBubbleBottom() && _caption.isEmpty(); return isRoundedInBubbleBottom() && _caption.isEmpty();
} }