mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added special fading-in top bar with title to giveaway box.
This commit is contained in:
parent
b56b9b1fb9
commit
49d5cf939c
2 changed files with 189 additions and 35 deletions
|
@ -27,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/effects/premium_graphics.h"
|
#include "ui/effects/premium_graphics.h"
|
||||||
#include "ui/effects/premium_top_bar.h"
|
#include "ui/effects/premium_top_bar.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "ui/rect.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
|
@ -67,6 +69,159 @@ constexpr auto kDoneTooltipDuration = 5 * crl::time(1000);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QWidget *FindFirstShadowInBox(not_null<Ui::BoxContent*> box) {
|
||||||
|
for (const auto &child : box->children()) {
|
||||||
|
if (child && child->isWidgetType()) {
|
||||||
|
const auto w = static_cast<QWidget*>(child);
|
||||||
|
if (w->height() == st::lineWidth) {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPremiumTopBarWithDefaultTitleBar(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
rpl::producer<> showFinished,
|
||||||
|
rpl::producer<QString> titleText) {
|
||||||
|
struct State final {
|
||||||
|
Ui::Animations::Simple animation;
|
||||||
|
Ui::Text::String title;
|
||||||
|
|
||||||
|
Ui::RpWidget close;
|
||||||
|
};
|
||||||
|
const auto state = box->lifetime().make_state<State>();
|
||||||
|
box->setNoContentMargin(true);
|
||||||
|
|
||||||
|
std::move(
|
||||||
|
titleText
|
||||||
|
) | rpl::start_with_next([=](const QString &s) {
|
||||||
|
state->title.setText(st::startGiveawayBox.title.style, s);
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
const auto hPadding = rect::m::sum::h(st::boxRowPadding);
|
||||||
|
const auto titlePaintContext = Ui::Text::PaintContext{
|
||||||
|
.position = st::boxTitlePosition,
|
||||||
|
.outerWidth = (st::boxWideWidth - hPadding),
|
||||||
|
.availableWidth = (st::boxWideWidth - hPadding),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto isCloseBarShown = [=] { return box->scrollTop() > 0; };
|
||||||
|
|
||||||
|
const auto closeTopBar = box->setPinnedToTopContent(
|
||||||
|
object_ptr<Ui::RpWidget>(box));
|
||||||
|
closeTopBar->resize(box->width(), st::boxTitleHeight);
|
||||||
|
closeTopBar->paintRequest(
|
||||||
|
) | rpl::start_with_next([=](const QRect &r) {
|
||||||
|
auto p = Painter(closeTopBar);
|
||||||
|
const auto radius = st::boxRadius;
|
||||||
|
const auto progress = state->animation.value(isCloseBarShown()
|
||||||
|
? 1.
|
||||||
|
: 0.);
|
||||||
|
const auto resultRect = r + QMargins{ 0, 0, 0, radius };
|
||||||
|
{
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
|
||||||
|
if (progress < 1.) {
|
||||||
|
auto path = QPainterPath();
|
||||||
|
path.addRect(resultRect);
|
||||||
|
path.addRect(
|
||||||
|
st::boxRowPadding.left(),
|
||||||
|
0,
|
||||||
|
resultRect.width() - hPadding,
|
||||||
|
resultRect.height());
|
||||||
|
p.setClipPath(path);
|
||||||
|
PainterHighQualityEnabler hq(p);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(st::boxDividerBg);
|
||||||
|
p.drawRoundedRect(resultRect, radius, radius);
|
||||||
|
}
|
||||||
|
if (progress > 0.) {
|
||||||
|
p.setOpacity(progress);
|
||||||
|
|
||||||
|
p.setClipping(false);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(st::boxBg);
|
||||||
|
p.drawRoundedRect(resultRect, radius, radius);
|
||||||
|
|
||||||
|
p.setPen(st::startGiveawayBox.title.textFg);
|
||||||
|
p.setBrush(Qt::NoBrush);
|
||||||
|
state->title.draw(p, titlePaintContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, closeTopBar->lifetime());
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto close = Ui::CreateChild<Ui::IconButton>(
|
||||||
|
closeTopBar.get(),
|
||||||
|
st::startGiveawayBoxTitleClose);
|
||||||
|
close->setClickedCallback([=] { box->closeBox(); });
|
||||||
|
closeTopBar->widthValue(
|
||||||
|
) | rpl::start_with_next([=](int w) {
|
||||||
|
const auto &pos = st::giveawayGiftCodeCoverClosePosition;
|
||||||
|
close->moveToRight(pos.x(), pos.y());
|
||||||
|
}, box->lifetime());
|
||||||
|
close->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto bar = Ui::CreateChild<Ui::Premium::TopBar>(
|
||||||
|
box.get(),
|
||||||
|
st::startGiveawayCover,
|
||||||
|
nullptr,
|
||||||
|
tr::lng_giveaway_new_title(),
|
||||||
|
tr::lng_giveaway_new_about(Ui::Text::RichLangValue),
|
||||||
|
true);
|
||||||
|
bar->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<Ui::BoxContentDivider>(
|
||||||
|
box.get(),
|
||||||
|
st::giveawayGiftCodeTopHeight
|
||||||
|
- st::boxTitleHeight
|
||||||
|
+ st::boxDividerHeight
|
||||||
|
+ st::settingsSectionSkip,
|
||||||
|
st::boxDividerBg,
|
||||||
|
RectPart::Bottom),
|
||||||
|
{});
|
||||||
|
bar->setPaused(true);
|
||||||
|
bar->setRoundEdges(false);
|
||||||
|
bar->setMaximumHeight(st::giveawayGiftCodeTopHeight);
|
||||||
|
bar->setMinimumHeight(st::infoLayerTopBarHeight);
|
||||||
|
bar->resize(bar->width(), bar->maximumHeight());
|
||||||
|
box->widthValue(
|
||||||
|
) | rpl::start_with_next([=](int w) {
|
||||||
|
bar->resizeToWidth(w - hPadding);
|
||||||
|
bar->moveToLeft(st::boxRowPadding.left(), bar->y());
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
std::move(
|
||||||
|
showFinished
|
||||||
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
|
closeTopBar->raise();
|
||||||
|
if (const auto shadow = FindFirstShadowInBox(box)) {
|
||||||
|
bar->stackUnder(shadow);
|
||||||
|
}
|
||||||
|
bar->setPaused(false);
|
||||||
|
box->scrolls(
|
||||||
|
) | rpl::map(isCloseBarShown) | rpl::distinct_until_changed(
|
||||||
|
) | rpl::start_with_next([=](bool showBar) {
|
||||||
|
state->animation.stop();
|
||||||
|
state->animation.start(
|
||||||
|
[=] { closeTopBar->update(); },
|
||||||
|
showBar ? 0. : 1.,
|
||||||
|
showBar ? 1. : 0.,
|
||||||
|
st::slideWrapDuration);
|
||||||
|
}, box->lifetime());
|
||||||
|
box->scrolls(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
bar->moveToLeft(bar->x(), -box->scrollTop());
|
||||||
|
}, box->lifetime());
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
bar->show();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void CreateGiveawayBox(
|
void CreateGiveawayBox(
|
||||||
|
@ -77,37 +232,6 @@ void CreateGiveawayBox(
|
||||||
|
|
||||||
const auto weakWindow = base::make_weak(controller->parentController());
|
const auto weakWindow = base::make_weak(controller->parentController());
|
||||||
|
|
||||||
const auto bar = box->verticalLayout()->add(
|
|
||||||
object_ptr<Ui::Premium::TopBar>(
|
|
||||||
box,
|
|
||||||
st::giveawayGiftCodeCover,
|
|
||||||
nullptr,
|
|
||||||
tr::lng_giveaway_new_title(),
|
|
||||||
tr::lng_giveaway_new_about(Ui::Text::RichLangValue),
|
|
||||||
true));
|
|
||||||
{
|
|
||||||
bar->setPaused(true);
|
|
||||||
bar->setMaximumHeight(st::giveawayGiftCodeTopHeight);
|
|
||||||
bar->setMinimumHeight(st::infoLayerTopBarHeight);
|
|
||||||
bar->resize(bar->width(), bar->maximumHeight());
|
|
||||||
|
|
||||||
const auto container = box->verticalLayout();
|
|
||||||
const auto &padding = st::giveawayGiftCodeCoverDividerPadding;
|
|
||||||
Settings::AddSkip(container, padding.top());
|
|
||||||
Settings::AddDivider(container);
|
|
||||||
Settings::AddSkip(container, padding.bottom());
|
|
||||||
|
|
||||||
const auto close = Ui::CreateChild<Ui::IconButton>(
|
|
||||||
container.get(),
|
|
||||||
st::boxTitleClose);
|
|
||||||
close->setClickedCallback([=] { box->closeBox(); });
|
|
||||||
box->widthValue(
|
|
||||||
) | rpl::start_with_next([=](int) {
|
|
||||||
const auto &pos = st::giveawayGiftCodeCoverClosePosition;
|
|
||||||
close->moveToRight(pos.x(), pos.y());
|
|
||||||
}, box->lifetime());
|
|
||||||
}
|
|
||||||
|
|
||||||
using GiveawayType = Giveaway::GiveawayTypeRow::Type;
|
using GiveawayType = Giveaway::GiveawayTypeRow::Type;
|
||||||
using GiveawayGroup = Ui::RadioenumGroup<GiveawayType>;
|
using GiveawayGroup = Ui::RadioenumGroup<GiveawayType>;
|
||||||
struct State final {
|
struct State final {
|
||||||
|
@ -132,6 +256,20 @@ void CreateGiveawayBox(
|
||||||
const auto state = box->lifetime().make_state<State>(peer);
|
const auto state = box->lifetime().make_state<State>(peer);
|
||||||
const auto typeGroup = std::make_shared<GiveawayGroup>();
|
const auto typeGroup = std::make_shared<GiveawayGroup>();
|
||||||
|
|
||||||
|
auto showFinished = Ui::BoxShowFinishes(box);
|
||||||
|
AddPremiumTopBarWithDefaultTitleBar(
|
||||||
|
box,
|
||||||
|
rpl::duplicate(showFinished),
|
||||||
|
rpl::conditional(
|
||||||
|
state->typeValue.value(
|
||||||
|
) | rpl::map(rpl::mappers::_1 == GiveawayType::Random),
|
||||||
|
tr::lng_giveaway_start(),
|
||||||
|
tr::lng_giveaway_award()));
|
||||||
|
{
|
||||||
|
const auto &padding = st::giveawayGiftCodeCoverDividerPadding;
|
||||||
|
Settings::AddSkip(box->verticalLayout(), padding.bottom());
|
||||||
|
}
|
||||||
|
|
||||||
const auto loading = box->addRow(
|
const auto loading = box->addRow(
|
||||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
box,
|
box,
|
||||||
|
@ -587,7 +725,7 @@ void CreateGiveawayBox(
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TODO mini-icon.
|
// TODO mini-icon.
|
||||||
const auto &stButton = st::premiumGiftBox;
|
const auto &stButton = st::startGiveawayBox;
|
||||||
box->setStyle(stButton);
|
box->setStyle(stButton);
|
||||||
auto button = object_ptr<Ui::RoundButton>(
|
auto button = object_ptr<Ui::RoundButton>(
|
||||||
box,
|
box,
|
||||||
|
@ -691,11 +829,12 @@ void CreateGiveawayBox(
|
||||||
}
|
}
|
||||||
state->typeValue.force_assign(GiveawayType::Random);
|
state->typeValue.force_assign(GiveawayType::Random);
|
||||||
|
|
||||||
box->setShowFinishedCallback([=] {
|
std::move(
|
||||||
|
showFinished
|
||||||
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
if (!loading->toggled()) {
|
if (!loading->toggled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bar->setPaused(false);
|
|
||||||
state->lifetimeApi = state->apiOptions.request(
|
state->lifetimeApi = state->apiOptions.request(
|
||||||
) | rpl::start_with_error_done([=](const QString &error) {
|
) | rpl::start_with_error_done([=](const QString &error) {
|
||||||
}, [=] {
|
}, [=] {
|
||||||
|
@ -706,5 +845,5 @@ void CreateGiveawayBox(
|
||||||
contentWrap->toggle(true, anim::type::instant);
|
contentWrap->toggle(true, anim::type::instant);
|
||||||
contentWrap->resizeToWidth(box->width());
|
contentWrap->resizeToWidth(box->width());
|
||||||
});
|
});
|
||||||
});
|
}, box->lifetime());
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,3 +163,18 @@ giveawayRefundedLabel: FlatLabel(boxLabel) {
|
||||||
textFg: attentionButtonFg;
|
textFg: attentionButtonFg;
|
||||||
}
|
}
|
||||||
giveawayRefundedPadding: margins(8px, 10px, 8px, 10px);
|
giveawayRefundedPadding: margins(8px, 10px, 8px, 10px);
|
||||||
|
|
||||||
|
startGiveawayBox: Box(premiumGiftBox) {
|
||||||
|
shadowIgnoreTopSkip: true;
|
||||||
|
}
|
||||||
|
startGiveawayScrollArea: ScrollArea(boxScroll) {
|
||||||
|
deltax: 3px;
|
||||||
|
deltat: 50px;
|
||||||
|
}
|
||||||
|
startGiveawayBoxTitleClose: IconButton(boxTitleClose) {
|
||||||
|
ripple: universalRippleAnimation;
|
||||||
|
}
|
||||||
|
startGiveawayCover: PremiumCover(giveawayGiftCodeCover) {
|
||||||
|
bg: boxDividerBg;
|
||||||
|
additionalShadowForDarkThemes: false;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue