mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support displaying of video spoilers.
This commit is contained in:
parent
ae3659d15b
commit
3a38497c4c
2 changed files with 117 additions and 56 deletions
|
@ -92,6 +92,10 @@ Gif::Gif(
|
||||||
setDocumentLinks(_data, realParent);
|
setDocumentLinks(_data, realParent);
|
||||||
setStatusSize(Ui::FileStatusSizeReady);
|
setStatusSize(Ui::FileStatusSizeReady);
|
||||||
|
|
||||||
|
if (_spoiler) {
|
||||||
|
createSpoilerLink(_spoiler.get());
|
||||||
|
}
|
||||||
|
|
||||||
refreshCaption();
|
refreshCaption();
|
||||||
if ((_dataMedia = _data->activeMediaView())) {
|
if ((_dataMedia = _data->activeMediaView())) {
|
||||||
dataMediaCreated();
|
dataMediaCreated();
|
||||||
|
@ -328,9 +332,59 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
&& canBePlayed
|
&& canBePlayed
|
||||||
&& CanPlayInline(_data);
|
&& CanPlayInline(_data);
|
||||||
const auto activeRoundPlaying = activeRoundStreamed();
|
const auto activeRoundPlaying = activeRoundStreamed();
|
||||||
|
|
||||||
|
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 inWebPage = (_parent->media() != this);
|
||||||
|
const auto isRound = _data->isVideoMessage();
|
||||||
|
|
||||||
|
const auto rounding = inWebPage
|
||||||
|
? std::optional<Ui::BubbleRounding>()
|
||||||
|
: adjustedBubbleRoundingWithCaption(_caption);
|
||||||
|
if (bubble) {
|
||||||
|
if (!_caption.isEmpty()) {
|
||||||
|
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
||||||
|
if (isBubbleBottom()) {
|
||||||
|
painth -= st::msgPadding.bottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto usex = 0, usew = paintw;
|
||||||
|
const auto unwrapped = isUnwrapped();
|
||||||
|
const auto via = unwrapped ? item->Get<HistoryMessageVia>() : nullptr;
|
||||||
|
const auto reply = unwrapped ? _parent->displayedReply() : nullptr;
|
||||||
|
const auto forwarded = unwrapped ? item->Get<HistoryMessageForwarded>() : nullptr;
|
||||||
|
const auto rightAligned = unwrapped
|
||||||
|
&& outbg
|
||||||
|
&& !_parent->delegate()->elementIsChatWide();
|
||||||
|
if (via || reply || forwarded) {
|
||||||
|
usew = maxWidth() - additionalWidth(via, reply, forwarded);
|
||||||
|
if (rightAligned) {
|
||||||
|
usex = width() - usew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isRound) {
|
||||||
|
accumulate_min(usew, painth);
|
||||||
|
}
|
||||||
|
if (rtl()) usex = width() - usex - usew;
|
||||||
|
|
||||||
|
QRect rthumb(style::rtlrect(usex + paintx, painty, usew, painth, width()));
|
||||||
|
|
||||||
|
const auto revealed = (!isRound && _spoiler)
|
||||||
|
? _spoiler->revealAnimation.value(_spoiler->revealed ? 1. : 0.)
|
||||||
|
: 1.;
|
||||||
|
const auto fullHiddenBySpoiler = (revealed == 0.);
|
||||||
|
if (revealed < 1.) {
|
||||||
|
validateSpoilerImageCache(rthumb.size(), rounding);
|
||||||
|
}
|
||||||
|
|
||||||
const auto startPlay = autoplay
|
const auto startPlay = autoplay
|
||||||
&& !_streamed
|
&& !_streamed
|
||||||
&& !activeRoundPlaying;
|
&& !activeRoundPlaying
|
||||||
|
&& !fullHiddenBySpoiler;
|
||||||
if (startPlay) {
|
if (startPlay) {
|
||||||
const_cast<Gif*>(this)->playAnimation(true);
|
const_cast<Gif*>(this)->playAnimation(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -339,13 +393,6 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
const auto streamingMode = _streamed || activeRoundPlaying || autoplay;
|
const auto streamingMode = _streamed || activeRoundPlaying || autoplay;
|
||||||
const auto activeOwnPlaying = activeOwnStreamed();
|
const auto activeOwnPlaying = activeOwnStreamed();
|
||||||
|
|
||||||
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 inWebPage = (_parent->media() != this);
|
|
||||||
const auto isRound = _data->isVideoMessage();
|
|
||||||
const auto unwrapped = isUnwrapped();
|
|
||||||
auto displayMute = false;
|
auto displayMute = false;
|
||||||
const auto streamed = activeRoundPlaying
|
const auto streamed = activeRoundPlaying
|
||||||
? activeRoundPlaying
|
? activeRoundPlaying
|
||||||
|
@ -372,38 +419,6 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
const auto radial = isRadialAnimation()
|
const auto radial = isRadialAnimation()
|
||||||
|| (streamedForWaiting && streamedForWaiting->waitingShown());
|
|| (streamedForWaiting && streamedForWaiting->waitingShown());
|
||||||
|
|
||||||
const auto rounding = inWebPage
|
|
||||||
? std::optional<Ui::BubbleRounding>()
|
|
||||||
: adjustedBubbleRoundingWithCaption(_caption);
|
|
||||||
if (bubble) {
|
|
||||||
if (!_caption.isEmpty()) {
|
|
||||||
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
|
||||||
if (isBubbleBottom()) {
|
|
||||||
painth -= st::msgPadding.bottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto usex = 0, usew = paintw;
|
|
||||||
const auto via = unwrapped ? item->Get<HistoryMessageVia>() : nullptr;
|
|
||||||
const auto reply = unwrapped ? _parent->displayedReply() : nullptr;
|
|
||||||
const auto forwarded = unwrapped ? item->Get<HistoryMessageForwarded>() : nullptr;
|
|
||||||
const auto rightAligned = unwrapped
|
|
||||||
&& outbg
|
|
||||||
&& !_parent->delegate()->elementIsChatWide();
|
|
||||||
if (via || reply || forwarded) {
|
|
||||||
usew = maxWidth() - additionalWidth(via, reply, forwarded);
|
|
||||||
if (rightAligned) {
|
|
||||||
usex = width() - usew;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isRound) {
|
|
||||||
accumulate_min(usew, painth);
|
|
||||||
}
|
|
||||||
if (rtl()) usex = width() - usex - usew;
|
|
||||||
|
|
||||||
QRect rthumb(style::rtlrect(usex + paintx, painty, usew, painth, width()));
|
|
||||||
|
|
||||||
if (!bubble && !unwrapped) {
|
if (!bubble && !unwrapped) {
|
||||||
Assert(rounding.has_value());
|
Assert(rounding.has_value());
|
||||||
fillImageShadow(p, rthumb, *rounding, context);
|
fillImageShadow(p, rthumb, *rounding, context);
|
||||||
|
@ -411,7 +426,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
|
|
||||||
const auto skipDrawingContent = context.skipDrawingParts
|
const auto skipDrawingContent = context.skipDrawingParts
|
||||||
== PaintContext::SkipDrawingParts::Content;
|
== PaintContext::SkipDrawingParts::Content;
|
||||||
if (streamed && !skipDrawingContent) {
|
if (streamed && !skipDrawingContent && !fullHiddenBySpoiler) {
|
||||||
auto paused = context.paused;
|
auto paused = context.paused;
|
||||||
auto request = ::Media::Streaming::FrameRequest{
|
auto request = ::Media::Streaming::FrameRequest{
|
||||||
.outer = QSize(usew, painth) * cIntRetinaFactor(),
|
.outer = QSize(usew, painth) * cIntRetinaFactor(),
|
||||||
|
@ -474,18 +489,17 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
p.setOpacity(1.);
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!skipDrawingContent) {
|
} else if (!skipDrawingContent && !fullHiddenBySpoiler) {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
validateThumbCache({ usew, painth }, isRound, rounding);
|
validateThumbCache({ usew, painth }, isRound, rounding);
|
||||||
p.drawImage(rthumb, _thumbCache);
|
p.drawImage(rthumb, _thumbCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRound && _spoiler) {
|
if (!isRound && revealed < 1.) {
|
||||||
fillImageSpoiler(
|
p.setOpacity(1. - revealed);
|
||||||
p,
|
p.drawImage(rthumb.topLeft(), _spoiler->background);
|
||||||
_spoiler.get(),
|
fillImageSpoiler(p, _spoiler.get(), rthumb, context);
|
||||||
rthumb,
|
p.setOpacity(1.);
|
||||||
context);
|
|
||||||
}
|
}
|
||||||
if (context.selected()) {
|
if (context.selected()) {
|
||||||
if (isRound) {
|
if (isRound) {
|
||||||
|
@ -498,13 +512,14 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (radial
|
if (radial
|
||||||
|| (!streamingMode
|
|| (!streamingMode
|
||||||
&& ((!loaded && !_data->loading()) || !autoplay))) {
|
&& ((!loaded && !_data->loading()) || !autoplay))) {
|
||||||
const auto radialOpacity = (item->isSending() || _data->uploading())
|
const auto opacity = (item->isSending() || _data->uploading())
|
||||||
? 1.
|
? 1.
|
||||||
: streamedForWaiting
|
: streamedForWaiting
|
||||||
? streamedForWaiting->waitingOpacity()
|
? streamedForWaiting->waitingOpacity()
|
||||||
: (radial && loaded)
|
: (radial && loaded)
|
||||||
? _animation->radial.opacity()
|
? _animation->radial.opacity()
|
||||||
: 1.;
|
: 1.;
|
||||||
|
const auto radialOpacity = opacity * revealed;
|
||||||
const auto innerSize = st::msgFileLayout.thumbSize;
|
const auto innerSize = st::msgFileLayout.thumbSize;
|
||||||
auto inner = QRect(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
|
auto inner = QRect(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
|
@ -542,7 +557,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (icon) {
|
if (icon) {
|
||||||
icon->paintInCenter(p, inner);
|
icon->paintInCenter(p, inner);
|
||||||
}
|
}
|
||||||
p.setOpacity(1);
|
p.setOpacity(revealed);
|
||||||
if (radial) {
|
if (radial) {
|
||||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||||
if (streamedForWaiting && !_data->uploading()) {
|
if (streamedForWaiting && !_data->uploading()) {
|
||||||
|
@ -562,6 +577,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
sti->historyFileThumbRadialFg);
|
sti->historyFileThumbRadialFg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
if (displayMute) {
|
if (displayMute) {
|
||||||
auto muteRect = style::rtlrect(rthumb.x() + (rthumb.width() - st::historyVideoMessageMuteSize) / 2, rthumb.y() + st::msgDateImgDelta, st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, width());
|
auto muteRect = style::rtlrect(rthumb.x() + (rthumb.width() - st::historyVideoMessageMuteSize) / 2, rthumb.y() + st::msgDateImgDelta, st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, width());
|
||||||
|
@ -808,6 +824,26 @@ QImage Gif::prepareThumbCache(QSize outer) const {
|
||||||
blurFromLarge ? large : blurred);
|
blurFromLarge ? large : blurred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gif::validateSpoilerImageCache(
|
||||||
|
QSize outer,
|
||||||
|
std::optional<Ui::BubbleRounding> rounding) const {
|
||||||
|
Expects(_spoiler != nullptr);
|
||||||
|
|
||||||
|
const auto ratio = style::DevicePixelRatio();
|
||||||
|
if (_spoiler->background.size() == (outer * ratio)
|
||||||
|
&& _spoiler->backgroundRounding == rounding) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_spoiler->background = Images::Round(
|
||||||
|
PrepareWithBlurredBackground(
|
||||||
|
outer,
|
||||||
|
::Media::Streaming::ExpandDecision(),
|
||||||
|
nullptr,
|
||||||
|
_dataMedia->thumbnailInline()),
|
||||||
|
MediaRoundingMask(rounding));
|
||||||
|
_spoiler->backgroundRounding = rounding;
|
||||||
|
}
|
||||||
|
|
||||||
void Gif::drawCornerStatus(
|
void Gif::drawCornerStatus(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
|
@ -984,7 +1020,9 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
|
||||||
}
|
}
|
||||||
if (QRect(usex + paintx, painty, usew, painth).contains(point)) {
|
if (QRect(usex + paintx, painty, usew, painth).contains(point)) {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
result.link = _data->uploading()
|
result.link = (_spoiler && !_spoiler->revealed)
|
||||||
|
? _spoiler->link
|
||||||
|
: _data->uploading()
|
||||||
? _cancell
|
? _cancell
|
||||||
: _realParent->isSending()
|
: _realParent->isSending()
|
||||||
? nullptr
|
? nullptr
|
||||||
|
@ -1105,6 +1143,15 @@ void Gif::drawGrouped(
|
||||||
const auto fullFeatured = fullFeaturedGrouped(sides);
|
const auto fullFeatured = fullFeaturedGrouped(sides);
|
||||||
const auto cornerDownload = fullFeatured && downloadInCorner();
|
const auto cornerDownload = fullFeatured && downloadInCorner();
|
||||||
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
|
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
|
||||||
|
|
||||||
|
const auto revealed = _spoiler
|
||||||
|
? _spoiler->revealAnimation.value(_spoiler->revealed ? 1. : 0.)
|
||||||
|
: 1.;
|
||||||
|
const auto fullHiddenBySpoiler = (revealed == 0.);
|
||||||
|
if (revealed < 1.) {
|
||||||
|
validateSpoilerImageCache(geometry.size(), rounding);
|
||||||
|
}
|
||||||
|
|
||||||
const auto autoplay = fullFeatured
|
const auto autoplay = fullFeatured
|
||||||
&& autoplayEnabled()
|
&& autoplayEnabled()
|
||||||
&& canBePlayed
|
&& canBePlayed
|
||||||
|
@ -1139,7 +1186,7 @@ void Gif::drawGrouped(
|
||||||
const auto radial = isRadialAnimation()
|
const auto radial = isRadialAnimation()
|
||||||
|| (streamedForWaiting && streamedForWaiting->waitingShown());
|
|| (streamedForWaiting && streamedForWaiting->waitingShown());
|
||||||
|
|
||||||
if (streamed) {
|
if (streamed && !fullHiddenBySpoiler) {
|
||||||
const auto original = sizeForAspectRatio();
|
const auto original = sizeForAspectRatio();
|
||||||
const auto originalWidth = style::ConvertScale(original.width());
|
const auto originalWidth = style::ConvertScale(original.width());
|
||||||
const auto originalHeight = style::ConvertScale(original.height());
|
const auto originalHeight = style::ConvertScale(original.height());
|
||||||
|
@ -1171,11 +1218,18 @@ void Gif::drawGrouped(
|
||||||
streamed->markFrameShown();
|
streamed->markFrameShown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!fullHiddenBySpoiler) {
|
||||||
validateGroupedCache(geometry, rounding, cacheKey, cache);
|
validateGroupedCache(geometry, rounding, cacheKey, cache);
|
||||||
p.drawPixmap(geometry, *cache);
|
p.drawPixmap(geometry, *cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (revealed < 1.) {
|
||||||
|
p.setOpacity(1. - revealed);
|
||||||
|
p.drawImage(geometry.topLeft(), _spoiler->background);
|
||||||
|
fillImageSpoiler(p, _spoiler.get(), geometry, context);
|
||||||
|
p.setOpacity(1.);
|
||||||
|
}
|
||||||
|
|
||||||
const auto overlayOpacity = context.selected()
|
const auto overlayOpacity = context.selected()
|
||||||
? (1. - highlightOpacity)
|
? (1. - highlightOpacity)
|
||||||
: highlightOpacity;
|
: highlightOpacity;
|
||||||
|
@ -1191,13 +1245,14 @@ void Gif::drawGrouped(
|
||||||
if (radial
|
if (radial
|
||||||
|| (!streamingMode
|
|| (!streamingMode
|
||||||
&& ((!loaded && !_data->loading()) || !autoplay))) {
|
&& ((!loaded && !_data->loading()) || !autoplay))) {
|
||||||
const auto radialOpacity = (item->isSending() || _data->uploading())
|
const auto opacity = (item->isSending() || _data->uploading())
|
||||||
? 1.
|
? 1.
|
||||||
: streamedForWaiting
|
: streamedForWaiting
|
||||||
? streamedForWaiting->waitingOpacity()
|
? streamedForWaiting->waitingOpacity()
|
||||||
: (radial && loaded)
|
: (radial && loaded)
|
||||||
? _animation->radial.opacity()
|
? _animation->radial.opacity()
|
||||||
: 1.;
|
: 1.;
|
||||||
|
const auto radialOpacity = opacity * revealed;
|
||||||
const auto radialSize = st::historyGroupRadialSize;
|
const auto radialSize = st::historyGroupRadialSize;
|
||||||
const auto inner = QRect(
|
const auto inner = QRect(
|
||||||
geometry.x() + (geometry.width() - radialSize) / 2,
|
geometry.x() + (geometry.width() - radialSize) / 2,
|
||||||
|
@ -1248,7 +1303,7 @@ void Gif::drawGrouped(
|
||||||
icon->paintInCenter(p, inner);
|
icon->paintInCenter(p, inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.setOpacity(1);
|
p.setOpacity(revealed);
|
||||||
if (radial) {
|
if (radial) {
|
||||||
const auto line = st::historyGroupRadialLine;
|
const auto line = st::historyGroupRadialLine;
|
||||||
const auto rinner = inner.marginsRemoved({ line, line, line, line });
|
const auto rinner = inner.marginsRemoved({ line, line, line, line });
|
||||||
|
@ -1269,6 +1324,7 @@ void Gif::drawGrouped(
|
||||||
sti->historyFileThumbRadialFg);
|
sti->historyFileThumbRadialFg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
if (fullFeatured) {
|
if (fullFeatured) {
|
||||||
drawCornerStatus(p, context, geometry.topLeft());
|
drawCornerStatus(p, context, geometry.topLeft());
|
||||||
|
@ -1289,7 +1345,9 @@ TextState Gif::getStateGrouped(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
return TextState(_parent, _data->uploading()
|
return TextState(_parent, (_spoiler && !_spoiler->revealed)
|
||||||
|
? _spoiler->link
|
||||||
|
: _data->uploading()
|
||||||
? _cancell
|
? _cancell
|
||||||
: _realParent->isSending()
|
: _realParent->isSending()
|
||||||
? nullptr
|
? nullptr
|
||||||
|
|
|
@ -183,6 +183,9 @@ private:
|
||||||
bool isEllipse,
|
bool isEllipse,
|
||||||
std::optional<Ui::BubbleRounding> rounding) const;
|
std::optional<Ui::BubbleRounding> rounding) const;
|
||||||
[[nodiscard]] QImage prepareThumbCache(QSize outer) const;
|
[[nodiscard]] QImage prepareThumbCache(QSize outer) const;
|
||||||
|
void validateSpoilerImageCache(
|
||||||
|
QSize outer,
|
||||||
|
std::optional<Ui::BubbleRounding> rounding) const;
|
||||||
|
|
||||||
void validateGroupedCache(
|
void validateGroupedCache(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
|
Loading…
Add table
Reference in a new issue