Correctly round spoiler animation in ExtendedMedia.

This commit is contained in:
John Preston 2022-09-09 20:09:51 +04:00
parent a919978a37
commit 2e8a03dfd1
37 changed files with 141 additions and 255 deletions

View File

@ -357,7 +357,8 @@ void BackgroundPreviewBox::paintTexts(Painter &p, crl::time ms) {
auto context = _controller->defaultChatTheme()->preparePaintContext(
_chatStyle.get(),
rect(),
rect());
rect(),
_controller->isGifPausedAtLeastFor(Window::GifPauseReason::Layer));
p.translate(0, textsTop());
paintDate(p);

View File

@ -194,7 +194,9 @@ void AddMessage(
auto context = theme->preparePaintContext(
state->style.get(),
widget->rect(),
widget->rect());
widget->rect(),
controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer));
context.outbg = view->hasOutLayout();
{

View File

@ -639,7 +639,7 @@ void InnerWidget::elementShowTooltip(
Fn<void()> hiddenCallback) {
}
bool InnerWidget::elementIsGifPaused() {
bool InnerWidget::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
}

View File

@ -124,7 +124,7 @@ public:
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override;
bool elementAnimationsPaused() override;
bool elementHideReply(
not_null<const HistoryView::Element*> view) override;
bool elementShownUnread(

View File

@ -219,8 +219,8 @@ public:
_widget->elementShowTooltip(text, hiddenCallback);
}
}
bool elementIsGifPaused() override {
return _widget ? _widget->elementIsGifPaused() : false;
bool elementAnimationsPaused() override {
return _widget ? _widget->elementAnimationsPaused() : false;
}
bool elementHideReply(not_null<const Element*> view) override {
return false;
@ -370,7 +370,7 @@ HistoryInner::HistoryInner(
setMouseTracking(true);
_controller->gifPauseLevelChanged(
) | rpl::start_with_next([=] {
if (!elementIsGifPaused()) {
if (!elementAnimationsPaused()) {
update();
}
}, lifetime());
@ -1098,7 +1098,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
p.translate(0, -top);
}
const auto paused = elementIsGifPaused();
enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
// stop the enumeration if the userpic is below the painted rect
if (userpicTop >= clip.top() + clip.height()) {
@ -1117,7 +1116,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
userpicTop,
width(),
st::msgPhotoSize,
paused);
context.paused);
} else if (const auto info = view->data()->hiddenSenderInfo()) {
if (info->customUserpic.empty()) {
info->emptyUserpic.paint(
@ -3250,7 +3249,7 @@ void HistoryInner::elementShowTooltip(
_widget->showInfoTooltip(text, std::move(hiddenCallback));
}
bool HistoryInner::elementIsGifPaused() {
bool HistoryInner::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
}

View File

@ -145,7 +145,7 @@ public:
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback);
bool elementIsGifPaused();
bool elementAnimationsPaused();
void elementSendBotCommand(
const QString &command,
const FullMsgId &context);

View File

@ -460,7 +460,7 @@ void HistoryMessageReply::paint(
p.setTextPalette(inBubble
? stm->replyTextPalette
: st->imgReplyTextPalette());
holder->prepareCustomEmojiPaint(p, replyToText);
holder->prepareCustomEmojiPaint(p, context, replyToText);
replyToText.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top() + st::msgServiceNameFont->height, w - st::msgReplyBarSkip - previewSkip, w + 2 * x);
p.setTextPalette(stm->textPalette);
}

View File

@ -170,7 +170,7 @@ void SimpleElementDelegate::elementShowTooltip(
Fn<void()> hiddenCallback) {
}
bool SimpleElementDelegate::elementIsGifPaused() {
bool SimpleElementDelegate::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
}
@ -419,12 +419,13 @@ void Element::clearCustomEmojiRepaint() const {
void Element::prepareCustomEmojiPaint(
Painter &p,
const PaintContext &context,
const Ui::Text::String &text) const {
if (!text.hasCustomEmoji()) {
return;
}
clearCustomEmojiRepaint();
p.setInactive(delegate()->elementIsGifPaused());
p.setInactive(context.paused);
if (!_heavyCustomEmoji) {
_heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
@ -433,31 +434,19 @@ void Element::prepareCustomEmojiPaint(
void Element::prepareCustomEmojiPaint(
Painter &p,
const PaintContext &context,
const Reactions::InlineList &reactions) const {
if (!reactions.hasCustomEmoji()) {
return;
}
clearCustomEmojiRepaint();
p.setInactive(delegate()->elementIsGifPaused());
p.setInactive(context.paused);
if (!_heavyCustomEmoji) {
_heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
}
}
//void Element::externalLottieProgressing(bool external) const {
// if (const auto media = _media.get()) {
// media->externalLottieProgressing(external);
// }
//}
//
//bool Element::externalLottieTill(ExternalLottieInfo info) const {
// if (const auto media = _media.get()) {
// return media->externalLottieTill(info);
// }
// return true;
//}
void Element::repaint() const {
history()->owner().requestViewRepaint(this);
}

View File

@ -49,7 +49,6 @@ enum class InfoDisplayType : char;
struct StateRequest;
struct TextState;
class Media;
//struct ExternalLottieInfo;
enum class Context : char {
History,
@ -92,7 +91,7 @@ public:
virtual void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) = 0;
virtual bool elementIsGifPaused() = 0;
virtual bool elementAnimationsPaused() = 0;
virtual bool elementHideReply(not_null<const Element*> view) = 0;
virtual bool elementShownUnread(not_null<const Element*> view) = 0;
virtual void elementSendBotCommand(
@ -154,7 +153,7 @@ public:
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override;
bool elementAnimationsPaused() override;
bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand(
@ -262,9 +261,6 @@ public:
Context context() const;
void refreshDataId();
//void externalLottieProgressing(bool external) const;
//bool externalLottieTill(ExternalLottieInfo info) const;
QDateTime dateTime() const;
int y() const;
@ -420,9 +416,11 @@ public:
void customEmojiRepaint();
void prepareCustomEmojiPaint(
Painter &p,
const PaintContext &context,
const Ui::Text::String &text) const;
void prepareCustomEmojiPaint(
Painter &p,
const PaintContext &context,
const Reactions::InlineList &reactions) const;
void clearCustomEmojiRepaint() const;

View File

@ -45,8 +45,8 @@ constexpr auto kDropDelayedAfterDelay = crl::time(2000);
EmojiInteractions::EmojiInteractions(
not_null<Main::Session*> session,
Fn<int(not_null<const Element*>)> itemTop)
: _session(session)
, _itemTop(std::move(itemTop)) {
: _session(session)
, _itemTop(std::move(itemTop)) {
_session->data().viewRemoved(
) | rpl::filter([=] {
return !_plays.empty() || !_delayed.empty();
@ -58,13 +58,7 @@ EmojiInteractions::EmojiInteractions(
}, _lifetime);
}
EmojiInteractions::~EmojiInteractions() {
//for (const auto &play : _plays) {
// if (play.premium) {
// play.view->externalLottieProgressing(false);
// }
//}
}
EmojiInteractions::~EmojiInteractions() = default;
void EmojiInteractions::play(
ChatHelpers::EmojiInteractionPlayRequest request,
@ -98,17 +92,11 @@ bool EmojiInteractions::playPremiumEffect(
if (replacing) {
const auto i = ranges::find(_plays, replacing, &Play::view);
if (i != end(_plays)) {
//if (i->premium) {
// replacing->externalLottieProgressing(false);
//}
if (already) {
_plays.erase(i);
} else {
i->view = view;
}
//if (i->premium) {
// view->externalLottieProgressing(true);
//}
return true;
}
} else if (already) {
@ -135,8 +123,6 @@ void EmojiInteractions::cancelPremiumEffect(not_null<const Element*> view) {
_plays.erase(ranges::remove_if(_plays, [&](const Play &play) {
if (play.view != view) {
return false;
//} else if (play.premium) {
// play.view->externalLottieProgressing(false);
}
return true;
}), end(_plays));
@ -199,9 +185,6 @@ void EmojiInteractions::play(
}
});
}, lottie->lifetime());
//if (premium) {
// view->externalLottieProgressing(true);
//}
_plays.push_back({
.view = view,
.lottie = std::move(lottie),
@ -281,19 +264,11 @@ void EmojiInteractions::paint(QPainter &p) {
p.drawImage(
QRect(rect.topLeft(), frame.image.size() / factor),
frame.image);
//const auto info = HistoryView::ExternalLottieInfo{
// .frame = frame.index,
// .count = play.framesCount,
//};
//if (!play.premium || play.view->externalLottieTill(info)) {
play.lottie->markFrameShown();
//}
play.lottie->markFrameShown();
}
_plays.erase(ranges::remove_if(_plays, [](const Play &play) {
if (!play.finished) {
return false;
//} else if (play.premium) {
// play.view->externalLottieProgressing(false);
}
return true;
}), end(_plays));

View File

@ -1471,7 +1471,7 @@ void ListWidget::elementShowTooltip(
_topToast.show(parentWidget(), text, hiddenCallback);
}
bool ListWidget::elementIsGifPaused() {
bool ListWidget::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
}

View File

@ -287,7 +287,7 @@ public:
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override;
bool elementAnimationsPaused() override;
bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand(

View File

@ -746,7 +746,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
g.setHeight(g.height() - reactionsHeight);
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
p.translate(reactionsPosition);
prepareCustomEmojiPaint(p, *_reactions);
prepareCustomEmojiPaint(p, context, *_reactions);
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
if (context.reactionInfo) {
context.reactionInfo->position = reactionsPosition;
@ -802,7 +802,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
trect.setHeight(trect.height() - reactionsHeight);
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop);
p.translate(reactionsPosition);
prepareCustomEmojiPaint(p, *_reactions);
prepareCustomEmojiPaint(p, context, *_reactions);
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
if (context.reactionInfo) {
context.reactionInfo->position = reactionsPosition;
@ -1152,7 +1152,7 @@ void Message::paintFromName(
.position = QPoint(
x - 2 * _fromNameStatus->skip,
y + _fromNameStatus->skip),
.paused = delegate()->elementIsGifPaused(),
.paused = context.paused,
});
} else {
st::dialogsPremiumIcon.paint(p, x, y, width(), color);
@ -1298,7 +1298,7 @@ void Message::paintText(
const auto stm = context.messageStyle();
p.setPen(stm->historyTextFg);
p.setFont(st::msgFont);
prepareCustomEmojiPaint(p, item->_text);
prepareCustomEmojiPaint(p, context, item->_text);
item->_text.draw(
p,
trect.x(),

View File

@ -538,7 +538,7 @@ void Service::draw(Painter &p, const PaintContext &context) const {
p.setBrush(Qt::NoBrush);
p.setPen(st->msgServiceFg());
p.setFont(st::msgServiceFont);
prepareCustomEmojiPaint(p, item->_text);
prepareCustomEmojiPaint(p, context, item->_text);
item->_text.draw(
p,
trect.x(),

View File

@ -211,7 +211,6 @@ void CustomEmoji::draw(
auto x = r.x();
auto y = r.y();
const auto perRow = std::max(r.width() / _singleSize, 1);
const auto paused = _parent->delegate()->elementIsGifPaused();
for (auto &line : _lines) {
const auto count = int(line.size());
const auto rows = std::max((count + perRow - 1) / perRow, 1);
@ -221,7 +220,7 @@ void CustomEmoji::draw(
if (index >= count) {
break;
}
paintElement(p, x, y, line[index], context, paused);
paintElement(p, x, y, line[index], context);
x += _singleSize;
}
x = r.x();
@ -235,12 +234,11 @@ void CustomEmoji::paintElement(
int x,
int y,
LargeCustomEmoji &element,
const PaintContext &context,
bool paused) {
const PaintContext &context) {
if (const auto sticker = std::get_if<StickerPtr>(&element)) {
paintSticker(p, x, y, sticker->get(), context, paused);
paintSticker(p, x, y, sticker->get(), context);
} else if (const auto custom = std::get_if<CustomPtr>(&element)) {
paintCustom(p, x, y, custom->get(), context, paused);
paintCustom(p, x, y, custom->get(), context);
}
}
@ -249,8 +247,7 @@ void CustomEmoji::paintSticker(
int x,
int y,
not_null<Sticker*> sticker,
const PaintContext &context,
bool paused) {
const PaintContext &context) {
sticker->draw(p, context, { QPoint(x, y), sticker->countOptimalSize() });
}
@ -259,8 +256,7 @@ void CustomEmoji::paintCustom(
int x,
int y,
not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context,
bool paused) {
const PaintContext &context) {
if (!_hasHeavyPart) {
_hasHeavyPart = true;
_parent->history()->owner().registerHeavyViewPart(_parent);
@ -280,7 +276,7 @@ void CustomEmoji::paintCustom(
emoji->paint(q, {
.preview = preview,
.now = context.now,
.paused = paused,
.paused = context.paused,
});
q.end();
@ -293,7 +289,7 @@ void CustomEmoji::paintCustom(
.preview = preview,
.now = context.now,
.position = { x, y },
.paused = paused,
.paused = context.paused,
});
}
}

View File

@ -64,22 +64,19 @@ private:
int x,
int y,
LargeCustomEmoji &element,
const PaintContext &context,
bool paused);
const PaintContext &context);
void paintSticker(
Painter &p,
int x,
int y,
not_null<Sticker*> sticker,
const PaintContext &context,
bool paused);
const PaintContext &context);
void paintCustom(
Painter &p,
int x,
int y,
not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context,
bool paused);
const PaintContext &context);
[[nodiscard]] not_null<Data::CustomEmojiManager::Listener*> listener() {
return this;

View File

@ -694,7 +694,7 @@ void Document::draw(
}
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, captioned->_caption);
_parent->prepareCustomEmojiPaint(p, context, captioned->_caption);
captioned->_caption.draw(p, st::msgPadding.left(), captiontop, captionw, style::al_left, 0, -1, selection);
}
}

View File

@ -7,27 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "history/view/media/history_view_extended_preview.h"
//#include "history/history_item_components.h"
#include "history/history_item.h"
#include "history/history.h"
#include "history/view/history_view_element.h"
#include "history/view/history_view_cursor_state.h"
#include "history/view/media/history_view_media_common.h"
//#include "main/main_session.h"
//#include "main/main_session_settings.h"
#include "media/streaming/media_streaming_utility.h"
#include "ui/effects/spoiler_mess.h"
#include "ui/image/image.h"
#include "ui/image/image_prepare.h"
#include "ui/chat/chat_style.h"
//#include "ui/cached_round_corners.h"
#include "data/data_session.h"
//#include "data/data_streaming.h"
//#include "data/data_photo.h"
//#include "data/data_photo_media.h"
//#include "data/data_file_click_handler.h"
//#include "data/data_file_origin.h"
//#include "data/data_auto_download.h"
//#include "core/application.h"
#include "payments/payments_checkout_process.h"
#include "window/window_session_controller.h"
#include "mainwindow.h"
@ -88,7 +78,10 @@ bool ExtendedPreview::hasHeavyPart() const {
}
void ExtendedPreview::unloadHeavyPart() {
_inlineThumbnail = _imageCache = QImage();
_inlineThumbnail
= _imageCache
= _cornerCache
= _buttonBackground = QImage();
_animation = nullptr;
_caption.unloadCustomEmoji();
}
@ -193,29 +186,16 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
| ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
validateImageCache(rthumb.size(), roundRadius, roundCorners);
p.drawImage(rthumb.topLeft(), _imageCache);
fillSpoilerMess(p, context.now, rthumb, roundRadius, roundCorners);
fillSpoilerMess(p, rthumb, roundRadius, roundCorners, context);
paintButtonBackground(p, rthumb, context);
if (context.selected()) {
Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners);
}
const auto innerSize = st::msgFileLayout.thumbSize;
QRect inner(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
p.setPen(Qt::NoPen);
if (context.selected()) {
p.setBrush(st->msgDateImgBgSelected());
} else {
const auto over = ClickHandler::showAsActive(_link);
p.setBrush(over ? st->msgDateImgBgOver() : st->msgDateImgBg());
}
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(inner);
}
// date
if (!_caption.isEmpty()) {
p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption);
_parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) {
auto fullRight = paintx + paintw;
@ -268,10 +248,10 @@ QImage ExtendedPreview::prepareImageCache(QSize outer) const {
void ExtendedPreview::fillSpoilerMess(
QPainter &p,
crl::time now,
QRect rect,
ImageRoundRadius radius,
RectParts corners) const {
RectParts corners,
const PaintContext &context) const {
if (!_animation) {
_animation = std::make_unique<Ui::SpoilerAnimation>([=] {
_parent->customEmojiRepaint();
@ -280,23 +260,47 @@ void ExtendedPreview::fillSpoilerMess(
}
_parent->clearCustomEmojiRepaint();
const auto &spoiler = Ui::DefaultImageSpoiler();
const auto size = spoiler.canvasSize() / style::DevicePixelRatio();
const auto frame = spoiler.frame(
_animation->index(now, _parent->delegate()->elementIsGifPaused()));
const auto columns = (rect.width() + size - 1) / size;
const auto rows = (rect.height() + size - 1) / size;
p.setClipRect(rect);
p.translate(rect.topLeft());
for (auto y = 0; y != rows; ++y) {
for (auto x = 0; x != columns; ++x) {
p.drawImage(
QRect(x * size, y * size, size, size),
*frame.image,
frame.source);
const auto index = _animation->index(context.now, context.paused);
Ui::FillSpoilerRect(
p,
rect,
radius,
corners,
spoiler.frame(index),
_cornerCache);
}
void ExtendedPreview::paintButtonBackground(
QPainter &p,
QRect outer,
const PaintContext &context) const {
const auto st = context.st;
const auto height = st::msgFileLayout.thumbSize;
const auto width = height * 4;
const auto overlay = st->msgDateImgBg()->c;
if (_buttonBackground.isNull() || _buttonBackgroundOverlay != overlay) {
const auto ratio = style::DevicePixelRatio();
if (_imageCache.width() < width * ratio
|| _imageCache.height() < height * ratio) {
return;
}
_buttonBackground = _imageCache.copy(QRect(
(_imageCache.width() - width * ratio) / 2,
(_imageCache.height() - height * ratio) / 2,
width * ratio,
height * ratio));
_buttonBackground.setDevicePixelRatio(ratio);
auto p = QPainter(&_buttonBackground);
p.fillRect(0, 0, width, height, overlay);
p.end();
_buttonBackground = Images::Round(
std::move(_buttonBackground),
Images::CornersMask(height / 2));
}
p.translate(-rect.topLeft());
p.setClipping(false);
p.drawImage(
outer.x() + (outer.width() - width) / 2,
outer.y() + (outer.height() - height) / 2,
_buttonBackground);
}
TextState ExtendedPreview::textState(QPoint point, StateRequest request) const {

View File

@ -85,13 +85,17 @@ private:
ImageRoundRadius radius,
RectParts corners) const;
[[nodiscard]] QImage prepareImageCache(QSize outer) const;
void paintButtonBackground(
QPainter &p,
QRect outer,
const PaintContext &context) const;
void fillSpoilerMess(
QPainter &p,
crl::time now,
QRect rect,
ImageRoundRadius radius,
RectParts corners) const;
RectParts corners,
const PaintContext &context) const;
const not_null<Data::Invoice*> _invoice;
ClickHandlerPtr _link;
@ -99,6 +103,9 @@ private:
mutable std::unique_ptr<Ui::SpoilerAnimation> _animation;
mutable QImage _inlineThumbnail;
mutable QImage _imageCache;
mutable QImage _cornerCache;
mutable QImage _buttonBackground;
mutable QColor _buttonBackgroundOverlay;
mutable int _imageCacheRoundRadius : 4 = 0;
mutable int _imageCacheRoundCorners : 12 = 0;
mutable int _imageCacheInvalid : 1 = 0;

View File

@ -245,7 +245,7 @@ void Game::draw(Painter &p, const PaintContext &context) const {
if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_parent->prepareCustomEmojiPaint(p, _description);
_parent->prepareCustomEmojiPaint(p, context, _description);
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight;
}

View File

@ -279,7 +279,6 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto st = context.st;
const auto sti = context.imageStyle();
const auto stm = context.messageStyle();
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto cornerDownload = downloadInCorner();
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
const auto autoplay = autoplayEnabled()
@ -383,7 +382,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto skipDrawingContent = context.skipDrawingParts
== PaintContext::SkipDrawingParts::Content;
if (streamed && !skipDrawingContent) {
auto paused = autoPaused;
auto paused = context.paused;
if (isRound) {
if (activeRoundStreamed()) {
paused = false;
@ -604,7 +603,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
}
if (!unwrapped && !_caption.isEmpty()) {
p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption);
_parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage && !skipDrawingSurrounding) {
auto fullRight = paintx + usex + usew;
@ -992,7 +991,6 @@ void Gif::drawGrouped(
|| _data->displayLoading();
const auto st = context.st;
const auto sti = context.imageStyle();
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto fullFeatured = fullFeaturedGrouped(sides);
const auto cornerDownload = fullFeatured && downloadInCorner();
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
@ -1033,7 +1031,6 @@ void Gif::drawGrouped(
const auto roundRadius = ImageRoundRadius::Large;
if (streamed) {
const auto paused = autoPaused;
const auto original = sizeForAspectRatio();
const auto originalWidth = style::ConvertScale(original.width());
const auto originalHeight = style::ConvertScale(original.height());
@ -1062,7 +1059,7 @@ void Gif::drawGrouped(
activeOwnPlaying->frozenStatusText = QString();
}
p.drawImage(geometry, streamed->frame(request));
if (!paused) {
if (!context.paused) {
streamed->markFrameShown();
}
}
@ -1607,7 +1604,7 @@ void Gif::repaintStreamedContent() {
const auto own = activeOwnStreamed();
if (own && !own->frozenFrame.isNull()) {
return;
} else if (_parent->delegate()->elementIsGifPaused()
} else if (_parent->delegate()->elementAnimationsPaused()
&& !activeRoundStreamed()) {
return;
}

View File

@ -95,7 +95,6 @@ void LargeEmoji::draw(
const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top();
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
const auto size = LargeEmojiImage::Size() / cIntRetinaFactor();
const auto paused = _parent->delegate()->elementIsGifPaused();
const auto selected = context.selected();
if (!selected) {
_selectedFrame = QImage();
@ -114,7 +113,7 @@ void LargeEmoji::draw(
(*image)->load();
}
} else if (const auto custom = std::get_if<CustomPtr>(&media)) {
paintCustom(p, x, y, custom->get(), context, paused);
paintCustom(p, x, y, custom->get(), context);
} else {
continue;
}
@ -127,8 +126,7 @@ void LargeEmoji::paintCustom(
int x,
int y,
not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context,
bool paused) {
const PaintContext &context) {
if (!_hasHeavyPart) {
_hasHeavyPart = true;
_parent->history()->owner().registerHeavyViewPart(_parent);
@ -151,7 +149,7 @@ void LargeEmoji::paintCustom(
emoji->paint(q, {
.preview = preview,
.now = context.now,
.paused = paused,
.paused = context.paused,
});
q.end();
@ -164,7 +162,7 @@ void LargeEmoji::paintCustom(
.preview = preview,
.now = context.now,
.position = { x + skip, y + skip },
.paused = paused,
.paused = context.paused,
});
}
}

View File

@ -50,8 +50,7 @@ private:
int x,
int y,
not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context,
bool paused);
const PaintContext &context);
const not_null<Element*> _parent;
const std::array<LargeEmojiMedia, Ui::Text::kIsolatedEmojiLimit> _images;

View File

@ -69,11 +69,6 @@ enum class MediaInBubbleState {
TimeId duration,
const QString &base);
//struct ExternalLottieInfo {
// int frame = -1;
// int count = -1;
//};
class Media : public Object {
public:
explicit Media(not_null<Element*> parent) : _parent(parent) {
@ -178,15 +173,6 @@ public:
virtual void checkAnimation() {
}
//virtual void externalLottieProgressing(bool external) {
//}
//virtual bool externalLottieTill(ExternalLottieInfo info) {
// return true;
//}
//virtual ExternalLottieInfo externalLottieInfo() const {
// return {};
//}
[[nodiscard]] virtual QSize sizeForGroupingOptimal(int maxWidth) const {
Unexpected("Grouping method call.");
}

View File

@ -344,7 +344,7 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
- _caption.countHeight(captionw);
const auto stm = context.messageStyle();
p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption);
_parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), captiony, captionw, style::al_left, 0, -1, selection);
} else if (_parent->media() == this) {
auto fullRight = width();

View File

@ -466,18 +466,6 @@ std::unique_ptr<StickerPlayer> UnwrappedMedia::stickerTakePlayer(
return _content->stickerTakePlayer(data, replacements);
}
//void UnwrappedMedia::externalLottieProgressing(bool external) {
// _content->externalLottieProgressing(external);
//}
//
//bool UnwrappedMedia::externalLottieTill(ExternalLottieInfo info) {
// return _content->externalLottieTill(info);
//}
//
//ExternalLottieInfo UnwrappedMedia::externalLottieInfo() const {
// return _content->externalLottieInfo();
//}
int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();

View File

@ -42,15 +42,6 @@ public:
not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements);
//virtual void externalLottieProgressing(bool external) {
//}
//virtual bool externalLottieTill(ExternalLottieInfo info) {
// return true;
//}
//virtual ExternalLottieInfo externalLottieInfo() const {
// return {};
//}
virtual bool hasHeavyPart() const {
return false;
}
@ -108,10 +99,6 @@ public:
not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) override;
//void externalLottieProgressing(bool external) override;
//bool externalLottieTill(ExternalLottieInfo info) override;
//ExternalLottieInfo externalLottieInfo() const override;
bool hasHeavyPart() const override {
return _content->hasHeavyPart();
}

View File

@ -295,7 +295,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
// date
if (!_caption.isEmpty()) {
p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption);
_parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) {
auto fullRight = paintx + paintw;
@ -384,7 +384,6 @@ void Photo::paintUserpicFrame(
if (_streamed
&& _streamed->instance.player().ready()
&& !_streamed->instance.player().videoSize().isEmpty()) {
const auto paused = _parent->delegate()->elementIsGifPaused();
auto request = ::Media::Streaming::FrameRequest();
request.outer = size * cIntRetinaFactor();
request.resize = size * cIntRetinaFactor();
@ -397,7 +396,7 @@ void Photo::paintUserpicFrame(
} else {
_streamed->frozenFrame = QImage();
p.drawImage(rect, _streamed->instance.frame(request));
if (!paused) {
if (!context.paused) {
_streamed->instance.markFrameShown();
}
}
@ -768,7 +767,7 @@ void Photo::handleStreamingError(::Media::Streaming::Error &&error) {
void Photo::repaintStreamedContent() {
if (_streamed && !_streamed->frozenFrame.isNull()) {
return;
} else if (_parent->delegate()->elementIsGifPaused()) {
} else if (_parent->delegate()->elementAnimationsPaused()) {
return;
}
repaint();

View File

@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "core/click_handler_types.h"
#include "window/window_session_controller.h" // isGifPausedAtLeastFor.
#include "window/window_session_controller.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
@ -81,7 +81,6 @@ Sticker::Sticker(
if (const auto media = replacing ? replacing->media() : nullptr) {
_player = media->stickerTakePlayer(_data, _replacements);
if (_player) {
//_externalInfo = media->externalLottieInfo();
if (hasPremiumEffect() && !_premiumEffectPlayed) {
_premiumEffectPlayed = true;
_parent->delegate()->elementStartPremium(_parent, replacing);
@ -227,16 +226,13 @@ void Sticker::paintAnimationFrame(
const auto colored = (context.selected() && !_nextLastDiceFrame)
? context.st->msgStickerOverlay()->c
: QColor(0, 0, 0, 0);
const auto paused = /*(_externalInfo.frame >= 0)
? (_frameIndex % _externalInfo.count >= _externalInfo.frame)
: */_parent->delegate()->elementIsGifPaused();
const auto frame = _player
? _player->frame(
_size,
colored,
mirrorHorizontal(),
context.now,
paused)
context.paused)
: StickerPlayer::FrameInfo();
if (_nextLastDiceFrame) {
_nextLastDiceFrame = false;
@ -265,7 +261,7 @@ void Sticker::paintAnimationFrame(
const auto count = _player->framesCount();
_frameIndex = frame.index;
_framesCount = count;
_nextLastDiceFrame = !paused
_nextLastDiceFrame = !context.paused
&& (_diceIndex > 0)
&& (_frameIndex + 2 == count);
const auto playOnce = (_diceIndex > 0)
@ -275,10 +271,9 @@ void Sticker::paintAnimationFrame(
: ((!customEmojiPart() && isEmojiSticker())
|| !Core::App().settings().loopAnimatedStickers());
const auto lastDiceFrame = (_diceIndex > 0) && atTheEnd();
const auto switchToNext = /*(_externalInfo.frame >= 0)
|| */!playOnce
const auto switchToNext = !playOnce
|| (!lastDiceFrame && (_frameIndex != 0 || !_oncePlayed));
if (!paused
if (!context.paused
&& switchToNext
&& _player->markFrameShown()
&& playOnce
@ -539,38 +534,4 @@ std::unique_ptr<StickerPlayer> Sticker::stickerTakePlayer(
: nullptr;
}
//void Sticker::externalLottieProgressing(bool external) {
// _externalInfo = !external
// ? ExternalLottieInfo{}
// : (_externalInfo.frame > 0)
// ? _externalInfo
// : ExternalLottieInfo{ 0, 2 };
//}
//
//bool Sticker::externalLottieTill(ExternalLottieInfo info) {
// if (_externalInfo.frame >= 0) {
// _externalInfo = info;
// }
// return markFramesTillExternal();
//}
//
//ExternalLottieInfo Sticker::externalLottieInfo() const {
// return _externalInfo;
//}
//
//bool Sticker::markFramesTillExternal() {
// if (_externalInfo.frame < 0 || !_lottie) {
// return true;
// } else if (!_lottie->ready()) {
// return false;
// }
// const auto till = _externalInfo.frame % _lottie->framesCount();
// while (_lottie->frameIndex() < till) {
// if (!_lottie->markFrameShown()) {
// return false;
// }
// }
// return true;
//}
} // namespace HistoryView

View File

@ -57,10 +57,6 @@ public:
not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) override;
//void externalLottieProgressing(bool external) override;
//bool externalLottieTill(ExternalLottieInfo info) override;
//ExternalLottieInfo externalLottieInfo() const override;
bool hasHeavyPart() const override;
void unloadHeavyPart() override;
@ -119,7 +115,6 @@ private:
void emojiStickerClicked();
void premiumStickerClicked();
void checkPremiumEffectStart();
//bool markFramesTillExternal();
const not_null<Element*> _parent;
const not_null<DocumentData*> _data;
@ -130,7 +125,6 @@ private:
QSize _size;
QImage _lastDiceFrame;
QString _diceEmoji;
//ExternalLottieInfo _externalInfo;
int _diceIndex = -1;
mutable int _frameIndex = -1;
mutable int _framesCount = -1;

View File

@ -566,7 +566,7 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_parent->prepareCustomEmojiPaint(p, _description);
_parent->prepareCustomEmojiPaint(p, context, _description);
if (_descriptionLines > 0) {
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight;

View File

@ -990,7 +990,9 @@ object_ptr<Ui::RpWidget> ForwardsPrivacyController::setupAboveWidget(
auto context = theme->preparePaintContext(
_chatStyle.get(),
widget->rect(),
widget->rect());
widget->rect(),
_controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer));
p.translate(padding / 2, padding + view->marginBottom());
context.outbg = view->hasOutLayout();
view->draw(p, context);

View File

@ -570,7 +570,8 @@ void ConfirmContactBox::paintEvent(QPaintEvent *e) {
auto context = theme->preparePaintContext(
_chatStyle.get(),
rect(),
rect());
rect(),
controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Layer));
p.translate(st::boxPadding.left(), 0);
if (_comment) {
context.outbg = _comment->hasOutLayout();

View File

@ -107,6 +107,7 @@ struct ChatPaintContext {
QRect clip;
TextSelection selection;
bool outbg = false;
bool paused = false;
crl::time now = 0;
void translate(int x, int y) {
@ -132,7 +133,7 @@ struct ChatPaintContext {
return translated(point.x(), point.y());
}
[[nodiscard]] ChatPaintContext withSelection(
TextSelection selection) const {
TextSelection selection) const {
auto result = *this;
result.selection = selection;
return result;

View File

@ -459,8 +459,10 @@ void ChatTheme::finishCreateOnMain() {
ChatPaintContext ChatTheme::preparePaintContext(
not_null<const ChatStyle*> st,
QRect viewport,
QRect clip) {
QRect clip,
bool paused) {
const auto area = viewport.size();
const auto now = crl::now();
if (!_bubblesBackgroundPrepared.isNull()
&& _bubblesBackground.area != area) {
if (!_cacheBubblesTimer) {
@ -470,7 +472,7 @@ ChatPaintContext ChatTheme::preparePaintContext(
|| (!_cacheBubblesTimer->isActive()
&& !_bubblesCachingRequest)) {
_cacheBubblesArea = area;
_lastBubblesAreaChangeTime = crl::now();
_lastBubblesAreaChangeTime = now;
_cacheBubblesTimer->callOnce(kCacheBackgroundFastTimeout);
}
}
@ -479,7 +481,8 @@ ChatPaintContext ChatTheme::preparePaintContext(
.bubblesPattern = _bubblesBackgroundPattern.get(),
.viewport = viewport,
.clip = clip,
.now = crl::now(),
.paused = paused,
.now = now,
};
}

View File

@ -171,7 +171,8 @@ public:
[[nodiscard]] ChatPaintContext preparePaintContext(
not_null<const ChatStyle*> st,
QRect viewport,
QRect clip);
QRect clip,
bool paused);
[[nodiscard]] const BackgroundState &backgroundState(QSize area);
void clearBackgroundState();
[[nodiscard]] rpl::producer<> repaintBackgroundRequests() const;

View File

@ -1909,7 +1909,8 @@ HistoryView::PaintContext SessionController::preparePaintContext(
return args.theme->preparePaintContext(
_chatStyle.get(),
viewport,
args.clip);
args.clip,
isGifPausedAtLeastFor(GifPauseReason::Any));
}
void SessionController::setPremiumRef(const QString &ref) {