diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index 73e54bae09..1a50c24f05 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_file_origin.h" #include "data/data_document_media.h" +#include "data/data_peer_values.h" #include "data/stickers/data_stickers.h" #include "data/stickers/data_custom_emoji.h" #include "menu/menu_send.h" @@ -112,8 +113,99 @@ using SetFlag = Data::StickersSetFlag; return ComputeImageColor(frame).value_or(st::windowSubTextFg->c); } +void ValidatePremiumLockBg(QImage &image, const QImage &frame) { + if (!image.isNull()) { + return; + } + const auto factor = style::DevicePixelRatio(); + const auto size = st::stickersPremiumLock.size(); + image = QImage( + size * factor, + QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(factor); + auto p = QPainter(&image); + const auto color = ComputeLockColor(frame); + p.fillRect( + QRect(QPoint(), size), + anim::color(color, st::windowSubTextFg, kGrayLockOpacity)); + p.end(); + + image = Images::Circle(std::move(image)); +} + +void ValidatePremiumStarFg(QImage &image) { + if (!image.isNull()) { + return; + } + const auto factor = style::DevicePixelRatio(); + const auto size = st::stickersPremiumLock.size(); + image = QImage( + size * factor, + QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(factor); + image.fill(Qt::transparent); + auto p = QPainter(&image); + auto star = QSvgRenderer(u":/gui/icons/settings/star.svg"_q); + const auto skip = size.width() / 5.; + const auto outer = QRectF(QPointF(), size).marginsRemoved( + { skip, skip, skip, skip }); + p.setBrush(st::premiumButtonFg); + p.setPen(Qt::NoPen); + star.render(&p, outer); +} + } // namespace +StickerPremiumMark::StickerPremiumMark(not_null session) { + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _lockGray = QImage(); + _star = QImage(); + }, _lifetime); + + Data::AmPremiumValue( + session + ) | rpl::start_with_next([=](bool premium) { + _premium = premium; + }, _lifetime); +} + +void StickerPremiumMark::paint( + QPainter &p, + const QImage &frame, + QImage &backCache, + QPoint position, + QSize singleSize, + int outerWidth) { + validateLock(frame, backCache); + const auto &bg = frame.isNull() ? _lockGray : backCache; + const auto factor = style::DevicePixelRatio(); + const auto radius = st::roundRadiusSmall; + const auto point = position + QPoint( + (_premium + ? (singleSize.width() - (bg.width() / factor) - radius) + : (singleSize.width() - (bg.width() / factor)) / 2), + singleSize.height() - (bg.height() / factor) - radius); + p.drawImage(point, bg); + if (_premium) { + validateStar(); + p.drawImage(point, _star); + } else { + st::stickersPremiumLock.paint(p, point, outerWidth); + } +} + +void StickerPremiumMark::validateLock( + const QImage &frame, + QImage &backCache) { + auto &image = frame.isNull() ? _lockGray : backCache; + ValidatePremiumLockBg(image, frame); +} + +void StickerPremiumMark::validateStar() { + ValidatePremiumStarFg(_star); +} + class StickerSetBox::Inner final : public Ui::RpWidget { public: Inner( @@ -204,8 +296,6 @@ private: not_null getLottiePlayer(); void showPreview(); - void validatePremiumLock(int index, const QImage &frame) const; - void validatePremiumStar() const; void updateItems(); void repaintItems(crl::time now = 0); @@ -237,8 +327,7 @@ private: ImageWithLocation _setThumbnail; const std::unique_ptr _pathGradient; - mutable QImage _premiumLockGray; - mutable QImage _premiumStar; + mutable StickerPremiumMark _premiumMark; int _visibleTop = 0; int _visibleBottom = 0; @@ -545,6 +634,7 @@ StickerSetBox::Inner::Inner( st::windowBgRipple, st::windowBgOver, [=] { repaintItems(); })) +, _premiumMark(&controller->session()) , _updateItemsTimer([=] { updateItems(); }) , _input(set) , _padding((type == Data::StickersType::Emoji) @@ -570,12 +660,6 @@ StickerSetBox::Inner::Inner( updateItems(); }, lifetime()); - style::PaletteChanged( - ) | rpl::start_with_next([=] { - _premiumLockGray = QImage(); - _premiumStar = QImage(); - }, lifetime()); - setMouseTracking(true); } @@ -937,18 +1021,6 @@ void StickerSetBox::Inner::showPreview() { } } -void StickerSetBox::Inner::validatePremiumLock( - int index, - const QImage &frame) const { - auto &element = _elements[index]; - auto &image = frame.isNull() ? _premiumLockGray : element.premiumLock; - ValidatePremiumLockBg(image, frame); -} - -void StickerSetBox::Inner::validatePremiumStar() const { - ValidatePremiumStarFg(_premiumStar); -} - not_null StickerSetBox::Inner::getLottiePlayer() { if (!_lottiePlayer) { _lottiePlayer = std::make_unique( @@ -1175,7 +1247,6 @@ void StickerSetBox::Inner::paintSticker( const auto document = element.document; const auto &media = element.documentMedia; const auto sticker = document->sticker(); - const auto premium = document->isPremiumSticker(); media->checkStickerSmall(); if (sticker->setType == Data::StickersType::Emoji) { @@ -1188,6 +1259,7 @@ void StickerSetBox::Inner::paintSticker( } } + const auto premium = document->isPremiumSticker(); const auto size = ChatHelpers::ComputeStickerSize( document, boundingBoxSize()); @@ -1216,10 +1288,12 @@ void StickerSetBox::Inner::paintSticker( .keepAlpha = true, }, paused ? 0 : now)); } else if (const auto image = media->getStickerSmall()) { - p.drawPixmapLeft( - ppos, - width(), - image->pix(size)); + const auto pixmap = image->pix(size); + p.drawPixmapLeft(ppos, width(), pixmap); + if (premium) { + lottieFrame = pixmap.toImage().convertToFormat( + QImage::Format_ARGB32_Premultiplied); + } } else { ChatHelpers::PaintStickerThumbnailPath( p, @@ -1228,25 +1302,13 @@ void StickerSetBox::Inner::paintSticker( _pathGradient.get()); } if (premium) { - validatePremiumLock(index, lottieFrame); - const auto &bg = lottieFrame.isNull() - ? _premiumLockGray - : element.premiumLock; - const auto factor = style::DevicePixelRatio(); - const auto radius = st::roundRadiusSmall; - const auto amPremium = _controller->session().premium(); - const auto point = position + QPoint( - (amPremium - ? (_singleSize.width() - (bg.width() / factor) - radius) - : (_singleSize.width() - (bg.width() / factor)) / 2), - _singleSize.height() - (bg.height() / factor) - radius); - p.drawImage(point, bg); - if (amPremium) { - validatePremiumStar(); - p.drawImage(point, _premiumStar); - } else { - st::stickersPremiumLock.paint(p, point, width()); - } + _premiumMark.paint( + p, + lottieFrame, + element.premiumLock, + position, + _singleSize, + width()); } } @@ -1340,44 +1402,3 @@ void StickerSetBox::Inner::repaintItems(crl::time now) { } StickerSetBox::Inner::~Inner() = default; - -void ValidatePremiumLockBg(QImage &image, const QImage &frame) { - if (!image.isNull()) { - return; - } - const auto factor = style::DevicePixelRatio(); - const auto size = st::stickersPremiumLock.size(); - image = QImage( - size * factor, - QImage::Format_ARGB32_Premultiplied); - image.setDevicePixelRatio(factor); - auto p = QPainter(&image); - const auto color = ComputeLockColor(frame); - p.fillRect( - QRect(QPoint(), size), - anim::color(color, st::windowSubTextFg, kGrayLockOpacity)); - p.end(); - - image = Images::Circle(std::move(image)); -} - -void ValidatePremiumStarFg(QImage &image) { - if (!image.isNull()) { - return; - } - const auto factor = style::DevicePixelRatio(); - const auto size = st::stickersPremiumLock.size(); - image = QImage( - size * factor, - QImage::Format_ARGB32_Premultiplied); - image.setDevicePixelRatio(factor); - image.fill(Qt::transparent); - auto p = QPainter(&image); - auto star = QSvgRenderer(u":/gui/icons/settings/star.svg"_q); - const auto skip = size.width() / 5.; - const auto outer = QRectF(QPointF(), size).marginsRemoved( - { skip, skip, skip, skip }); - p.setBrush(st::premiumButtonFg); - p.setPen(Qt::NoPen); - star.render(&p, outer); -} diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.h b/Telegram/SourceFiles/boxes/sticker_set_box.h index 19e3ff040b..73d99dc7de 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.h +++ b/Telegram/SourceFiles/boxes/sticker_set_box.h @@ -23,6 +23,30 @@ namespace Data { class StickersSet; } // namespace Data +class StickerPremiumMark final { +public: + explicit StickerPremiumMark(not_null session); + + void paint( + QPainter &p, + const QImage &frame, + QImage &backCache, + QPoint position, + QSize singleSize, + int outerWidth); + +private: + void validateLock(const QImage &frame, QImage &backCache); + void validateStar(); + + QImage _lockGray; + QImage _star; + bool _premium = false; + + rpl::lifetime _lifetime; + +}; + class StickerSetBox final : public Ui::BoxContent { public: StickerSetBox( @@ -63,6 +87,3 @@ private: QPointer _inner; }; - -void ValidatePremiumLockBg(QImage &image, const QImage &frame); -void ValidatePremiumStarFg(QImage &image); diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index e7d0d970c6..8b6e1fcbc6 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "base/random.h" #include "base/qt/qt_common_adapters.h" +#include "boxes/sticker_set_box.h" #include "window/window_adaptive.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" @@ -135,6 +136,7 @@ private: bool _isOneColumn = false; const std::unique_ptr _pathGradient; + StickerPremiumMark _premiumMark; Fn _sendMenuType; @@ -153,6 +155,7 @@ struct FieldAutocomplete::StickerSuggestion { std::shared_ptr documentMedia; std::unique_ptr lottie; Media::Clip::ReaderPointer webm; + QImage premiumLock; }; FieldAutocomplete::FieldAutocomplete( @@ -790,6 +793,7 @@ FieldAutocomplete::Inner::Inner( st::windowBgRipple, st::windowBgOver, [=] { update(); })) +, _premiumMark(&controller->session()) , _previewTimer([=] { showPreview(); }) { controller->session().downloaderTaskFinished( ) | rpl::start_with_next([=] { @@ -868,11 +872,12 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) { const auto ppos = pos + QPoint( (st::stickerPanSize.width() - size.width()) / 2, (st::stickerPanSize.height() - size.height()) / 2); + auto lottieFrame = QImage(); if (sticker.lottie && sticker.lottie->ready()) { - const auto frame = sticker.lottie->frame(); + lottieFrame = sticker.lottie->frame(); p.drawImage( - QRect(ppos, frame.size() / cIntRetinaFactor()), - frame); + QRect(ppos, lottieFrame.size() / cIntRetinaFactor()), + lottieFrame); if (!paused) { sticker.lottie->markFrameShown(); } @@ -890,6 +895,16 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) { QRect(ppos, size), _pathGradient.get()); } + + if (document->isPremiumSticker()) { + _premiumMark.paint( + p, + lottieFrame, + sticker.premiumLock, + pos, + st::stickerPanSize, + width()); + } } } } else { diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index f82fc3f90f..3b5e12e511 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -180,6 +180,7 @@ StickersListWidget::StickersListWidget( , _addWidth(st::stickersTrendingAdd.font->width(_addText)) , _settings(this, tr::lng_stickers_you_have(tr::now)) , _previewTimer([=] { showPreview(); }) +, _premiumMark(std::make_unique(&controller->session())) , _searchRequestTimer([=] { sendSearchRequest(); }) { setMouseTracking(true); setAttribute(Qt::WA_OpaquePaintEvent); @@ -218,12 +219,6 @@ StickersListWidget::StickersListWidget( TabbedSelector::Action::Update ) | rpl::start_to_stream(_choosingUpdated, lifetime()); - style::PaletteChanged( - ) | rpl::start_with_next([=] { - _premiumLockGray = QImage(); - _premiumStar = QImage(); - }, lifetime()); - Data::AmPremiumValue( &session() ) | rpl::start_with_next([=](bool premium) { @@ -1375,41 +1370,16 @@ void StickersListWidget::paintSticker( } if (premium) { - validatePremiumLock(set, index, lottieFrame); - const auto &bg = lottieFrame.isNull() - ? _premiumLockGray - : sticker.premiumLock; - const auto factor = style::DevicePixelRatio(); - const auto radius = st::roundRadiusSmall; - const auto amPremium = session().premium(); - const auto point = pos + QPoint( - (amPremium - ? (_singleSize.width() - (bg.width() / factor) - radius) - : (_singleSize.width() - (bg.width() / factor)) / 2), - _singleSize.height() - (bg.height() / factor) - radius); - p.drawImage(point, bg); - if (amPremium) { - validatePremiumStar(); - p.drawImage(point, _premiumStar); - } else { - st::stickersPremiumLock.paint(p, point, width()); - } + _premiumMark->paint( + p, + lottieFrame, + sticker.premiumLock, + pos, + _singleSize, + width()); } } -void StickersListWidget::validatePremiumLock( - Set &set, - int index, - const QImage &frame) { - auto &sticker = set.stickers[index]; - auto &image = frame.isNull() ? _premiumLockGray : sticker.premiumLock; - ValidatePremiumLockBg(image, frame); -} - -void StickersListWidget::validatePremiumStar() { - ValidatePremiumStarFg(_premiumStar); -} - int StickersListWidget::stickersRight() const { return stickersLeft() + (_columnCount * _singleSize.width()); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 73269ab6ce..7cdbfaad51 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/variant.h" #include "base/timer.h" +class StickerPremiumMark; + namespace Main { class Session; } // namespace Main @@ -355,7 +357,6 @@ private: int _rowsLeft = 0; int _columnCount = 1; QSize _singleSize; - QImage _premiumStar; OverState _selected; OverState _pressed; @@ -377,7 +378,7 @@ private: base::Timer _previewTimer; bool _previewShown = false; - QImage _premiumLockGray; + std::unique_ptr _premiumMark; std::map> _searchCache; std::vector> _searchIndex;