mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Show premium stickers lock icon.
This commit is contained in:
parent
5cd065ef6b
commit
853cafe195
BIN
Telegram/Resources/icons/emoji/premium_lock.png
Normal file
BIN
Telegram/Resources/icons/emoji/premium_lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/emoji/premium_lock@2x.png
Normal file
BIN
Telegram/Resources/icons/emoji/premium_lock@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/emoji/premium_lock@3x.png
Normal file
BIN
Telegram/Resources/icons/emoji/premium_lock@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@ -345,7 +345,7 @@ void EditCaptionBox::setupEditEventHandler() {
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const auto premium = _controller->session().user()->isPremium();
|
||||
const auto premium = _controller->session().premium();
|
||||
auto list = Storage::PreparedFileFromFilesDialog(
|
||||
std::move(result),
|
||||
checkResult,
|
||||
@ -524,7 +524,7 @@ void EditCaptionBox::updateEmojiPanelGeometry() {
|
||||
}
|
||||
|
||||
bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||
const auto premium = _controller->session().user()->isPremium();
|
||||
const auto premium = _controller->session().premium();
|
||||
return setPreparedList(ListFromMimeData(data, premium));
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]] int Limit(not_null<Main::Session*> session) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
return Limit(session,
|
||||
(premium
|
||||
? "dialog_filters_chats_limit_premium"
|
||||
|
@ -454,7 +454,7 @@ void SimplePinsLimitBox(
|
||||
int limitDefault,
|
||||
const QString &keyPremium,
|
||||
int limitPremium) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(session, keyDefault, limitDefault);
|
||||
const auto premiumLimit = Limit(session, keyPremium, limitPremium);
|
||||
@ -489,7 +489,7 @@ void SimplePinsLimitBox(
|
||||
void ChannelsLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(session, "channels_limit_default", 500);
|
||||
const auto premiumLimit = Limit(session, "channels_limit_premium", 1000);
|
||||
@ -574,7 +574,7 @@ void PublicLinksLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::SessionNavigation*> navigation) {
|
||||
const auto session = &navigation->session();
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(
|
||||
session,
|
||||
@ -639,7 +639,7 @@ void PublicLinksLimitBox(
|
||||
void FilterChatsLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(
|
||||
session,
|
||||
@ -679,7 +679,7 @@ void FilterChatsLimitBox(
|
||||
void FiltersLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(
|
||||
session,
|
||||
@ -754,7 +754,7 @@ void PinsLimitBox(
|
||||
void CaptionLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
|
||||
const auto defaultLimit = Limit(
|
||||
session,
|
||||
@ -795,7 +795,7 @@ void CaptionLimitReachedBox(
|
||||
.text = tr::lng_caption_limit_reached(tr::now, lt_count, remove),
|
||||
.inform = true,
|
||||
});
|
||||
if (!session->user()->isPremium()) {
|
||||
if (!session->premium()) {
|
||||
box->addLeftButton(tr::lng_limits_increase(), [=] {
|
||||
box->getDelegate()->showBox(
|
||||
Box(CaptionLimitBox, session),
|
||||
@ -821,7 +821,7 @@ int CurrentPremiumLimit(
|
||||
int limitDefault,
|
||||
const QString &keyPremium,
|
||||
int limitPremium) {
|
||||
const auto premium = session->user()->isPremium();
|
||||
const auto premium = session->premium();
|
||||
return AppConfigLimit(
|
||||
session,
|
||||
premium ? keyPremium : keyDefault,
|
||||
|
@ -447,7 +447,7 @@ void ReactionsSettingsBox(
|
||||
&button->lifetime());
|
||||
|
||||
button->setClickedCallback([=, emoji = r.emoji] {
|
||||
if (premium && !controller->session().user()->isPremium()) {
|
||||
if (premium && !controller->session().premium()) {
|
||||
Settings::ShowPremium(&controller->session());
|
||||
return;
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ void SendFilesBox::openDialogToAddFileToAlbum() {
|
||||
return true;
|
||||
};
|
||||
const auto callback = [=](FileDialog::OpenResult &&result) {
|
||||
const auto premium = _controller->session().user()->isPremium();
|
||||
const auto premium = _controller->session().premium();
|
||||
FileDialogCallback(
|
||||
std::move(result),
|
||||
checkResult,
|
||||
@ -575,7 +575,7 @@ void SendFilesBox::pushBlock(int from, int till) {
|
||||
return true;
|
||||
};
|
||||
const auto callback = [=](FileDialog::OpenResult &&result) {
|
||||
const auto premium = _controller->session().user()->isPremium();
|
||||
const auto premium = _controller->session().premium();
|
||||
FileDialogCallback(
|
||||
std::move(result),
|
||||
checkResult,
|
||||
@ -773,7 +773,7 @@ bool SendFilesBox::canAddFiles(not_null<const QMimeData*> data) const {
|
||||
}
|
||||
|
||||
bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
|
||||
const auto premium = _controller->session().user()->isPremium();
|
||||
const auto premium = _controller->session().premium();
|
||||
auto list = [&] {
|
||||
const auto urls = data->hasUrls() ? data->urls() : QList<QUrl>();
|
||||
auto result = CanAddUrls(urls)
|
||||
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/gradient_round_button.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
@ -149,11 +150,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::AbstractButton> CreatePremiumButton(
|
||||
QWidget *parent) {
|
||||
return CreateGradientButton(parent, {
|
||||
{ 0., st::premiumButtonBg1->c },
|
||||
{ 0.6, st::premiumButtonBg2->c },
|
||||
{ 1., st::premiumButtonBg3->c },
|
||||
});
|
||||
return CreateGradientButton(parent, Ui::Premium::ButtonGradientStops());
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::AbstractButton> CreateUnlockButton(
|
||||
@ -167,6 +164,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||
result.data(),
|
||||
tr::lng_sticker_premium_button(),
|
||||
st::premiumPreviewButtonLabel);
|
||||
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
rpl::combine(
|
||||
result->widthValue(),
|
||||
label->widthValue()
|
||||
|
@ -298,3 +298,5 @@ premiumPreviewButtonLabel: FlatLabel(defaultFlatLabel) {
|
||||
textFg: premiumButtonFg;
|
||||
style: semiboldTextStyle;
|
||||
}
|
||||
|
||||
stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
|
||||
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_cloud_file.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "menu/menu_send.h" // SendMenu::FillSendMenu
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
@ -21,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "lottie/lottie_multi_player.h"
|
||||
@ -56,6 +58,7 @@ constexpr auto kPreloadOfficialPages = 4;
|
||||
constexpr auto kOfficialLoadLimit = 40;
|
||||
constexpr auto kMinRepaintDelay = crl::time(33);
|
||||
constexpr auto kMinAfterScrollDelay = crl::time(33);
|
||||
constexpr auto kPremiumLockedOpacity = 0.5;
|
||||
|
||||
using Data::StickersSet;
|
||||
using Data::StickersPack;
|
||||
@ -1176,6 +1179,17 @@ StickersListWidget::StickersListWidget(
|
||||
) | rpl::skip(1) | rpl::map_to(
|
||||
TabbedSelector::Action::Update
|
||||
) | rpl::start_to_stream(_choosingUpdated, lifetime());
|
||||
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_premiumLock = QImage();
|
||||
}, lifetime());
|
||||
|
||||
Data::AmPremiumValue(
|
||||
&session()
|
||||
) | rpl::start_with_next([=](bool premium) {
|
||||
refreshStickers();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
Main::Session &StickersListWidget::session() const {
|
||||
@ -2276,6 +2290,7 @@ void StickersListWidget::paintSticker(
|
||||
return;
|
||||
}
|
||||
|
||||
const auto locked = document->isPremiumSticker() && !session().premium();
|
||||
const auto isLottie = document->sticker()->isLottie();
|
||||
const auto isWebm = document->sticker()->isWebm();
|
||||
if (isLottie
|
||||
@ -2302,6 +2317,9 @@ void StickersListWidget::paintSticker(
|
||||
(_singleSize.width() - size.width()) / 2,
|
||||
(_singleSize.height() - size.height()) / 2);
|
||||
|
||||
if (locked) {
|
||||
p.setOpacity(kPremiumLockedOpacity);
|
||||
}
|
||||
if (sticker.lottie && sticker.lottie->ready()) {
|
||||
auto request = Lottie::FrameRequest();
|
||||
request.box = boundingBoxSize() * cIntRetinaFactor();
|
||||
@ -2341,6 +2359,7 @@ void StickersListWidget::paintSticker(
|
||||
sticker.savedFrameFor = _singleSize;
|
||||
}
|
||||
} else {
|
||||
p.setOpacity(1.);
|
||||
PaintStickerThumbnailPath(
|
||||
p,
|
||||
media.get(),
|
||||
@ -2358,16 +2377,40 @@ void StickersListWidget::paintSticker(
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
if (document->isPremiumSticker()) {
|
||||
if (locked) {
|
||||
p.setOpacity(1.);
|
||||
|
||||
validatePremiumLock();
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
const auto point = pos
|
||||
+ QPoint(
|
||||
_singleSize.width() - st::stickerPanDeleteIconBg.width(),
|
||||
_singleSize.height() - st::stickerPanDeleteIconBg.height());
|
||||
st::stickerPanDeleteIconBg.paint(p, point, width());
|
||||
st::stickerPanDeleteIconFg.paint(p, point, width());
|
||||
_singleSize.width() - (_premiumLock.width() / factor),
|
||||
_singleSize.height() - (_premiumLock.height() / factor));
|
||||
p.drawImage(point, _premiumLock);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::validatePremiumLock() {
|
||||
if (!_premiumLock.isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
const auto size = st::stickersPremiumLock.size();
|
||||
_premiumLock = QImage(
|
||||
size * factor,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_premiumLock.setDevicePixelRatio(factor);
|
||||
auto p = QPainter(&_premiumLock);
|
||||
auto gradient = QLinearGradient(
|
||||
QPoint(0, size.height()),
|
||||
QPoint(size.width(), 0));
|
||||
gradient.setStops(Ui::Premium::LockGradientStops());
|
||||
p.fillRect(QRect(QPoint(), size), gradient);
|
||||
st::stickersPremiumLock.paint(p, 0, 0, size.width());
|
||||
p.end();
|
||||
_premiumLock = Images::Circle(std::move(_premiumLock));
|
||||
}
|
||||
|
||||
int StickersListWidget::stickersRight() const {
|
||||
return stickersLeft() + (_columnCount * _singleSize.width());
|
||||
}
|
||||
@ -2991,7 +3034,7 @@ bool StickersListWidget::appendSet(
|
||||
PrepareStickers((set->stickers.empty() && externalLayout)
|
||||
? set->covers
|
||||
: set->stickers));
|
||||
if (!externalLayout && _premiumsIndex >= 0) {
|
||||
if (!externalLayout && _premiumsIndex >= 0 && session().premium()) {
|
||||
for (const auto &sticker : to.back().stickers) {
|
||||
const auto document = sticker.document;
|
||||
if (document->isPremiumSticker()) {
|
||||
|
@ -330,6 +330,7 @@ private:
|
||||
void addSearchRow(not_null<Data::StickersSet*> set);
|
||||
|
||||
void showPreview();
|
||||
void validatePremiumLock();
|
||||
|
||||
Ui::MessageSendingAnimationFrom messageSentAnimationInfo(
|
||||
int section,
|
||||
@ -390,6 +391,8 @@ private:
|
||||
base::Timer _previewTimer;
|
||||
bool _previewShown = false;
|
||||
|
||||
QImage _premiumLock;
|
||||
|
||||
std::map<QString, std::vector<uint64>> _searchCache;
|
||||
std::vector<std::pair<uint64, QStringList>> _searchIndex;
|
||||
base::Timer _searchRequestTimer;
|
||||
|
@ -94,18 +94,25 @@ void EmojiInteractions::play(
|
||||
void EmojiInteractions::playPremiumEffect(
|
||||
not_null<const Element*> view,
|
||||
Element *replacing) {
|
||||
const auto already = ranges::contains(_plays, view, &Play::view);
|
||||
if (replacing) {
|
||||
const auto i = ranges::find(_plays, replacing, &Play::view);
|
||||
if (i != end(_plays)) {
|
||||
//if (i->premium) {
|
||||
// replacing->externalLottieProgressing(false);
|
||||
//}
|
||||
i->view = view;
|
||||
if (already) {
|
||||
_plays.erase(i);
|
||||
} else {
|
||||
i->view = view;
|
||||
}
|
||||
//if (i->premium) {
|
||||
// view->externalLottieProgressing(true);
|
||||
//}
|
||||
return;
|
||||
}
|
||||
} else if (already) {
|
||||
return;
|
||||
}
|
||||
if (const auto media = view->media()) {
|
||||
if (const auto document = media->getDocument()) {
|
||||
|
@ -255,6 +255,7 @@ void Sticker::paintLottie(
|
||||
_lottieOncePlayed = true;
|
||||
_parent->delegate()->elementStartStickerLoop(_parent);
|
||||
}
|
||||
checkPremiumEffectStart();
|
||||
}
|
||||
|
||||
bool Sticker::paintPixmap(
|
||||
@ -362,7 +363,16 @@ void Sticker::refreshLink() {
|
||||
}
|
||||
});
|
||||
} else if (sticker && sticker->set) {
|
||||
_link = ShowSetHandler(_data);
|
||||
if (_data->isPremiumSticker()) {
|
||||
const auto weak = base::make_weak(this);
|
||||
_link = std::make_shared<LambdaClickHandler>([weak] {
|
||||
if (const auto that = weak.get()) {
|
||||
that->premiumStickerClicked();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_link = ShowSetHandler(_data);
|
||||
}
|
||||
} else if (sticker
|
||||
&& (_data->dimensions.width() > kStickerSideSize
|
||||
|| _data->dimensions.height() > kStickerSideSize)
|
||||
@ -388,6 +398,11 @@ void Sticker::emojiStickerClicked() {
|
||||
_parent->history()->owner().requestViewRepaint(_parent);
|
||||
}
|
||||
|
||||
void Sticker::premiumStickerClicked() {
|
||||
_premiumEffectPlayed = false;
|
||||
_parent->history()->owner().requestViewRepaint(_parent);
|
||||
}
|
||||
|
||||
void Sticker::ensureDataMediaCreated() const {
|
||||
if (_dataMedia) {
|
||||
return;
|
||||
@ -423,12 +438,15 @@ void Sticker::setupLottie() {
|
||||
ChatHelpers::StickerLottieSize::MessageHistory,
|
||||
size() * style::DevicePixelRatio(),
|
||||
Lottie::Quality::High);
|
||||
if (_data->isPremiumSticker()
|
||||
&& !_premiumEffectPlayed) {
|
||||
checkPremiumEffectStart();
|
||||
lottieCreated();
|
||||
}
|
||||
|
||||
void Sticker::checkPremiumEffectStart() {
|
||||
if (!_premiumEffectPlayed && _data->isPremiumSticker()) {
|
||||
_premiumEffectPlayed = true;
|
||||
_parent->delegate()->elementStartPremium(_parent, nullptr);
|
||||
}
|
||||
lottieCreated();
|
||||
}
|
||||
|
||||
void Sticker::lottieCreated() {
|
||||
|
@ -100,6 +100,8 @@ private:
|
||||
void lottieCreated();
|
||||
void unloadLottie();
|
||||
void emojiStickerClicked();
|
||||
void premiumStickerClicked();
|
||||
void checkPremiumEffectStart();
|
||||
//bool markFramesTillExternal();
|
||||
|
||||
const not_null<Element*> _parent;
|
||||
|
@ -218,6 +218,10 @@ rpl::producer<> Session::downloaderTaskFinished() const {
|
||||
return downloader().taskFinished();
|
||||
}
|
||||
|
||||
bool Session::premium() const {
|
||||
return _user->isPremium();
|
||||
}
|
||||
|
||||
uint64 Session::uniqueId() const {
|
||||
// See also Account::willHaveSessionUniqueId.
|
||||
return userId().bare
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
[[nodiscard]] Domain &domain() const;
|
||||
[[nodiscard]] Storage::Domain &domainLocal() const;
|
||||
|
||||
[[nodiscard]] bool premium() const;
|
||||
[[nodiscard]] uint64 uniqueId() const; // userId() with TestDC shift.
|
||||
[[nodiscard]] UserId userId() const;
|
||||
[[nodiscard]] PeerId userPeerId() const;
|
||||
|
@ -29,15 +29,6 @@ constexpr auto kStepBeforeDeflection = 0.75;
|
||||
constexpr auto kStepAfterDeflection = kStepBeforeDeflection
|
||||
+ (1. - kStepBeforeDeflection) / 2.;
|
||||
|
||||
[[nodiscard]] QGradientStops GradientStops() {
|
||||
return QGradientStops{
|
||||
QGradientStop(0.0, st::premiumButtonBg1->c),
|
||||
QGradientStop(.25, st::premiumButtonBg1->c),
|
||||
QGradientStop(.85, st::premiumButtonBg2->c),
|
||||
QGradientStop(1.0, st::premiumButtonBg3->c),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] QLinearGradient ComputeGradient(
|
||||
not_null<QWidget*> content,
|
||||
int left,
|
||||
@ -46,7 +37,7 @@ constexpr auto kStepAfterDeflection = kStepBeforeDeflection
|
||||
// Take a full width of parent box without paddings.
|
||||
const auto fullGradientWidth = content->parentWidget()->width();
|
||||
auto fullGradient = QLinearGradient(0, 0, fullGradientWidth, 0);
|
||||
fullGradient.setStops(GradientStops());
|
||||
fullGradient.setStops(ButtonGradientStops());
|
||||
|
||||
auto gradient = QLinearGradient(0, 0, width, 0);
|
||||
const auto fullFinal = float64(fullGradient.finalStop().x());
|
||||
@ -506,5 +497,26 @@ void AddLimitRow(not_null<Ui::VerticalLayout*> parent, int max) {
|
||||
st::boxRowPadding);
|
||||
}
|
||||
|
||||
QGradientStops LimitGradientStops() {
|
||||
return {
|
||||
{ 0.0, st::premiumButtonBg1->c },
|
||||
{ .25, st::premiumButtonBg1->c },
|
||||
{ .85, st::premiumButtonBg2->c },
|
||||
{ 1.0, st::premiumButtonBg3->c },
|
||||
};
|
||||
}
|
||||
|
||||
QGradientStops ButtonGradientStops() {
|
||||
return {
|
||||
{ 0., st::premiumButtonBg1->c },
|
||||
{ 0.6, st::premiumButtonBg2->c },
|
||||
{ 1., st::premiumButtonBg3->c },
|
||||
};
|
||||
}
|
||||
|
||||
QGradientStops LockGradientStops() {
|
||||
return ButtonGradientStops();
|
||||
}
|
||||
|
||||
} // namespace Premium
|
||||
} // namespace Ui
|
||||
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QBrush>
|
||||
|
||||
namespace tr {
|
||||
template <typename ...>
|
||||
struct phrase;
|
||||
@ -31,5 +33,9 @@ void AddBubbleRow(
|
||||
|
||||
void AddLimitRow(not_null<Ui::VerticalLayout*> parent, int max);
|
||||
|
||||
[[nodiscard]] QGradientStops LimitGradientStops();
|
||||
[[nodiscard]] QGradientStops ButtonGradientStops();
|
||||
[[nodiscard]] QGradientStops LockGradientStops();
|
||||
|
||||
} // namespace Premium
|
||||
} // namespace Ui
|
||||
|
Loading…
Reference in New Issue
Block a user