2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 14:45:14 +00:00

Don't show premium stickers if premium blocked.

This commit is contained in:
John Preston
2022-06-08 10:28:45 +04:00
parent e925acc622
commit 86889cf1ef
7 changed files with 185 additions and 94 deletions

View File

@@ -55,12 +55,54 @@ namespace {
constexpr auto kStickersPanelPerRow = 5;
constexpr auto kMinRepaintDelay = crl::time(33);
constexpr auto kMinAfterScrollDelay = crl::time(33);
constexpr auto kGrayLockOpacity = 0.3;
using Data::StickersSet;
using Data::StickersPack;
using Data::StickersByEmojiMap;
using SetFlag = Data::StickersSetFlag;
[[nodiscard]] std::optional<QColor> ComputeImageColor(const QImage &frame) {
if (frame.isNull()
|| frame.format() != QImage::Format_ARGB32_Premultiplied) {
return {};
}
auto sr = int64();
auto sg = int64();
auto sb = int64();
auto sa = int64();
const auto factor = frame.devicePixelRatio();
const auto size = st::stickersPremiumLock.size() * factor;
const auto width = std::min(frame.width(), size.width());
const auto height = std::min(frame.height(), size.height());
const auto skipx = (frame.width() - width) / 2;
const auto radius = st::roundRadiusSmall;
const auto skipy = std::max(frame.height() - height - radius, 0);
const auto perline = frame.bytesPerLine();
const auto addperline = perline - (width * 4);
auto bits = static_cast<const uchar*>(frame.bits())
+ perline * skipy
+ sizeof(uint32) * skipx;
for (auto y = 0; y != height; ++y) {
for (auto x = 0; x != width; ++x) {
sb += int(*bits++);
sg += int(*bits++);
sr += int(*bits++);
sa += int(*bits++);
}
bits += addperline;
}
if (!sa) {
return {};
}
return QColor(sr * 255 / sa, sg * 255 / sa, sb * 255 / sa, 255);
}
[[nodiscard]] QColor ComputeLockColor(const QImage &frame) {
return ComputeImageColor(frame).value_or(st::windowSubTextFg->c);
}
} // namespace
class StickerSetBox::Inner final : public Ui::RpWidget {
@@ -106,6 +148,7 @@ private:
Lottie::Animation *lottie = nullptr;
Media::Clip::ReaderPointer webm;
Ui::Animations::Simple overAnimation;
mutable QImage premiumLock;
};
void visibleTopBottomUpdated(int visibleTop, int visibleBottom) override;
@@ -138,6 +181,7 @@ private:
not_null<Lottie::MultiPlayer*> getLottiePlayer();
void showPreview();
const QImage &validatePremiumLock(int index, const QImage &frame) const;
void updateItems();
void repaintItems(crl::time now = 0);
@@ -158,6 +202,7 @@ private:
ImageWithLocation _setThumbnail;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
mutable QImage _premiumLockGray;
int _visibleTop = 0;
int _visibleBottom = 0;
@@ -416,6 +461,11 @@ StickerSetBox::Inner::Inner(
updateItems();
}, lifetime());
style::PaletteChanged(
) | rpl::start_with_next([=] {
_premiumLockGray = QImage();
}, lifetime());
setMouseTracking(true);
}
@@ -425,18 +475,25 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
_elements.clear();
_selected = -1;
setCursor(style::cur_default);
const auto owner = &_controller->session().data();
const auto premiumPossible = _controller->session().premiumPossible();
set.match([&](const MTPDmessages_stickerSet &data) {
const auto &v = data.vdocuments().v;
_pack.reserve(v.size());
_elements.reserve(v.size());
for (const auto &item : v) {
const auto document = _controller->session().data().processDocument(item);
const auto document = owner->processDocument(item);
const auto sticker = document->sticker();
if (!sticker) {
continue;
}
_pack.push_back(document);
_elements.push_back({ document, document->createMediaView() });
if (!document->isPremiumSticker() || premiumPossible) {
_elements.push_back({
document,
document->createMediaView(),
});
}
}
for (const auto &pack : data.vpacks().v) {
pack.match([&](const MTPDstickerPack &pack) {
@@ -756,6 +813,15 @@ void StickerSetBox::Inner::showPreview() {
}
}
const QImage &StickerSetBox::Inner::validatePremiumLock(
int index,
const QImage &frame) const {
auto &element = _elements[index];
auto &image = frame.isNull() ? _premiumLockGray : element.premiumLock;
ValidatePremiumLockBg(image, frame);
return image;
}
not_null<Lottie::MultiPlayer*> StickerSetBox::Inner::getLottiePlayer() {
if (!_lottiePlayer) {
_lottiePlayer = std::make_unique<Lottie::MultiPlayer>(
@@ -939,6 +1005,8 @@ void StickerSetBox::Inner::paintSticker(
const auto document = element.document;
const auto &media = element.documentMedia;
const auto sticker = document->sticker();
const auto locked = document->isPremiumSticker()
&& !_controller->session().premium();
media->checkStickerSmall();
if (media->loaded()) {
@@ -955,12 +1023,12 @@ void StickerSetBox::Inner::paintSticker(
const auto ppos = position + QPoint(
(st::stickersSize.width() - size.width()) / 2,
(st::stickersSize.height() - size.height()) / 2);
auto lottieFrame = QImage();
if (element.lottie && element.lottie->ready()) {
const auto frame = element.lottie->frame();
lottieFrame = element.lottie->frame();
p.drawImage(
QRect(ppos, frame.size() / cIntRetinaFactor()),
frame);
QRect(ppos, lottieFrame.size() / cIntRetinaFactor()),
lottieFrame);
_lottiePlayer->unpause(element.lottie);
} else if (element.webm && element.webm->started()) {
@@ -980,6 +1048,20 @@ void StickerSetBox::Inner::paintSticker(
QRect(ppos, size),
_pathGradient.get());
}
if (locked) {
validatePremiumLock(index, lottieFrame);
const auto &bg = lottieFrame.isNull()
? _premiumLockGray
: element.premiumLock;
const auto factor = style::DevicePixelRatio();
const auto radius = st::roundRadiusSmall;
const auto point = position + QPoint(
(st::stickersSize.width() - (bg.width() / factor)) / 2,
st::stickersSize.height() - (bg.height() / factor) - radius);
p.drawImage(point, bg);
st::stickersPremiumLock.paint(p, point, width());
}
}
bool StickerSetBox::Inner::loaded() const {
@@ -1066,3 +1148,23 @@ 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));
}