mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show premium mark in suggested stickers.
This commit is contained in:
parent
e3140a8a45
commit
4a5592e95d
5 changed files with 161 additions and 133 deletions
|
@ -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<Main::Session*> 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<Lottie::MultiPlayer*> 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<Ui::PathShiftGradient> _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<Lottie::MultiPlayer*> StickerSetBox::Inner::getLottiePlayer() {
|
||||
if (!_lottiePlayer) {
|
||||
_lottiePlayer = std::make_unique<Lottie::MultiPlayer>(
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,30 @@ namespace Data {
|
|||
class StickersSet;
|
||||
} // namespace Data
|
||||
|
||||
class StickerPremiumMark final {
|
||||
public:
|
||||
explicit StickerPremiumMark(not_null<Main::Session*> 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> _inner;
|
||||
|
||||
};
|
||||
|
||||
void ValidatePremiumLockBg(QImage &image, const QImage &frame);
|
||||
void ValidatePremiumStarFg(QImage &image);
|
||||
|
|
|
@ -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<Ui::PathShiftGradient> _pathGradient;
|
||||
StickerPremiumMark _premiumMark;
|
||||
|
||||
Fn<SendMenu::Type()> _sendMenuType;
|
||||
|
||||
|
@ -153,6 +155,7 @@ struct FieldAutocomplete::StickerSuggestion {
|
|||
std::shared_ptr<Data::DocumentMedia> documentMedia;
|
||||
std::unique_ptr<Lottie::SinglePlayer> 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 {
|
||||
|
|
|
@ -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<StickerPremiumMark>(&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());
|
||||
}
|
||||
|
|
|
@ -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<StickerPremiumMark> _premiumMark;
|
||||
|
||||
std::map<QString, std::vector<uint64>> _searchCache;
|
||||
std::vector<std::pair<uint64, QStringList>> _searchIndex;
|
||||
|
|
Loading…
Add table
Reference in a new issue