mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-30 07:18:28 +00:00
Don't show premium stickers if premium blocked.
This commit is contained in:
parent
e925acc622
commit
86889cf1ef
Telegram/SourceFiles
@ -422,6 +422,7 @@ void ReactionsSettingsBox(
|
||||
};
|
||||
|
||||
auto firstCheckedButton = (Ui::RpWidget*)(nullptr);
|
||||
const auto premiumPossible = controller->session().premiumPossible();
|
||||
for (const auto &r : reactions.list(Data::Reactions::Type::Active)) {
|
||||
const auto button = Settings::AddButton(
|
||||
container,
|
||||
@ -429,7 +430,7 @@ void ReactionsSettingsBox(
|
||||
st::settingsButton);
|
||||
|
||||
const auto premium = r.premium;
|
||||
if (premium && !controller->session().premiumPossible()) {
|
||||
if (premium && !premiumPossible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -53,3 +53,5 @@ private:
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
void ValidatePremiumLockBg(QImage &image, const QImage &frame);
|
||||
|
@ -242,11 +242,11 @@ private:
|
||||
[[nodiscard]] Data::StickersSetFlags fillSetFlags(
|
||||
not_null<StickersSet*> set) const;
|
||||
void rebuildMegagroupSet();
|
||||
void fixupMegagroupSetAddress();
|
||||
void handleMegagroupSetAddressChange();
|
||||
void setMegagroupSelectedSet(const StickerSetIdentifier &set);
|
||||
|
||||
int countMaxNameWidth() const;
|
||||
[[nodiscard]] bool skipPremium() const;
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
MTP::Sender _api;
|
||||
@ -2193,6 +2193,10 @@ bool StickersBox::Inner::appendSet(not_null<StickersSet*> set) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StickersBox::Inner::skipPremium() const {
|
||||
return !_controller->session().premiumPossible();
|
||||
}
|
||||
|
||||
int StickersBox::Inner::countMaxNameWidth() const {
|
||||
int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
if (!_megagroupSet && _isInstalled) {
|
||||
@ -2317,23 +2321,39 @@ void StickersBox::Inner::fillSetCover(
|
||||
}
|
||||
|
||||
int StickersBox::Inner::fillSetCount(not_null<StickersSet*> set) const {
|
||||
const auto skipPremium = this->skipPremium();
|
||||
int result = set->stickers.isEmpty()
|
||||
? set->count
|
||||
: set->stickers.size();
|
||||
if (skipPremium && !set->stickers.isEmpty()) {
|
||||
result -= ranges::count(
|
||||
set->stickers,
|
||||
true,
|
||||
&DocumentData::isPremiumSticker);
|
||||
}
|
||||
auto added = 0;
|
||||
if (set->id == Data::Stickers::CloudRecentSetId) {
|
||||
const auto &sets = session().data().stickers().sets();
|
||||
const auto &recent = session().data().stickers().getRecentPack();
|
||||
auto customIt = sets.find(Data::Stickers::CustomSetId);
|
||||
if (customIt != sets.cend()) {
|
||||
added = customIt->second->stickers.size();
|
||||
const auto &recent = session().data().stickers().getRecentPack();
|
||||
auto &custom = customIt->second->stickers;
|
||||
added = custom.size();
|
||||
if (skipPremium) {
|
||||
added -= ranges::count(
|
||||
custom,
|
||||
true,
|
||||
&DocumentData::isPremiumSticker);
|
||||
}
|
||||
for (const auto &sticker : recent) {
|
||||
if (customIt->second->stickers.indexOf(sticker.first) < 0) {
|
||||
if (skipPremium && sticker.first->isPremiumSticker()) {
|
||||
continue;
|
||||
} else if (customIt->second->stickers.indexOf(sticker.first) < 0) {
|
||||
++added;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
added = session().data().stickers().getRecentPack().size();
|
||||
added = recent.size();
|
||||
}
|
||||
}
|
||||
return result + added;
|
||||
|
@ -58,7 +58,6 @@ constexpr auto kPreloadOfficialPages = 4;
|
||||
constexpr auto kOfficialLoadLimit = 40;
|
||||
constexpr auto kMinRepaintDelay = crl::time(33);
|
||||
constexpr auto kMinAfterScrollDelay = crl::time(33);
|
||||
constexpr auto kGrayLockOpacity = 0.3;
|
||||
|
||||
using Data::StickersSet;
|
||||
using Data::StickersPack;
|
||||
@ -69,47 +68,6 @@ using SetFlag = Data::StickersSetFlag;
|
||||
return (flags & SetFlag::Installed) && !(flags & SetFlag::Archived);
|
||||
}
|
||||
|
||||
[[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
|
||||
|
||||
struct StickerIcon {
|
||||
@ -313,11 +271,14 @@ struct StickersListWidget::Set {
|
||||
};
|
||||
|
||||
auto StickersListWidget::PrepareStickers(
|
||||
const QVector<DocumentData*> &pack)
|
||||
const QVector<DocumentData*> &pack,
|
||||
bool skipPremium)
|
||||
-> std::vector<Sticker> {
|
||||
return ranges::views::all(
|
||||
pack
|
||||
) | ranges::views::transform([](DocumentData *document) {
|
||||
) | ranges::views::filter([&](DocumentData *document) {
|
||||
return !skipPremium || !document->isPremiumSticker();
|
||||
}) | ranges::views::transform([](DocumentData *document) {
|
||||
return Sticker{ document };
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
@ -1673,6 +1634,10 @@ void StickersListWidget::fillCloudSearchRows(
|
||||
}
|
||||
|
||||
void StickersListWidget::addSearchRow(not_null<StickersSet*> set) {
|
||||
const auto skipPremium = !session().premiumPossible();
|
||||
auto elements = PrepareStickers(
|
||||
set->stickers.empty() ? set->covers : set->stickers,
|
||||
skipPremium);
|
||||
_searchSets.emplace_back(
|
||||
set->id,
|
||||
set,
|
||||
@ -1681,9 +1646,7 @@ void StickersListWidget::addSearchRow(not_null<StickersSet*> set) {
|
||||
set->shortName,
|
||||
set->count,
|
||||
!SetInMyList(set->flags),
|
||||
PrepareStickers(set->stickers.empty()
|
||||
? set->covers
|
||||
: set->stickers));
|
||||
std::move(elements));
|
||||
}
|
||||
|
||||
void StickersListWidget::takeHeavyData(
|
||||
@ -2445,23 +2408,7 @@ const QImage &StickersListWidget::validatePremiumLock(
|
||||
const QImage &frame) {
|
||||
auto &sticker = set.stickers[index];
|
||||
auto &image = frame.isNull() ? _premiumLockGray : sticker.premiumLock;
|
||||
if (!image.isNull()) {
|
||||
return image;
|
||||
}
|
||||
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));
|
||||
ValidatePremiumLockBg(image, frame);
|
||||
return image;
|
||||
}
|
||||
|
||||
@ -2996,13 +2943,15 @@ void StickersListWidget::refreshSearchSets() {
|
||||
refreshSearchIndex();
|
||||
|
||||
const auto &sets = session().data().stickers().sets();
|
||||
const auto skipPremium = !session().premiumPossible();
|
||||
for (auto &entry : _searchSets) {
|
||||
if (const auto it = sets.find(entry.id); it != sets.end()) {
|
||||
const auto set = it->second.get();
|
||||
entry.flags = set->flags;
|
||||
if (!set->stickers.empty()) {
|
||||
auto elements = PrepareStickers(set->stickers, skipPremium);
|
||||
if (!elements.empty()) {
|
||||
entry.lottiePlayer = nullptr;
|
||||
entry.stickers = PrepareStickers(set->stickers);
|
||||
entry.stickers = std::move(elements);
|
||||
}
|
||||
if (!SetInMyList(entry.flags)) {
|
||||
_installedLocallySets.remove(entry.id);
|
||||
@ -3077,6 +3026,15 @@ bool StickersListWidget::appendSet(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const auto skipPremium = !session().premiumPossible();
|
||||
auto elements = PrepareStickers(
|
||||
((set->stickers.empty() && externalLayout)
|
||||
? set->covers
|
||||
: set->stickers),
|
||||
skipPremium);
|
||||
if (elements.empty()) {
|
||||
return false;
|
||||
}
|
||||
to.emplace_back(
|
||||
set->id,
|
||||
set,
|
||||
@ -3085,9 +3043,7 @@ bool StickersListWidget::appendSet(
|
||||
set->shortName,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers((set->stickers.empty() && externalLayout)
|
||||
? set->covers
|
||||
: set->stickers));
|
||||
std::move(elements));
|
||||
if (!externalLayout && _premiumsIndex >= 0 && session().premium()) {
|
||||
for (const auto &sticker : to.back().stickers) {
|
||||
const auto document = sticker.document;
|
||||
@ -3232,12 +3188,17 @@ void StickersListWidget::refreshFavedStickers() {
|
||||
clearSelection();
|
||||
const auto &sets = session().data().stickers().sets();
|
||||
const auto it = sets.find(Data::Stickers::FavedSetId);
|
||||
if (it == sets.cend() || it->second->stickers.isEmpty()) {
|
||||
if (it == sets.cend()) {
|
||||
return;
|
||||
}
|
||||
const auto skipPremium = !session().premiumPossible();
|
||||
const auto set = it->second.get();
|
||||
const auto externalLayout = false;
|
||||
const auto shortName = QString();
|
||||
auto elements = PrepareStickers(set->stickers, skipPremium);
|
||||
if (elements.empty()) {
|
||||
return;
|
||||
}
|
||||
_mySets.insert(_mySets.begin(), Set{
|
||||
Data::Stickers::FavedSetId,
|
||||
nullptr,
|
||||
@ -3246,7 +3207,7 @@ void StickersListWidget::refreshFavedStickers() {
|
||||
shortName,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers(set->stickers)
|
||||
std::move(elements)
|
||||
});
|
||||
_favedStickersMap = base::flat_set<not_null<DocumentData*>> {
|
||||
set->stickers.begin(),
|
||||
@ -3308,15 +3269,19 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
|
||||
} else if (isShownHere(hidden)) {
|
||||
const auto shortName = QString();
|
||||
const auto externalLayout = false;
|
||||
_mySets.emplace_back(
|
||||
Data::Stickers::MegagroupSetId,
|
||||
set,
|
||||
SetFlag::Special,
|
||||
tr::lng_group_stickers(tr::now),
|
||||
shortName,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers(set->stickers));
|
||||
const auto skipPremium = !session().premiumPossible();
|
||||
auto elements = PrepareStickers(set->stickers, skipPremium);
|
||||
if (!elements.empty()) {
|
||||
_mySets.emplace_back(
|
||||
Data::Stickers::MegagroupSetId,
|
||||
set,
|
||||
SetFlag::Special,
|
||||
tr::lng_group_stickers(tr::now),
|
||||
shortName,
|
||||
set->count,
|
||||
externalLayout,
|
||||
std::move(elements));
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (!isShownHere(hidden) || _megagroupSetIdRequested == set.id) {
|
||||
|
@ -192,7 +192,8 @@ private:
|
||||
};
|
||||
|
||||
static std::vector<Sticker> PrepareStickers(
|
||||
const QVector<DocumentData*> &pack);
|
||||
const QVector<DocumentData*> &pack,
|
||||
bool skipPremium);
|
||||
|
||||
void preloadMoreOfficial();
|
||||
QSize boundingBoxSize() const;
|
||||
|
@ -224,7 +224,7 @@ bool Session::premium() const {
|
||||
}
|
||||
|
||||
bool Session::premiumPossible() const {
|
||||
return !_account->appConfig().get<bool>(
|
||||
return !premium() && !_account->appConfig().get<bool>(
|
||||
"premium_purchase_blocked",
|
||||
true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user