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

Implement full theming of attachments in stories.

This commit is contained in:
John Preston
2023-05-18 17:46:24 +04:00
parent ae4d660c38
commit 2c5d990e1c
53 changed files with 1113 additions and 353 deletions

View File

@@ -76,7 +76,7 @@ bool operator==(const Descriptor &a, const Descriptor &b) {
struct Preload {
Descriptor descriptor;
std::shared_ptr<Data::DocumentMedia> media;
base::weak_ptr<Window::SessionController> controller;
std::weak_ptr<ChatHelpers::Show> show;
};
[[nodiscard]] std::vector<Preload> &Preloads() {
@@ -168,7 +168,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] not_null<Ui::RpWidget*> StickerPreview(
not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
const std::shared_ptr<Data::DocumentMedia> &media,
Fn<void()> readyCallback = nullptr) {
using namespace HistoryView;
@@ -194,6 +194,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
struct State {
std::unique_ptr<Lottie::SinglePlayer> lottie;
std::unique_ptr<Lottie::SinglePlayer> effect;
style::owned_color pathFg = style::owned_color(
QColor(255, 255, 255, 64));
std::unique_ptr<Ui::PathShiftGradient> pathGradient;
bool readyInvoked = false;
};
@@ -239,15 +241,17 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
};
createLottieIfReady();
if (!state->lottie || !state->effect) {
controller->session().downloaderTaskFinished(
show->session().downloaderTaskFinished(
) | rpl::take_while([=] {
createLottieIfReady();
return !state->lottie || !state->effect;
}) | rpl::start(result->lifetime());
}
state->pathGradient = MakePathShiftGradient(
controller->chatStyle(),
[=] { result->update(); });
state->pathGradient = std::make_unique<Ui::PathShiftGradient>(
st::shadowFg,
state->pathFg.color(),
[=] { result->update(); },
rpl::never<>());
result->paintRequest(
) | rpl::start_with_next([=] {
@@ -262,7 +266,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
if (!state->lottie
|| !state->lottie->ready()
|| !state->effect->ready()) {
p.setBrush(controller->chatStyle()->msgServiceBg());
p.setBrush(st::shadowFg);
ChatHelpers::PaintStickerThumbnailPath(
p,
media.get(),
@@ -302,7 +306,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] not_null<Ui::RpWidget*> StickersPreview(
not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
Fn<void()> readyCallback) {
const auto result = Ui::CreateChild<Ui::RpWidget>(parent.get());
result->show();
@@ -327,7 +331,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
bool nextReady = false;
int index = 0;
};
const auto premium = &controller->session().api().premium();
const auto premium = &show->session().api().premium();
const auto state = lifetime.make_state<State>();
const auto create = [=](std::shared_ptr<Data::DocumentMedia> media) {
const auto outer = Ui::CreateChild<Ui::RpWidget>(result);
@@ -340,7 +344,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[maybe_unused]] const auto sticker = StickerPreview(
outer,
controller,
show,
media,
state->singleReadyCallback);
@@ -520,7 +524,7 @@ struct VideoPreviewDocument {
[[nodiscard]] not_null<Ui::RpWidget*> VideoPreview(
not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
not_null<DocumentData*> document,
bool alignToBottom,
Fn<void()> readyCallback) {
@@ -683,7 +687,7 @@ struct VideoPreviewDocument {
[[nodiscard]] not_null<Ui::RpWidget*> GenericPreview(
not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
PremiumPreview section,
Fn<void()> readyCallback) {
const auto result = Ui::CreateChild<Ui::RpWidget>(parent.get());
@@ -699,7 +703,7 @@ struct VideoPreviewDocument {
std::vector<std::shared_ptr<Data::DocumentMedia>> medias;
Ui::RpWidget *single = nullptr;
};
const auto session = &controller->session();
const auto session = &show->session();
const auto state = lifetime.make_state<State>();
const auto create = [=] {
const auto document = LookupVideo(session, section);
@@ -708,7 +712,7 @@ struct VideoPreviewDocument {
}
state->single = VideoPreview(
result,
controller,
show,
document,
!VideoAlignToTop(section),
readyCallback);
@@ -724,14 +728,18 @@ struct VideoPreviewDocument {
[[nodiscard]] not_null<Ui::RpWidget*> GenerateDefaultPreview(
not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
PremiumPreview section,
Fn<void()> readyCallback) {
switch (section) {
case PremiumPreview::Stickers:
return StickersPreview(parent, controller, readyCallback);
return StickersPreview(parent, std::move(show), readyCallback);
default:
return GenericPreview(parent, controller, section, readyCallback);
return GenericPreview(
parent,
std::move(show),
section,
readyCallback);
}
}
@@ -792,7 +800,7 @@ struct VideoPreviewDocument {
void PreviewBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
const Descriptor &descriptor,
const std::shared_ptr<Data::DocumentMedia> &media,
const QImage &back) {
@@ -825,7 +833,7 @@ void PreviewBox(
};
const auto state = outer->lifetime().make_state<State>();
state->selected = descriptor.section;
state->order = Settings::PremiumPreviewOrder(&controller->session());
state->order = Settings::PremiumPreviewOrder(&show->session());
const auto index = [=](PremiumPreview section) {
const auto it = ranges::find(state->order, section);
@@ -880,7 +888,7 @@ void PreviewBox(
};
state->stickersPreload = GenerateDefaultPreview(
outer,
controller,
show,
PremiumPreview::Stickers,
ready);
state->stickersPreload->hide();
@@ -890,13 +898,13 @@ void PreviewBox(
switch (descriptor.section) {
case PremiumPreview::Stickers:
state->content = media
? StickerPreview(outer, controller, media, state->preload)
: StickersPreview(outer, controller, state->preload);
? StickerPreview(outer, show, media, state->preload)
: StickersPreview(outer, show, state->preload);
break;
default:
state->content = GenericPreview(
outer,
controller,
show,
descriptor.section,
state->preload);
break;
@@ -955,7 +963,7 @@ void PreviewBox(
} else {
state->content = GenerateDefaultPreview(
outer,
controller,
show,
now,
state->preload);
}
@@ -1003,7 +1011,7 @@ void PreviewBox(
state->preload();
}
};
if (descriptor.fromSettings && controller->session().premium()) {
if (descriptor.fromSettings && show->session().premium()) {
box->setShowFinishedCallback(showFinished);
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
} else {
@@ -1030,16 +1038,21 @@ void PreviewBox(
auto button = descriptor.fromSettings
? object_ptr<Ui::GradientButton>::fromRaw(
Settings::CreateSubscribeButton({
controller,
box,
computeRef,
.parent = box,
.computeRef = computeRef,
.show = show,
}))
: CreateUnlockButton(box, std::move(unlock));
button->resizeToWidth(width);
if (!descriptor.fromSettings) {
button->setClickedCallback([=] {
const auto window = show->resolveWindow(
ChatHelpers::WindowUsage::PremiumPromo);
if (!window) {
return;
}
Settings::ShowPremium(
controller,
window,
Settings::LookupPremiumRef(state->selected.current()));
});
}
@@ -1052,7 +1065,7 @@ void PreviewBox(
if (descriptor.fromSettings) {
Data::AmPremiumValue(
&controller->session()
&show->session()
) | rpl::skip(1) | rpl::start_with_next([=] {
box->closeBox();
}, box->lifetime());
@@ -1076,25 +1089,26 @@ void PreviewBox(
}
void Show(
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
const Descriptor &descriptor,
const std::shared_ptr<Data::DocumentMedia> &media,
QImage back) {
const auto box = controller->show(
Box(PreviewBox, controller, descriptor, media, back));
auto box = Box(PreviewBox, show, descriptor, media, back);
const auto raw = box.data();
show->showBox(std::move(box));
if (descriptor.shownCallback) {
descriptor.shownCallback(box);
descriptor.shownCallback(raw);
}
}
void Show(not_null<Window::SessionController*> controller, QImage back) {
void Show(std::shared_ptr<ChatHelpers::Show> show, QImage back) {
auto &list = Preloads();
for (auto i = begin(list); i != end(list);) {
const auto already = i->controller.get();
const auto already = i->show.lock();
if (!already) {
i = list.erase(i);
} else if (already == controller) {
Show(controller, i->descriptor, i->media, back);
} else if (already == show) {
Show(std::move(show), i->descriptor, i->media, back);
i = list.erase(i);
return;
} else {
@@ -1104,21 +1118,23 @@ void Show(not_null<Window::SessionController*> controller, QImage back) {
}
void Show(
not_null<Window::SessionController*> controller,
std::shared_ptr<ChatHelpers::Show> show,
Descriptor &&descriptor) {
if (!controller->session().premiumPossible()) {
const auto box = controller->show(Box(PremiumUnavailableBox));
if (!show->session().premiumPossible()) {
auto box = Box(PremiumUnavailableBox);
const auto raw = box.data();
show->showBox(std::move(box));
if (descriptor.shownCallback) {
descriptor.shownCallback(box);
descriptor.shownCallback(raw);
}
return;
}
auto &list = Preloads();
for (auto i = begin(list); i != end(list);) {
const auto already = i->controller.get();
const auto already = i->show.lock();
if (!already) {
i = list.erase(i);
} else if (already == controller) {
} else if (already == show) {
if (i->descriptor == descriptor) {
return;
}
@@ -1135,13 +1151,13 @@ void Show(
}
}
const auto weak = base::make_weak(controller);
const auto weak = std::weak_ptr(show);
list.push_back({
.descriptor = descriptor,
.media = (descriptor.requestedSticker
? descriptor.requestedSticker->createMediaView()
: nullptr),
.controller = weak,
.show = weak,
});
if (const auto &media = list.back().media) {
PreloadSticker(media);
@@ -1166,8 +1182,8 @@ void Show(
Images::CornersMask(st::boxRadius),
RectPart::TopLeft | RectPart::TopRight);
crl::on_main([=] {
if (const auto strong = weak.get()) {
Show(strong, result);
if (auto strong = weak.lock()) {
Show(std::move(strong), result);
}
});
});
@@ -1178,7 +1194,7 @@ void Show(
void ShowStickerPreviewBox(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document) {
Show(controller, Descriptor{
Show(controller->uiShow(), Descriptor{
.section = PremiumPreview::Stickers,
.requestedSticker = document,
});
@@ -1188,7 +1204,14 @@ void ShowPremiumPreviewBox(
not_null<Window::SessionController*> controller,
PremiumPreview section,
Fn<void(not_null<Ui::BoxContent*>)> shown) {
Show(controller, Descriptor{
ShowPremiumPreviewBox(controller->uiShow(), section, std::move(shown));
}
void ShowPremiumPreviewBox(
std::shared_ptr<ChatHelpers::Show> show,
PremiumPreview section,
Fn<void(not_null<Ui::BoxContent*>)> shown) {
Show(std::move(show), Descriptor{
.section = section,
.shownCallback = std::move(shown),
});
@@ -1198,7 +1221,7 @@ void ShowPremiumPreviewToBuy(
not_null<Window::SessionController*> controller,
PremiumPreview section,
Fn<void()> hiddenCallback) {
Show(controller, Descriptor{
Show(controller->uiShow(), Descriptor{
.section = section,
.fromSettings = true,
.hiddenCallback = std::move(hiddenCallback),
@@ -1337,7 +1360,10 @@ void DoubledLimitsPreviewBox(
Main::Domain::kPremiumMaxAccounts,
till,
});
Ui::Premium::ShowListBox(box, std::move(entries));
Ui::Premium::ShowListBox(
box,
st::defaultPremiumLimits,
std::move(entries));
}
object_ptr<Ui::GradientButton> CreateUnlockButton(