Improve jump-to-message in saved messages.

This commit is contained in:
John Preston 2024-01-01 23:33:19 +04:00
parent bfe7683cdb
commit a4f4e4564a
12 changed files with 91 additions and 61 deletions

View File

@ -1342,6 +1342,10 @@ bool Element::hasOutLayout() const {
return false;
}
bool Element::hasRightLayout() const {
return hasOutLayout() && !_delegate->elementIsChatWide();
}
bool Element::drawBubble() const {
return false;
}

View File

@ -439,6 +439,7 @@ public:
[[nodiscard]] virtual TopicButton *displayedTopicButton() const;
[[nodiscard]] virtual bool displayForwardedFrom() const;
[[nodiscard]] virtual bool hasOutLayout() const;
[[nodiscard]] bool hasRightLayout() const;
[[nodiscard]] virtual bool drawBubble() const;
[[nodiscard]] virtual bool hasBubble() const;
[[nodiscard]] virtual bool unwrapped() const;

View File

@ -220,8 +220,7 @@ QRect EmojiInteractions::computeRect(const Play &play) const {
? int(sticker.width() * kPremiumShift)
: (size.width() / 40);
const auto inner = view->innerGeometry();
const auto rightAligned = view->hasOutLayout()
&& !view->delegate()->elementIsChatWide();
const auto rightAligned = view->hasRightLayout();
const auto left = rightAligned
? (inner.x() + inner.width() + shift - size.width())
: (inner.x() - shift);
@ -241,8 +240,7 @@ void EmojiInteractions::paint(QPainter &p) {
}
auto request = Lottie::FrameRequest();
request.box = play.outer * factor;
const auto rightAligned = play.view->hasOutLayout()
&& !play.view->delegate()->elementIsChatWide();
const auto rightAligned = play.view->hasRightLayout();
if (!rightAligned) {
request.mirrorHorizontal = true;
}

View File

@ -1186,7 +1186,9 @@ void Message::draw(Painter &p, const PaintContext &context) const {
(g.height() - size->height()) / 2,
0,
st::historyFastShareBottom);
const auto fastShareLeft = g.left() + g.width() + st::historyFastShareLeft;
const auto fastShareLeft = hasRightLayout()
? (g.left() - size->width() - st::historyFastShareLeft)
: (g.left() + g.width() + st::historyFastShareLeft);
const auto fastShareTop = data()->isSponsored()
? g.top() + fastShareSkip
: g.top() + g.height() - fastShareSkip - size->height();
@ -2199,7 +2201,9 @@ TextState Message::textState(
(g.height() - size->height()) / 2,
0,
st::historyFastShareBottom);
const auto fastShareLeft = g.left() + g.width() + st::historyFastShareLeft;
const auto fastShareLeft = hasRightLayout()
? (g.left() - size->width() - st::historyFastShareLeft)
: (g.left() + g.width() + st::historyFastShareLeft);
const auto fastShareTop = data()->isSponsored()
? g.top() + fastShareSkip
: g.top() + g.height() - fastShareSkip - size->height();
@ -2761,11 +2765,10 @@ Reactions::ButtonParameters Message::reactionButtonParameters(
const TextState &reactionState) const {
using namespace Reactions;
auto result = ButtonParameters{ .context = data()->fullId() };
const auto outbg = hasOutLayout();
const auto outsideBubble = (!_comments && !embedReactionsInBubble());
const auto geometry = countGeometry();
result.pointer = position;
const auto onTheLeft = (outbg && !delegate()->elementIsChatWide());
const auto onTheLeft = hasRightLayout();
const auto keyboard = data()->inlineReplyKeyboard();
const auto keyboardHeight = keyboard
@ -3755,7 +3758,7 @@ QRect Message::countGeometry() const {
const auto availableWidth = width()
- st::msgMargin.left()
- (centeredView ? st::msgMargin.left() : st::msgMargin.right());
auto contentLeft = (outbg && !delegate()->elementIsChatWide())
auto contentLeft = hasRightLayout()
? st::msgMargin.right()
: st::msgMargin.left();
auto contentWidth = availableWidth;
@ -3809,7 +3812,7 @@ Ui::BubbleRounding Message::countMessageRounding() const {
|| (keyboard != nullptr)
|| item->isFakeBotAbout()
|| (context() == Context::Replies && item->isDiscussionPost());
const auto right = !delegate()->elementIsChatWide() && hasOutLayout();
const auto right = hasRightLayout();
using Corner = Ui::BubbleCornerRounding;
return Ui::BubbleRounding{
.topLeft = (smallTop && !right) ? Corner::Small : Corner::Large,
@ -4009,7 +4012,7 @@ int Message::resizeContentGetHeight(int newWidth) {
: contentWidth;
newHeight += st::mediaInBubbleSkip
+ _reactions->resizeGetHeight(reactionsWidth);
if (hasOutLayout() && !delegate()->elementIsChatWide()) {
if (hasRightLayout()) {
_reactions->flipToRight();
}
}

View File

@ -259,7 +259,9 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
InfoDisplayType::Image);
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
}
@ -376,7 +378,9 @@ TextState ExtendedPreview::textState(QPoint point, StateRequest request) const {
return bottomInfoResult;
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink(point

View File

@ -364,7 +364,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
auto paintx = 0, painty = 0, paintw = width(), painth = height();
auto captionw = paintw - st::msgPadding.left() - st::msgPadding.right();
const bool bubble = _parent->hasBubble();
const auto outbg = context.outbg;
const auto rightLayout = _parent->hasRightLayout();
const auto inWebPage = (_parent->media() != this);
const auto isRound = _data->isVideoMessage();
const auto botTop = _parent->Get<FakeBotAboutTop>();
@ -389,9 +389,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto via = unwrapped ? item->Get<HistoryMessageVia>() : nullptr;
const auto reply = unwrapped ? _parent->Get<Reply>() : nullptr;
const auto forwarded = unwrapped ? item->Get<HistoryMessageForwarded>() : nullptr;
const auto rightAligned = unwrapped
&& outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = unwrapped && rightLayout;
if (via || reply || forwarded) {
usew = maxWidth() - additionalWidth(reply, via, forwarded);
if (rightAligned) {
@ -770,7 +768,9 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto rightActionWidth = size
? size->width()
: _transcribe->size().width();
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = rightLayout
? (paintx + usex - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = fullBottom
- st::historyFastShareBottom
- (size ? size->height() : 0);
@ -789,8 +789,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
if (_transcribe) {
paintTranscribe(p, fastShareLeft, fastShareTop, true, context);
}
}
if (rightAligned && _transcribe) {
} else if (rightAligned && _transcribe) {
paintTranscribe(p, usex, fullBottom, false, context);
}
}
@ -1010,7 +1009,7 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
}
painth -= st::mediaCaptionSkip;
}
const auto outbg = _parent->hasOutLayout();
const auto rightLayout = _parent->hasRightLayout();
const auto inWebPage = (_parent->media() != this);
const auto isRound = _data->isVideoMessage();
const auto unwrapped = isUnwrapped();
@ -1019,9 +1018,7 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
const auto via = unwrapped ? item->Get<HistoryMessageVia>() : nullptr;
const auto reply = unwrapped ? _parent->Get<Reply>() : nullptr;
const auto forwarded = unwrapped ? item->Get<HistoryMessageForwarded>() : nullptr;
const auto rightAligned = unwrapped
&& outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = unwrapped && rightLayout;
if (via || reply || forwarded) {
usew = maxWidth() - additionalWidth(reply, via, forwarded);
if (rightAligned) {
@ -1158,7 +1155,9 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto rightActionWidth = size->width();
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx + usex - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = fullBottom
- st::historyFastShareBottom
- size->height();
@ -1532,9 +1531,7 @@ QRect Gif::contentRectForReactions() const {
}
auto paintx = 0, painty = 0, paintw = width(), painth = height();
auto usex = 0, usew = paintw;
const auto outbg = _parent->hasOutLayout();
const auto rightAligned = outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto item = _parent->data();
const auto via = item->Get<HistoryMessageVia>();
const auto reply = _parent->Get<Reply>();
@ -1573,9 +1570,7 @@ QPoint Gif::resolveCustomInfoRightBottom() const {
maxRight -= st::msgMargin.left();
}
const auto infoWidth = _parent->infoWidth();
const auto outbg = _parent->hasOutLayout();
const auto rightAligned = outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
if (!rightAligned) {
// This is just some arbitrary point,
// the main idea is to make info left aligned here.

View File

@ -235,7 +235,9 @@ void Location::draw(Painter &p, const PaintContext &context) const {
paintx * 2 + paintw,
InfoDisplayType::Image);
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
}
@ -331,7 +333,9 @@ TextState Location::textState(QPoint point, StateRequest request) const {
return bottomInfoResult;
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink(point

View File

@ -427,7 +427,9 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
InfoDisplayType::Image);
}
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (-size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, width());
}
@ -501,7 +503,9 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const {
return bottomInfoResult;
}
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (-size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink(point

View File

@ -81,8 +81,7 @@ QSize UnwrappedMedia::countCurrentSize(int newWidth) {
if (_parent->media() != this) {
return { newWidth, newHeight };
}
if (_parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide()) {
if (_parent->hasRightLayout()) {
// Add some height to isolated emoji for the timestamp info.
const auto infoHeight = st::msgDateImgPadding.y() * 2
+ st::msgDateFont->height;
@ -137,8 +136,7 @@ void UnwrappedMedia::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
return;
}
const auto rightAligned = context.outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto inWebPage = (_parent->media() != this);
const auto item = _parent->data();
auto usex = 0;
@ -248,8 +246,7 @@ void UnwrappedMedia::drawSurrounding(
const HistoryMessageForwarded *forwarded) const {
const auto st = context.st;
const auto sti = context.imageStyle();
const auto rightAligned = context.outbg
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto rightActionSize = _parent->rightActionSize();
const auto fullRight = calculateFullRight(inner);
auto fullBottom = height();
@ -262,6 +259,7 @@ void UnwrappedMedia::drawSurrounding(
inner.x() * 2 + inner.width(),
InfoDisplayType::Background);
}
auto replyLeft = 0;
auto replyRight = 0;
auto rectw = _additionalOnTop
? std::min(width() - st::msgReplyPadding.left(), additionalWidth(topic, reply, via, forwarded))
@ -340,11 +338,15 @@ void UnwrappedMedia::drawSurrounding(
}
reply->paint(p, _parent, context, rectx, recty, rectw, false);
}
replyLeft = rectx;
replyRight = rectx + rectw;
}
}
if (rightActionSize) {
const auto position = calculateFastActionPosition(
inner,
rightAligned,
replyLeft,
replyRight,
reply ? reply->height() : 0,
fullBottom,
@ -360,8 +362,7 @@ PointState UnwrappedMedia::pointState(QPoint point) const {
return PointState::Outside;
}
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto inWebPage = (_parent->media() != this);
auto usex = 0;
auto usew = _contentSize.width();
@ -394,8 +395,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
return result;
}
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto inWebPage = (_parent->media() != this);
const auto item = _parent->data();
auto usex = 0;
@ -420,6 +420,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
const auto reply = inWebPage ? nullptr : _parent->Get<Reply>();
const auto topic = inWebPage ? nullptr : _parent->displayedTopicButton();
const auto forwarded = inWebPage ? nullptr : getDisplayedForwardedInfo();
auto replyLeft = 0;
auto replyRight = 0;
auto rectw = _additionalOnTop
? std::min(width() - st::msgReplyPadding.left(), additionalWidth(topic, reply, via, forwarded))
@ -491,7 +492,8 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
reply->createRippleAnimation(_parent, replyRect.size());
}
}
replyRight = rectx + rectw - st::msgReplyPadding.right();
replyLeft = rectx;
replyRight = rectx + rectw;
}
}
const auto fullRight = calculateFullRight(inner);
@ -509,6 +511,9 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
}
if (rightActionSize) {
const auto position = calculateFastActionPosition(
inner,
rightAligned,
replyLeft,
replyRight,
reply ? reply->height() : 0,
fullBottom,
@ -544,8 +549,7 @@ QRect UnwrappedMedia::contentRectForReactions() const {
if (inWebPage) {
return QRect(0, 0, width(), height());
}
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
auto usex = 0;
auto usew = _contentSize.width();
accumulate_max(usew, _parent->reactionsOptimalWidth());
@ -589,8 +593,7 @@ std::unique_ptr<StickerPlayer> UnwrappedMedia::stickerTakePlayer(
}
int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
const auto infoWidth = _parent->infoWidth()
+ st::msgDateImgPadding.x() * 2
+ st::msgReplyPadding.left();
@ -606,13 +609,19 @@ int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
auto fullRight = inner.x()
+ inner.width()
+ (rightAligned ? 0 : infoWidth);
if (fullRight + rightActionWidth + rightSkip > _parent->width()) {
fullRight = _parent->width() - rightActionWidth - rightSkip;
const auto rightActionSkip = rightAligned ? 0 : rightActionWidth;
if (fullRight + rightActionSkip + rightSkip > _parent->width()) {
fullRight = _parent->width()
- (rightAligned ? 0 : rightActionSkip)
- rightSkip;
}
return fullRight;
}
QPoint UnwrappedMedia::calculateFastActionPosition(
QRect inner,
bool rightAligned,
int replyLeft,
int replyRight,
int replyHeight,
int fullBottom,
@ -623,9 +632,12 @@ QPoint UnwrappedMedia::calculateFastActionPosition(
- size.height());
const auto doesRightActionHitReply = replyRight
&& (fastShareTop < replyHeight);
const auto fastShareLeft = ((doesRightActionHitReply
? replyRight
: fullRight) + st::historyFastShareLeft);
const auto fastShareLeft = rightAligned
? ((doesRightActionHitReply ? replyLeft : inner.x())
- size.width()
- st::historyFastShareLeft)
: ((doesRightActionHitReply ? replyRight : fullRight)
+ st::historyFastShareLeft);
return QPoint(fastShareLeft, fastShareTop);
}
@ -635,8 +647,7 @@ bool UnwrappedMedia::needInfoDisplay() const {
|| _parent->isUnderCursor()
|| _parent->rightActionSize()
|| _parent->isLastAndSelfMessage()
|| (_parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide()
|| (_parent->hasRightLayout()
&& _content->alwaysShowOutTimestamp());
}

View File

@ -146,6 +146,9 @@ private:
int calculateFullRight(const QRect &inner) const;
QPoint calculateFastActionPosition(
QRect inner,
bool rightAligned,
int replyLeft,
int replyRight,
int replyHeight,
int fullBottom,

View File

@ -455,7 +455,9 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
InfoDisplayType::Image);
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
}
@ -731,7 +733,9 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
return bottomInfoResult;
}
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink(point

View File

@ -403,8 +403,7 @@ bool Sticker::mirrorHorizontal() const {
if (!hasPremiumEffect()) {
return false;
}
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();
const auto rightAligned = _parent->hasRightLayout();
return !rightAligned;
}