mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Show nice thumbnails for paid albums.
This commit is contained in:
parent
dfc422b505
commit
90dfae52f5
7 changed files with 187 additions and 88 deletions
|
@ -34,7 +34,7 @@ constexpr auto kTransactionsLimit = 100;
|
|||
const auto photo = tl.data().vphoto()
|
||||
? owner->photoFromWeb(*tl.data().vphoto(), ImageLocation())
|
||||
: nullptr;
|
||||
auto extended = std::vector<CreditsHistoryEntry::Media>();
|
||||
auto extended = std::vector<CreditsHistoryMedia>();
|
||||
if (const auto list = tl.data().vextended_media()) {
|
||||
extended.reserve(list->v.size());
|
||||
for (const auto &media : list->v) {
|
||||
|
@ -42,9 +42,9 @@ constexpr auto kTransactionsLimit = 100;
|
|||
if (const auto inner = photo.vphoto()) {
|
||||
const auto photo = owner->processPhoto(*inner);
|
||||
if (!photo->isNull()) {
|
||||
extended.push_back(CreditsHistoryEntry::Media{
|
||||
.type = CreditsHistoryEntry::MediaType::Photo,
|
||||
.mediaId = photo->id,
|
||||
extended.push_back(CreditsHistoryMedia{
|
||||
.type = CreditsHistoryMediaType::Photo,
|
||||
.id = photo->id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -54,9 +54,9 @@ constexpr auto kTransactionsLimit = 100;
|
|||
if (document->isAnimation()
|
||||
|| document->isVideoFile()
|
||||
|| document->isGifv()) {
|
||||
extended.push_back(CreditsHistoryEntry::Media{
|
||||
.type = CreditsHistoryEntry::MediaType::Video,
|
||||
.mediaId = document->id,
|
||||
extended.push_back(CreditsHistoryMedia{
|
||||
.type = CreditsHistoryMediaType::Video,
|
||||
.id = document->id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,11 +156,18 @@ struct PaidMediaData {
|
|||
not_null<Payments::CreditsFormData*> form,
|
||||
int photoSize) {
|
||||
if (const auto data = LookupPaidMediaData(session, form)) {
|
||||
const auto first = data.invoice->extendedMedia.front().get();
|
||||
if (const auto photo = first->photo()) {
|
||||
if (photo->extendedMediaPreview()) {
|
||||
return Settings::PaidMediaPhoto(parent, photo, photoSize);
|
||||
}
|
||||
const auto first = data.invoice->extendedMedia[0]->photo();
|
||||
const auto second = (data.photos > 1)
|
||||
? data.invoice->extendedMedia[1]->photo()
|
||||
: nullptr;
|
||||
const auto totalCount = int(data.invoice->extendedMedia.size());
|
||||
if (first && first->extendedMediaPreview()) {
|
||||
return Settings::PaidMediaThumbnail(
|
||||
parent,
|
||||
first,
|
||||
second,
|
||||
totalCount,
|
||||
photoSize);
|
||||
}
|
||||
}
|
||||
if (form->photo) {
|
||||
|
|
|
@ -19,6 +19,16 @@ struct CreditTopupOption final {
|
|||
|
||||
using CreditTopupOptions = std::vector<CreditTopupOption>;
|
||||
|
||||
enum class CreditsHistoryMediaType {
|
||||
Photo,
|
||||
Video,
|
||||
};
|
||||
|
||||
struct CreditsHistoryMedia {
|
||||
CreditsHistoryMediaType type = CreditsHistoryMediaType::Photo;
|
||||
uint64 id = 0;
|
||||
};
|
||||
|
||||
struct CreditsHistoryEntry final {
|
||||
using PhotoId = uint64;
|
||||
enum class PeerType {
|
||||
|
@ -30,21 +40,13 @@ struct CreditsHistoryEntry final {
|
|||
PremiumBot,
|
||||
Ads,
|
||||
};
|
||||
enum class MediaType {
|
||||
Photo,
|
||||
Video,
|
||||
};
|
||||
struct Media {
|
||||
MediaType type = MediaType::Photo;
|
||||
uint64 mediaId = 0;
|
||||
};
|
||||
|
||||
QString id;
|
||||
QString title;
|
||||
QString description;
|
||||
QDateTime date;
|
||||
PhotoId photoId = 0;
|
||||
std::vector<Media> extended;
|
||||
std::vector<CreditsHistoryMedia> extended;
|
||||
uint64 credits = 0;
|
||||
uint64 bareMsgId = 0;
|
||||
uint64 barePeerId = 0;
|
||||
|
|
|
@ -569,26 +569,20 @@ object_ptr<Ui::RpWidget> HistoryEntryPhoto(
|
|||
photoSize);
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> HistoryEntryVideo(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<DocumentData*> video,
|
||||
int photoSize) {
|
||||
return GenericEntryPhoto(
|
||||
parent,
|
||||
[=](Fn<void()> update) {
|
||||
return Ui::GenerateCreditsPaintEntryCallback(video, update);
|
||||
},
|
||||
photoSize);
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> PaidMediaPhoto(
|
||||
object_ptr<Ui::RpWidget> PaidMediaThumbnail(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<PhotoData*> photo,
|
||||
PhotoData *second,
|
||||
int totalCount,
|
||||
int photoSize) {
|
||||
return GenericEntryPhoto(
|
||||
parent,
|
||||
[=](Fn<void()> update) {
|
||||
return Ui::GeneratePaidMediaPaintCallback(photo, update);
|
||||
return Ui::GeneratePaidMediaPaintCallback(
|
||||
photo,
|
||||
second,
|
||||
totalCount,
|
||||
update);
|
||||
},
|
||||
photoSize);
|
||||
}
|
||||
|
|
|
@ -65,14 +65,11 @@ void ReceiptCreditsBox(
|
|||
not_null<PhotoData*> photo,
|
||||
int photoSize);
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> HistoryEntryVideo(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<DocumentData*> video,
|
||||
int photoSize);
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> PaidMediaPhoto(
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> PaidMediaThumbnail(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<PhotoData*> photo,
|
||||
PhotoData *second,
|
||||
int totalCount,
|
||||
int photoSize);
|
||||
|
||||
void SmallBalanceBox(
|
||||
|
|
|
@ -37,21 +37,62 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtSvg/QSvgRenderer>
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
using PaintRoundImageCallback = Fn<void(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
int size)>;
|
||||
PaintRoundImageCallback MultiThumbnail(
|
||||
PaintRoundImageCallback first,
|
||||
PaintRoundImageCallback second,
|
||||
int totalCount) {
|
||||
const auto cache = std::make_shared<QImage>();
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) {
|
||||
const auto stroke = st::lineWidth * 2;
|
||||
const auto shift = stroke * 3;
|
||||
if (size <= 2 * shift) {
|
||||
first(p, x, y, outerWidth, size);
|
||||
return;
|
||||
}
|
||||
const auto smaller = size - shift;
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto full = QSize(size, size) * ratio;
|
||||
if (cache->size() != full) {
|
||||
*cache = QImage(full, QImage::Format_ARGB32_Premultiplied);
|
||||
cache->setDevicePixelRatio(ratio);
|
||||
}
|
||||
cache->fill(Qt::transparent);
|
||||
auto q = Painter(cache.get());
|
||||
second(q, shift, 0, outerWidth, smaller);
|
||||
q.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
q.setPen(QPen(Qt::transparent, 2 * stroke));
|
||||
q.setBrush(Qt::NoBrush);
|
||||
const auto radius = st::roundRadiusLarge;
|
||||
auto hq = PainterHighQualityEnabler(q);
|
||||
q.drawRoundedRect(QRect(0, shift, smaller, smaller), radius, radius);
|
||||
q.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
first(q, 0, shift, outerWidth, smaller);
|
||||
q.setPen(Qt::NoPen);
|
||||
q.setBrush(st::shadowFg);
|
||||
q.drawRoundedRect(QRect(0, shift, smaller, smaller), radius, radius);
|
||||
q.setPen(st::toastFg);
|
||||
q.setFont(style::font(smaller / 2, style::FontFlag::Semibold, 0));
|
||||
q.drawText(
|
||||
QRect(0, shift, smaller, smaller),
|
||||
QString::number(totalCount),
|
||||
style::al_center);
|
||||
q.end();
|
||||
|
||||
p.drawImage(x, y, *cache);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
QImage GenerateStars(int height, int count) {
|
||||
constexpr auto kOutlineWidth = .6;
|
||||
constexpr auto kStrokeWidth = 3;
|
||||
constexpr auto kShift = 3;
|
||||
|
||||
auto colorized = qs(Ui::Premium::ColorizedSvg(
|
||||
Ui::Premium::CreditsIconGradientStops()));
|
||||
auto colorized = qs(Premium::ColorizedSvg(
|
||||
Premium::CreditsIconGradientStops()));
|
||||
colorized.replace(
|
||||
u"stroke=\"none\""_q,
|
||||
u"stroke=\"%1\""_q.arg(st::creditsStroke->c.name()));
|
||||
|
@ -98,10 +139,10 @@ QImage GenerateStars(int height, int count) {
|
|||
return frame;
|
||||
}
|
||||
|
||||
not_null<Ui::RpWidget*> CreateSingleStarWidget(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<RpWidget*> CreateSingleStarWidget(
|
||||
not_null<RpWidget*> parent,
|
||||
int height) {
|
||||
const auto widget = Ui::CreateChild<Ui::RpWidget>(parent);
|
||||
const auto widget = CreateChild<RpWidget>(parent);
|
||||
const auto image = GenerateStars(height, 1);
|
||||
widget->resize(image.size() / style::DevicePixelRatio());
|
||||
widget->paintRequest(
|
||||
|
@ -113,15 +154,15 @@ not_null<Ui::RpWidget*> CreateSingleStarWidget(
|
|||
return widget;
|
||||
}
|
||||
|
||||
not_null<Ui::MaskedInputField*> AddInputFieldForCredits(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<MaskedInputField*> AddInputFieldForCredits(
|
||||
not_null<VerticalLayout*> container,
|
||||
rpl::producer<uint64> value) {
|
||||
const auto &st = st::botEarnInputField;
|
||||
const auto inputContainer = container->add(
|
||||
CreateSkipWidget(container, st.heightMin));
|
||||
const auto currentValue = rpl::variable<uint64>(
|
||||
rpl::duplicate(value));
|
||||
const auto input = Ui::CreateChild<Ui::NumberInput>(
|
||||
const auto input = CreateChild<NumberInput>(
|
||||
inputContainer,
|
||||
st,
|
||||
tr::lng_bot_earn_out_ph(),
|
||||
|
@ -146,16 +187,16 @@ not_null<Ui::MaskedInputField*> AddInputFieldForCredits(
|
|||
st::boxRowPadding.left(),
|
||||
st.textMargins.top());
|
||||
}, input->lifetime());
|
||||
Ui::ToggleChildrenVisibility(inputContainer, true);
|
||||
ToggleChildrenVisibility(inputContainer, true);
|
||||
return input;
|
||||
}
|
||||
|
||||
PaintRoundImageCallback GenerateCreditsPaintUserpicCallback(
|
||||
const Data::CreditsHistoryEntry &entry) {
|
||||
const auto bg = [&]() -> Ui::EmptyUserpic::BgColors {
|
||||
const auto bg = [&]() -> EmptyUserpic::BgColors {
|
||||
switch (entry.peerType) {
|
||||
case Data::CreditsHistoryEntry::PeerType::Peer:
|
||||
return Ui::EmptyUserpic::UserpicColor(0);
|
||||
return EmptyUserpic::UserpicColor(0);
|
||||
case Data::CreditsHistoryEntry::PeerType::AppStore:
|
||||
return { st::historyPeer7UserpicBg, st::historyPeer7UserpicBg2 };
|
||||
case Data::CreditsHistoryEntry::PeerType::PlayMarket:
|
||||
|
@ -172,7 +213,7 @@ PaintRoundImageCallback GenerateCreditsPaintUserpicCallback(
|
|||
}
|
||||
Unexpected("Unknown peer type.");
|
||||
}();
|
||||
const auto userpic = std::make_shared<Ui::EmptyUserpic>(bg, QString());
|
||||
const auto userpic = std::make_shared<EmptyUserpic>(bg, QString());
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||
userpic->paintCircle(p, x, y, outerWidth, size);
|
||||
using PeerType = Data::CreditsHistoryEntry::PeerType;
|
||||
|
@ -190,7 +231,7 @@ PaintRoundImageCallback GenerateCreditsPaintUserpicCallback(
|
|||
};
|
||||
}
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void()> update) {
|
||||
struct State {
|
||||
|
@ -240,7 +281,7 @@ Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
|||
};
|
||||
}
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<DocumentData*> video,
|
||||
Fn<void()> update) {
|
||||
struct State {
|
||||
|
@ -286,7 +327,36 @@ Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
|||
};
|
||||
}
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GeneratePaidMediaPaintCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<Main::Session*> session,
|
||||
Data::CreditsHistoryMedia media,
|
||||
Fn<void()> update) {
|
||||
return (media.type == Data::CreditsHistoryMediaType::Photo)
|
||||
? GenerateCreditsPaintEntryCallback(
|
||||
session->data().photo(media.id),
|
||||
std::move(update))
|
||||
: GenerateCreditsPaintEntryCallback(
|
||||
session->data().document(media.id),
|
||||
std::move(update));
|
||||
}
|
||||
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<Main::Session*> session,
|
||||
const std::vector<Data::CreditsHistoryMedia> &media,
|
||||
Fn<void()> update) {
|
||||
if (media.size() == 1) {
|
||||
return GenerateCreditsPaintEntryCallback(
|
||||
session,
|
||||
media.front(),
|
||||
std::move(update));
|
||||
}
|
||||
return MultiThumbnail(
|
||||
GenerateCreditsPaintEntryCallback(session, media[0], update),
|
||||
GenerateCreditsPaintEntryCallback(session, media[1], update),
|
||||
media.size());
|
||||
}
|
||||
|
||||
PaintRoundImageCallback GeneratePaidPhotoPaintCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void()> update) {
|
||||
struct State {
|
||||
|
@ -294,7 +364,8 @@ Fn<void(Painter &, int, int, int, int)> GeneratePaidMediaPaintCallback(
|
|||
}
|
||||
|
||||
QImage image;
|
||||
Ui::SpoilerAnimation spoiler;
|
||||
QImage spoilerCornerCache;
|
||||
SpoilerAnimation spoiler;
|
||||
};
|
||||
const auto state = std::make_shared<State>(update);
|
||||
|
||||
|
@ -322,36 +393,49 @@ Fn<void(Painter &, int, int, int, int)> GeneratePaidMediaPaintCallback(
|
|||
{ .options = Images::Option::RoundLarge });
|
||||
}
|
||||
p.drawImage(x, y, state->image);
|
||||
Ui::FillSpoilerRect(
|
||||
FillSpoilerRect(
|
||||
p,
|
||||
QRect(x, y, size, size),
|
||||
Ui::DefaultImageSpoiler().frame(
|
||||
state->spoiler.index(crl::now(), false)));
|
||||
Images::CornersMaskRef(
|
||||
Images::CornersMask(ImageRoundRadius::Large)),
|
||||
DefaultImageSpoiler().frame(
|
||||
state->spoiler.index(crl::now(), false)),
|
||||
state->spoilerCornerCache);
|
||||
};
|
||||
}
|
||||
|
||||
Fn<Fn<void(Painter&, int, int, int, int)>(Fn<void()>)> PaintPreviewCallback(
|
||||
PaintRoundImageCallback GeneratePaidMediaPaintCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
PhotoData *second,
|
||||
int totalCount,
|
||||
Fn<void()> update) {
|
||||
if (!second) {
|
||||
return GeneratePaidPhotoPaintCallback(photo, update);
|
||||
}
|
||||
return MultiThumbnail(
|
||||
GeneratePaidPhotoPaintCallback(photo, update),
|
||||
GeneratePaidPhotoPaintCallback(second, update),
|
||||
totalCount);
|
||||
}
|
||||
|
||||
Fn<PaintRoundImageCallback(Fn<void()>)> PaintPreviewCallback(
|
||||
not_null<Main::Session*> session,
|
||||
const Data::CreditsHistoryEntry &entry) {
|
||||
using MediaType = Data::CreditsHistoryEntry::MediaType;
|
||||
using MediaType = Data::CreditsHistoryMediaType;
|
||||
const auto &extended = entry.extended;
|
||||
const auto owner = &session->data();
|
||||
const auto photo = entry.photoId
|
||||
? owner->photo(entry.photoId).get()
|
||||
: (!extended.empty() && extended.front().type == MediaType::Photo)
|
||||
? owner->photo(extended.front().mediaId).get()
|
||||
: nullptr;
|
||||
const auto video = (!extended.empty()
|
||||
&& extended.front().type == MediaType::Video)
|
||||
? owner->document(extended.front().mediaId).get()
|
||||
: nullptr;
|
||||
if (photo) {
|
||||
if (!extended.empty()) {
|
||||
return [=](Fn<void()> update) {
|
||||
return Ui::GenerateCreditsPaintEntryCallback(photo, update);
|
||||
return GenerateCreditsPaintEntryCallback(
|
||||
session,
|
||||
extended,
|
||||
std::move(update));
|
||||
};
|
||||
} else if (video) {
|
||||
} else if (entry.photoId) {
|
||||
const auto photo = session->data().photo(entry.photoId);
|
||||
return [=](Fn<void()> update) {
|
||||
return Ui::GenerateCreditsPaintEntryCallback(video, update);
|
||||
return GenerateCreditsPaintEntryCallback(
|
||||
photo,
|
||||
std::move(update));
|
||||
};
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -12,6 +12,7 @@ class DocumentData;
|
|||
|
||||
namespace Data {
|
||||
struct CreditsHistoryEntry;
|
||||
struct CreditsHistoryMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Main {
|
||||
|
@ -26,6 +27,13 @@ class VerticalLayout;
|
|||
|
||||
namespace Ui {
|
||||
|
||||
using PaintRoundImageCallback = Fn<void(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
int size)>;
|
||||
|
||||
[[nodiscard]] QImage GenerateStars(int height, int count);
|
||||
|
||||
[[nodiscard]] not_null<Ui::RpWidget*> CreateSingleStarWidget(
|
||||
|
@ -36,22 +44,29 @@ namespace Ui {
|
|||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<uint64> value);
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintUserpicCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintUserpicCallback(
|
||||
const Data::CreditsHistoryEntry &entry);
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void()> update);
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GenerateCreditsPaintEntryCallback(
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<DocumentData*> video,
|
||||
Fn<void()> update);
|
||||
|
||||
Fn<void(Painter &, int, int, int, int)> GeneratePaidMediaPaintCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
PaintRoundImageCallback GenerateCreditsPaintEntryCallback(
|
||||
not_null<Main::Session*> session,
|
||||
Data::CreditsHistoryMedia media,
|
||||
Fn<void()> update);
|
||||
|
||||
Fn<Fn<void(Painter&, int, int, int, int)>(Fn<void()>)> PaintPreviewCallback(
|
||||
PaintRoundImageCallback GeneratePaidMediaPaintCallback(
|
||||
not_null<PhotoData*> photo,
|
||||
PhotoData *second,
|
||||
int totalCount,
|
||||
Fn<void()> update);
|
||||
|
||||
Fn<PaintRoundImageCallback(Fn<void()>)> PaintPreviewCallback(
|
||||
not_null<Main::Session*> session,
|
||||
const Data::CreditsHistoryEntry &entry);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue