Show comments button for unwrapped medias.

This commit is contained in:
John Preston 2020-09-17 19:25:06 +03:00
parent 1a40f2b3ef
commit 7862443fcb
13 changed files with 159 additions and 76 deletions

View File

@ -530,6 +530,7 @@ historyFastShareLeft: 13px;
historyFastShareBottom: 5px;
historyFastShareIcon: icon {{ "fast_share", msgServiceFg, point(4px, 3px)}};
historyGoToOriginalIcon: icon {{ "title_back-flip_horizontal", msgServiceFg, point(8px, 7px) }};
historyFastCommentsIcon: icon {{ "history_comments", msgServiceFg }};
historySavedFont: font(semibold 14px);

View File

@ -44,6 +44,7 @@ struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, Histor
std::vector<PeerId> recentRepliers;
Part views;
Part replies;
Part repliesSmall;
ChannelId commentsChannelId = 0;
MsgId commentsRootId = 0;
MsgId commentsReadTillId = 0;

View File

@ -1018,10 +1018,16 @@ void HistoryMessage::setupForwardedComponent(const CreateConfig &config) {
}
void HistoryMessage::refreshMedia(const MTPMessageMedia *media) {
const auto was = (_media != nullptr);
_media = nullptr;
if (media) {
setMedia(*media);
}
if (was || _media) {
if (const auto views = Get<HistoryMessageViews>()) {
refreshRepliesText(views);
}
}
}
void HistoryMessage::refreshSentMedia(const MTPMessageMedia *media) {
@ -1567,6 +1573,11 @@ void HistoryMessage::refreshRepliesText(
: tr::lng_comments_open_none(tr::now);
views->replies.textWidth = st::semiboldFont->width(
views->replies.text);
views->repliesSmall.text = (views->replies.count > 0)
? Lang::FormatCountToShort(views->replies.count).string
: QString();
views->repliesSmall.textWidth = st::semiboldFont->width(
views->repliesSmall.text);
} else {
views->replies.text = (views->replies.count > 0)
? Lang::FormatCountToShort(views->replies.count).string

View File

@ -599,8 +599,8 @@ bool Element::displayFastReply() const {
return false;
}
bool Element::displayRightAction() const {
return false;
std::optional<QSize> Element::rightActionSize() const {
return std::nullopt;
}
void Element::drawRightAction(

View File

@ -262,7 +262,7 @@ public:
virtual bool hasBubble() const;
virtual bool hasFastReply() const;
virtual bool displayFastReply() const;
virtual bool displayRightAction() const;
virtual std::optional<QSize> rightActionSize() const;
virtual void drawRightAction(
Painter &p,
int left,

View File

@ -201,6 +201,10 @@ struct Message::CommentsButton {
QImage cachedUserpics;
ClickHandlerPtr link;
QPoint lastPoint;
QString rightActionCountString;
int rightActionCount = 0;
int rightActionCountWidth = 0;
};
LogEntryOriginal::LogEntryOriginal() = default;
@ -611,13 +615,13 @@ void Message::draw(
p.setOpacity(o);
}
}
if (displayRightAction()) {
if (const auto size = rightActionSize()) {
const auto fastShareSkip = std::clamp(
(gBubble.height() - st::historyFastShareSize) / 2,
(gBubble.height() - size->height()) / 2,
0,
st::historyFastShareBottom);
const auto fastShareLeft = g.left() + g.width() + st::historyFastShareLeft;
const auto fastShareTop = g.top() + gBubble.height() - fastShareSkip - st::historyFastShareSize;
const auto fastShareTop = g.top() + gBubble.height() - fastShareSkip - size->height();
drawRightAction(p, fastShareLeft, fastShareTop, width());
}
@ -1227,18 +1231,18 @@ TextState Message::textState(
}
}
checkForPointInTime();
if (displayRightAction()) {
if (const auto size = rightActionSize()) {
const auto fastShareSkip = snap(
(gBubble.height() - st::historyFastShareSize) / 2,
(gBubble.height() - size->height()) / 2,
0,
st::historyFastShareBottom);
const auto fastShareLeft = g.left() + g.width() + st::historyFastShareLeft;
const auto fastShareTop = g.top() + gBubble.height() - fastShareSkip - st::historyFastShareSize;
const auto fastShareTop = g.top() + gBubble.height() - fastShareSkip - size->height();
if (QRect(
fastShareLeft,
fastShareTop,
st::historyFastShareSize,
st::historyFastShareSize
size->width(),
size->height()
).contains(point)) {
result.link = rightActionLink();
}
@ -1276,16 +1280,7 @@ bool Message::getStateCommentsButton(
return false;
}
if (!_comments->link && data()->repliesAreComments()) {
const auto fullId = data()->fullId();
_comments->link = std::make_shared<LambdaClickHandler>([=] {
if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) {
if (const auto item = controller->session().data().message(fullId)) {
controller->showRepliesForMessage(item->history(), item->id);
}
}
}
});
_comments->link = createGoToCommentsLink();
} else if (!_comments->link && data()->externalReply()) {
_comments->link = rightActionLink();
}
@ -1294,6 +1289,19 @@ bool Message::getStateCommentsButton(
return true;
}
ClickHandlerPtr Message::createGoToCommentsLink() const {
const auto fullId = data()->fullId();
return std::make_shared<LambdaClickHandler>([=] {
if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) {
if (const auto item = controller->session().data().message(fullId)) {
controller->showRepliesForMessage(item->history(), item->id);
}
}
}
});
}
bool Message::getStateFromName(
QPoint point,
QRect &trect,
@ -2017,8 +2025,28 @@ bool Message::displayFastReply() const {
&& !delegate()->elementInSelectionMode();
}
bool Message::displayRightAction() const {
return displayFastShare() || displayGoToOriginal();
bool Message::displayRightActionComments() const {
return data()->repliesAreComments()
&& media()
&& media()->isDisplayed()
&& media()->customInfoLayout();
}
std::optional<QSize> Message::rightActionSize() const {
if (displayRightActionComments()) {
const auto views = data()->Get<HistoryMessageViews>();
Assert(views != nullptr);
return (views->repliesSmall.textWidth > 0)
? QSize(
std::max(
st::historyFastShareSize,
2 * st::historyFastShareBottom + views->repliesSmall.textWidth),
st::historyFastShareSize + st::historyFastShareBottom + st::semiboldFont->height)
: QSize(st::historyFastShareSize, st::historyFastShareSize);
}
return (displayFastShare() || displayGoToOriginal())
? QSize(st::historyFastShareSize, st::historyFastShareSize)
: std::optional<QSize>();
}
bool Message::displayFastShare() const {
@ -2060,18 +2088,44 @@ void Message::drawRightAction(
int left,
int top,
int outerWidth) const {
const auto size = rightActionSize();
p.setPen(Qt::NoPen);
p.setBrush(st::msgServiceBg);
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(style::rtlrect(
const auto rect = style::rtlrect(
left,
top,
st::historyFastShareSize,
st::historyFastShareSize,
outerWidth));
size->width(),
size->height(),
outerWidth);
const auto usual = st::historyFastShareSize;
if (size->width() == size->height() && size->width() == usual) {
p.drawEllipse(rect);
} else {
p.drawRoundedRect(rect, usual / 2, usual / 2);
}
}
if (displayFastShare()) {
if (displayRightActionComments()) {
const auto &icon = st::historyFastCommentsIcon;
icon.paint(
p,
left + (size->width() - icon.width()) / 2,
top + (st::historyFastShareSize - icon.height()) / 2,
outerWidth);
const auto views = data()->Get<HistoryMessageViews>();
Assert(views != nullptr);
if (views->repliesSmall.textWidth > 0) {
p.setPen(st::msgServiceFg);
p.setFont(st::semiboldFont);
p.drawTextLeft(
left + (size->width() - views->repliesSmall.textWidth) / 2,
top + st::historyFastShareSize,
outerWidth,
views->repliesSmall.text,
views->repliesSmall.textWidth);
}
} else if (displayFastShare()) {
st::historyFastShareIcon.paint(p, left, top, outerWidth);
} else {
st::historyGoToOriginalIcon.paint(p, left, top, outerWidth);
@ -2080,6 +2134,10 @@ void Message::drawRightAction(
ClickHandlerPtr Message::rightActionLink() const {
if (!_rightActionLink) {
if (displayRightActionComments()) {
_rightActionLink = createGoToCommentsLink();
return _rightActionLink;
}
const auto owner = &data()->history()->owner();
const auto itemId = data()->fullId();
const auto forwarded = data()->Get<HistoryMessageForwarded>();
@ -2231,8 +2289,8 @@ QRect Message::countGeometry() const {
auto contentWidth = availableWidth;
if (hasFromPhoto()) {
contentLeft += st::msgPhotoSkip;
if (displayRightAction()) {
contentWidth -= st::msgPhotoSkip;
if (const auto size = rightActionSize()) {
contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize);
}
//} else if (!Adaptive::Wide() && !out() && !fromChannel() && st::msgPhotoSkip - (hmaxwidth - hwidth) > 0) {
// contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth);
@ -2276,8 +2334,10 @@ int Message::resizeContentGetHeight(int newWidth) {
// This code duplicates countGeometry() but also resizes media.
auto contentWidth = newWidth - (st::msgMargin.left() + st::msgMargin.right());
if (hasFromPhoto() && displayRightAction()) {
contentWidth -= st::msgPhotoSkip;
if (hasFromPhoto()) {
if (const auto size = rightActionSize()) {
contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize);
}
}
accumulate_min(contentWidth, maxWidth());
_bubbleWidthLimit = std::max(st::msgMaxWidth, monospaceMaxWidth());

View File

@ -93,7 +93,8 @@ public:
bool hasBubble() const override;
bool hasFastReply() const override;
bool displayFastReply() const override;
bool displayRightAction() const override;
bool displayRightActionComments() const;
std::optional<QSize> rightActionSize() const override;
void drawRightAction(
Painter &p,
int left,
@ -186,6 +187,7 @@ private:
WebPage *logEntryOriginal() const;
[[nodiscard]] ClickHandlerPtr createGoToCommentsLink() const;
[[nodiscard]] ClickHandlerPtr psaTooltipLink() const;
void psaTooltipToggled(bool shown) const;

View File

@ -632,11 +632,11 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
if (isRound || needInfoDisplay()) {
_parent->drawInfo(p, fullRight, fullBottom, 2 * paintx + paintw, selected, isRound ? InfoDisplayType::Background : InfoDisplayType::Image);
}
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
if (fastShareLeft + st::historyFastShareSize > maxRight) {
fastShareLeft = (fullRight - st::historyFastShareSize - st::msgDateImgDelta);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (fastShareLeft + size->width() > maxRight) {
fastShareLeft = (fullRight - size->width() - st::msgDateImgDelta);
fastShareTop -= (st::msgDateImgDelta + st::msgDateImgPadding.y() + st::msgDateFont->height + st::msgDateImgPadding.y());
}
_parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw);
@ -860,14 +860,14 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
result.cursor = CursorState::Date;
}
}
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
if (fastShareLeft + st::historyFastShareSize > maxRight) {
fastShareLeft = (fullRight - st::historyFastShareSize - st::msgDateImgDelta);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (fastShareLeft + size->width() > maxRight) {
fastShareLeft = (fullRight - size->width() - st::msgDateImgDelta);
fastShareTop -= st::msgDateImgDelta + st::msgDateImgPadding.y() + st::msgDateFont->height + st::msgDateImgPadding.y();
}
if (QRect(fastShareLeft, fastShareTop, st::historyFastShareSize, st::historyFastShareSize).contains(point)) {
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
}
}

View File

@ -210,9 +210,9 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
auto fullRight = paintx + paintw;
auto fullBottom = height();
_parent->drawInfo(p, fullRight, fullBottom, paintx * 2 + paintw, selected, InfoDisplayType::Image);
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw);
}
}
@ -278,10 +278,10 @@ TextState Location::textState(QPoint point, StateRequest request) const {
if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayType::Image)) {
result.cursor = CursorState::Date;
}
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
if (QRect(fastShareLeft, fastShareTop, st::historyFastShareSize, st::historyFastShareSize).contains(point)) {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
}
}

View File

@ -216,9 +216,9 @@ void GroupedMedia::draw(
if (needInfoDisplay()) {
_parent->drawInfo(p, fullRight, fullBottom, width(), selected, InfoDisplayType::Image);
}
if (!_parent->hasBubble() && _parent->displayRightAction()) {
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, fastShareLeft, fastShareTop, width());
}
}
@ -272,10 +272,10 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const {
if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayType::Image)) {
result.cursor = CursorState::Date;
}
if (!_parent->hasBubble() && _parent->displayRightAction()) {
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
if (QRect(fastShareLeft, fastShareTop, st::historyFastShareSize, st::historyFastShareSize).contains(point)) {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
}
}

View File

@ -66,6 +66,11 @@ QSize UnwrappedMedia::countOptimalSize() {
+ infoHeight;
minHeight = std::max(minHeight, minimal);
}
if (const auto size = _parent->rightActionSize()) {
minHeight = std::max(
minHeight,
st::historyFastShareBottom + size->height());
}
}
return { maxWidth, minHeight };
}
@ -181,7 +186,7 @@ void UnwrappedMedia::drawSurrounding(
const HistoryMessageReply *reply,
const HistoryMessageForwarded *forwarded) const {
const auto rightAligned = _parent->hasOutLayout() && !Core::App().settings().chatWide();
const auto rightAction = _parent->displayRightAction();
const auto rightActionSize = _parent->rightActionSize();
const auto fullRight = calculateFullRight(inner);
auto fullBottom = height();
if (needInfoDisplay()) {
@ -224,11 +229,12 @@ void UnwrappedMedia::drawSurrounding(
}
replyRight = rectx + rectw;
}
if (rightAction) {
if (rightActionSize) {
const auto position = calculateFastActionPosition(
fullBottom,
replyRight,
fullRight);
fullRight,
*rightActionSize);
const auto outer = 2 * inner.x() + inner.width();
_parent->drawRightAction(p, position.x(), position.y(), outer);
}
@ -355,18 +361,18 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
replyRight = rectx + rectw - st::msgReplyPadding.right();
}
const auto fullRight = calculateFullRight(inner);
const auto rightAction = _parent->displayRightAction();
const auto rightActionSize = _parent->rightActionSize();
auto fullBottom = height();
if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayType::Background)) {
result.cursor = CursorState::Date;
}
if (rightAction) {
const auto size = st::historyFastShareSize;
if (rightActionSize) {
const auto position = calculateFastActionPosition(
fullBottom,
replyRight,
fullRight);
if (QRect(position.x(), position.y(), size, size).contains(point)) {
fullRight,
*rightActionSize);
if (QRect(position.x(), position.y(), rightActionSize->width(), rightActionSize->height()).contains(point)) {
result.link = _parent->rightActionLink();
return result;
}
@ -396,9 +402,10 @@ int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
const auto infoWidth = _parent->infoWidth()
+ st::msgDateImgPadding.x() * 2
+ st::msgReplyPadding.left();
const auto rightActionWidth = _parent->displayRightAction()
const auto rightActionSize = _parent->rightActionSize();
const auto rightActionWidth = rightActionSize
? (st::historyFastShareLeft * 2
+ st::historyFastShareSize
+ rightActionSize->width()
+ st::msgPadding.left()
+ (_parent->hasFromPhoto()
? st::msgMargin.right()
@ -414,13 +421,13 @@ int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
}
QPoint UnwrappedMedia::calculateFastActionPosition(
int fullBottom,
int replyRight,
int fullRight) const {
const auto size = st::historyFastShareSize;
int fullBottom,
int replyRight,
int fullRight,
QSize size) const {
const auto fastShareTop = (fullBottom
- st::historyFastShareBottom
- size);
- size.height());
const auto doesRightActionHitReply = replyRight && (fastShareTop <
st::msgReplyBarSize.height()
+ st::msgReplyPadding.top()
@ -434,7 +441,7 @@ QPoint UnwrappedMedia::calculateFastActionPosition(
bool UnwrappedMedia::needInfoDisplay() const {
return (_parent->data()->id < 0)
|| (_parent->isUnderCursor())
|| (_parent->displayRightAction())
|| (_parent->rightActionSize())
|| (_parent->isLastAndSelfMessage())
|| (_parent->hasOutLayout()
&& !Core::App().settings().chatWide()

View File

@ -130,11 +130,12 @@ private:
const HistoryMessageReply *reply,
const HistoryMessageForwarded *forwarded) const;
inline int calculateFullRight(const QRect &inner) const;
inline QPoint calculateFastActionPosition(
int calculateFullRight(const QRect &inner) const;
QPoint calculateFastActionPosition(
int fullBottom,
int replyRight,
int fullRight) const;
int fullRight,
QSize size) const;
const HistoryMessageForwarded *getDisplayedForwardedInfo() const;

View File

@ -322,9 +322,9 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
if (needInfoDisplay()) {
_parent->drawInfo(p, fullRight, fullBottom, 2 * paintx + paintw, selected, InfoDisplayType::Image);
}
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw);
}
}
@ -450,10 +450,10 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayType::Image)) {
result.cursor = CursorState::Date;
}
if (!bubble && _parent->displayRightAction()) {
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
if (QRect(fastShareLeft, fastShareTop, st::historyFastShareSize, st::historyFastShareSize).contains(point)) {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
}
}