diff --git a/Telegram/Resources/icons/chat/link_photo_enlarge.png b/Telegram/Resources/icons/chat/link_photo_enlarge.png new file mode 100644 index 0000000000..c4ba35289e Binary files /dev/null and b/Telegram/Resources/icons/chat/link_photo_enlarge.png differ diff --git a/Telegram/Resources/icons/chat/link_photo_enlarge@2x.png b/Telegram/Resources/icons/chat/link_photo_enlarge@2x.png new file mode 100644 index 0000000000..02e1328ed3 Binary files /dev/null and b/Telegram/Resources/icons/chat/link_photo_enlarge@2x.png differ diff --git a/Telegram/Resources/icons/chat/link_photo_enlarge@3x.png b/Telegram/Resources/icons/chat/link_photo_enlarge@3x.png new file mode 100644 index 0000000000..3dbc8aad42 Binary files /dev/null and b/Telegram/Resources/icons/chat/link_photo_enlarge@3x.png differ diff --git a/Telegram/SourceFiles/data/data_web_page.cpp b/Telegram/SourceFiles/data/data_web_page.cpp index e8eef89784..95b042775c 100644 --- a/Telegram/SourceFiles/data/data_web_page.cpp +++ b/Telegram/SourceFiles/data/data_web_page.cpp @@ -391,3 +391,7 @@ bool WebPageData::computeDefaultSmallMedia() const { } return false; } + +bool WebPageData::suggestEnlargePhoto() const { + return !siteName.isEmpty() || !title.isEmpty() || !description.empty(); +} diff --git a/Telegram/SourceFiles/data/data_web_page.h b/Telegram/SourceFiles/data/data_web_page.h index 9aea4a0f58..04f16a7b66 100644 --- a/Telegram/SourceFiles/data/data_web_page.h +++ b/Telegram/SourceFiles/data/data_web_page.h @@ -90,6 +90,7 @@ struct WebPageData { [[nodiscard]] QString displayedSiteName() const; [[nodiscard]] bool computeDefaultSmallMedia() const; + [[nodiscard]] bool suggestEnlargePhoto() const; const WebPageId id = 0; WebPageType type = WebPageType::None; diff --git a/Telegram/SourceFiles/history/view/history_view_cursor_state.h b/Telegram/SourceFiles/history/view/history_view_cursor_state.h index 82fcda9547..d5bcaa6f94 100644 --- a/Telegram/SourceFiles/history/view/history_view_cursor_state.h +++ b/Telegram/SourceFiles/history/view/history_view_cursor_state.h @@ -22,6 +22,7 @@ enum class CursorState : char { None, Text, Date, + Enlarge, Forwarded, }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index b3d79c6fe2..85a2997a8b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_click_handler.h" #include "data/data_file_origin.h" #include "data/data_auto_download.h" +#include "data/data_web_page.h" #include "core/application.h" #include "styles/style_chat.h" @@ -242,6 +243,7 @@ QSize Photo::countCurrentSize(int newWidth) { maxWidth()); newWidth = qMax(pix.width(), minWidth); auto newHeight = qMax(pix.height(), st::minPhotoSize); + auto imageHeight = newHeight; if (_parent->hasBubble() && !_caption.isEmpty()) { auto captionMaxWidth = st::msgPadding.left() + _caption.maxWidth() @@ -252,7 +254,7 @@ QSize Photo::countCurrentSize(int newWidth) { } const auto maxWithCaption = qMin(st::msgMaxWidth, captionMaxWidth); newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth); - newHeight = adjustHeightForLessCrop( + imageHeight = newHeight = adjustHeightForLessCrop( dimensions, { newWidth, newHeight }); const auto captionw = newWidth @@ -266,6 +268,15 @@ QSize Photo::countCurrentSize(int newWidth) { newHeight += st::msgPadding.bottom(); } } + const auto enlargeInner = st::historyPageEnlargeSize; + const auto enlargeOuter = 2 * st::historyPageEnlargeSkip + enlargeInner; + const auto showEnlarge = (_parent->media() != this) + && _parent->data()->media() + && _parent->data()->media()->webpage() + && _parent->data()->media()->webpage()->suggestEnlargePhoto() + && (newWidth >= enlargeOuter) + && (imageHeight >= enlargeOuter); + _showEnlarge = showEnlarge ? 1 : 0; return { newWidth, newHeight }; } @@ -351,15 +362,16 @@ void Photo::draw(Painter &p, const PaintContext &context) const { fillImageOverlay(p, rthumb, rounding, context); } } - if (radial || (!loaded && !_data->loading())) { - const auto radialOpacity = (radial && loaded && !_data->uploading()) - ? _animation->radial.opacity() : - 1.; - const auto innerSize = st::msgFileLayout.thumbSize; - QRect inner(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize); + + const auto showEnlarge = loaded && _showEnlarge; + const auto paintInCenter = (radial || (!loaded && !_data->loading())); + if (paintInCenter || showEnlarge) { p.setPen(Qt::NoPen); if (context.selected()) { p.setBrush(st->msgDateImgBgSelected()); + } else if (showEnlarge) { + const auto over = ClickHandler::showAsActive(_openl); + p.setBrush(over ? st->msgDateImgBgOver() : st->msgDateImgBg()); } else if (isThumbAnimation()) { const auto over = _animation->a_thumbOver.value(1.); p.setBrush(anim::brush(st->msgDateImgBg(), st->msgDateImgBgOver(), over)); @@ -367,6 +379,13 @@ void Photo::draw(Painter &p, const PaintContext &context) const { const auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel); p.setBrush(over ? st->msgDateImgBgOver() : st->msgDateImgBg()); } + } + if (paintInCenter) { + const auto radialOpacity = (radial && loaded && !_data->uploading()) + ? _animation->radial.opacity() : + 1.; + const auto innerSize = st::msgFileLayout.thumbSize; + QRect inner(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize); p.setOpacity(radialOpacity * p.opacity()); @@ -386,6 +405,13 @@ void Photo::draw(Painter &p, const PaintContext &context) const { _animation->radial.draw(p, rinner, st::msgFileRadialLine, sti->historyFileThumbRadialFg); } } + if (showEnlarge) { + auto hq = PainterHighQualityEnabler(p); + const auto rect = enlargeRect(); + const auto radius = st::historyPageEnlargeRadius; + p.drawRoundedRect(rect, radius, radius); + sti->historyPageEnlarge.paintInCenter(p, rect); + } // date if (!_caption.isEmpty()) { @@ -631,6 +657,18 @@ QSize Photo::photoSize() const { return QSize(_data->width(), _data->height()); } +QRect Photo::enlargeRect() const { + const auto skip = st::historyPageEnlargeSkip; + const auto enlargeInner = st::historyPageEnlargeSize; + const auto enlargeOuter = 2 * skip + enlargeInner; + return { + width() - enlargeOuter + skip, + skip, + enlargeInner, + enlargeInner, + }; +} + TextState Photo::textState(QPoint point, StateRequest request) const { auto result = TextState(_parent); @@ -673,6 +711,11 @@ TextState Photo::textState(QPoint point, StateRequest request) const { : _data->loading() ? _cancell : _savel; + if (_showEnlarge + && result.link == _openl + && enlargeRect().contains(point)) { + result.cursor = CursorState::Enlarge; + } } if (_caption.isEmpty() && _parent->media() == this) { auto fullRight = paintx + paintw; diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.h b/Telegram/SourceFiles/history/view/media/history_view_photo.h index 7213dca210..4b123cc7c1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.h +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.h @@ -163,6 +163,7 @@ private: QPoint photoPosition) const; [[nodiscard]] QSize photoSize() const; + [[nodiscard]] QRect enlargeRect() const; void togglePollingStory(bool enabled) const; @@ -178,6 +179,7 @@ private: mutable uint32 _imageCacheForum : 1 = 0; mutable uint32 _imageCacheBlurred : 1 = 0; mutable uint32 _pollingStory : 1 = 0; + mutable uint32 _showEnlarge : 1 = 0; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 56299bf451..c622585b9a 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -783,7 +783,11 @@ TextState WebPage::textState(QPoint point, StateRequest request) const { auto attachTop = tshift - bubble.top(); if (rtl()) attachLeft = width() - attachLeft - _attach->width(); result = _attach->textState(point - QPoint(attachLeft, attachTop), request); - result.link = replaceAttachLink(result.link); + if (result.cursor == CursorState::Enlarge) { + result.cursor = CursorState::None; + } else { + result.link = replaceAttachLink(result.link); + } } } if (!result.link && outer.contains(point)) { diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index d4f189ac00..7567c501a8 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -640,6 +640,12 @@ historyPageButtonLine: 1px; historyPageButtonHeight: 36px; historyPageButtonPadding: margins(13px, 8px, 13px, 8px); +historyPageEnlarge: icon{{ "chat/link_photo_enlarge", historyFileThumbRadialFg }}; +historyPageEnlargeSelected: icon{{ "chat/link_photo_enlarge", historyFileThumbRadialFgSelected }}; +historyPageEnlargeSize: 36px; +historyPageEnlargeSkip: 4px; +historyPageEnlargeRadius: 8px; + historyCommentsButtonHeight: 40px; historyCommentsSkipLeft: 9px; historyCommentsSkipText: 10px; diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index 7bdebaee17..d85da4ec4f 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -505,6 +505,10 @@ ChatStyle::ChatStyle(rpl::producer colorIndices) { &MessageImageStyle::historyVideoMessageMute, st::historyVideoMessageMute, st::historyVideoMessageMuteSelected); + make( + &MessageImageStyle::historyPageEnlarge, + st::historyPageEnlarge, + st::historyPageEnlargeSelected); updateDarkValue(); } diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index 39f5a76e44..afa63a7ae2 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -117,6 +117,7 @@ struct MessageImageStyle { style::icon historyVideoDownload = { Qt::Uninitialized }; style::icon historyVideoCancel = { Qt::Uninitialized }; style::icon historyVideoMessageMute = { Qt::Uninitialized }; + style::icon historyPageEnlarge = { Qt::Uninitialized }; }; struct ReactionPaintInfo {