mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Handle GiftCode links, show Gift Link box.
This commit is contained in:
parent
3fc9ed0ccb
commit
744c1b925e
15 changed files with 715 additions and 57 deletions
|
@ -816,20 +816,6 @@ PRIVATE
|
|||
history/history_view_highlight_manager.h
|
||||
history/history_widget.cpp
|
||||
history/history_widget.h
|
||||
info/info_content_widget.cpp
|
||||
info/info_content_widget.h
|
||||
info/info_controller.cpp
|
||||
info/info_controller.h
|
||||
info/info_layer_widget.cpp
|
||||
info/info_layer_widget.h
|
||||
info/info_memento.cpp
|
||||
info/info_memento.h
|
||||
info/info_section_widget.cpp
|
||||
info/info_section_widget.h
|
||||
info/info_top_bar.cpp
|
||||
info/info_top_bar.h
|
||||
info/info_wrap_widget.cpp
|
||||
info/info_wrap_widget.h
|
||||
info/boosts/info_boosts_inner_widget.cpp
|
||||
info/boosts/info_boosts_inner_widget.h
|
||||
info/boosts/info_boosts_widget.cpp
|
||||
|
@ -916,6 +902,20 @@ PRIVATE
|
|||
info/userpic/info_userpic_emoji_builder_preview.h
|
||||
info/userpic/info_userpic_emoji_builder_widget.cpp
|
||||
info/userpic/info_userpic_emoji_builder_widget.h
|
||||
info/info_content_widget.cpp
|
||||
info/info_content_widget.h
|
||||
info/info_controller.cpp
|
||||
info/info_controller.h
|
||||
info/info_layer_widget.cpp
|
||||
info/info_layer_widget.h
|
||||
info/info_memento.cpp
|
||||
info/info_memento.h
|
||||
info/info_section_widget.cpp
|
||||
info/info_section_widget.h
|
||||
info/info_top_bar.cpp
|
||||
info/info_top_bar.h
|
||||
info/info_wrap_widget.cpp
|
||||
info/info_wrap_widget.h
|
||||
inline_bots/bot_attach_web_view.cpp
|
||||
inline_bots/bot_attach_web_view.h
|
||||
inline_bots/inline_bot_layout_internal.cpp
|
||||
|
|
|
@ -1640,6 +1640,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_action_story_mention_button" = "View Story";
|
||||
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
|
||||
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
|
||||
"lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers.";
|
||||
|
||||
"lng_premium_gift_duration_months#one" = "for {count} month";
|
||||
"lng_premium_gift_duration_months#other" = "for {count} months";
|
||||
|
@ -2034,6 +2035,88 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_boost_now_instead" = "You currently boost {channel}. Do you want to boost {other} instead?";
|
||||
"lng_boost_now_replace" = "Replace";
|
||||
|
||||
"lng_giveaway_new_title" = "Boosts via Gifts";
|
||||
"lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
|
||||
"lng_giveaway_create_option" = "Create Giveaway";
|
||||
"lng_giveaway_create_subtitle" = "winners are chosen randomly";
|
||||
"lng_giveaway_award_option" = "Award Specific Users";
|
||||
"lng_giveaway_award_subtitle" = "Select recipients >";
|
||||
"lng_giveaway_award_chosen#one" = "{count} recipient >";
|
||||
"lng_giveaway_award_chosen#other" = "{count} recipients >";
|
||||
"lng_giveaway_quantity_title" = "Quantity of prizes / boosts";
|
||||
"lng_giveaway_quantity#one" = "{count} Subscription / Boost";
|
||||
"lng_giveaway_quantity#other" = "{count} Subscriptions / Boosts";
|
||||
"lng_giveaway_quantity_about" = "Choose how many Premium subscriptions to give away and boosts to receive.";
|
||||
"lng_giveaway_channels_title" = "Channels included in the giveaway";
|
||||
"lng_giveaway_channels_this#one" = "this channel will receive {count} boost";
|
||||
"lng_giveaway_channels_this#other" = "this channel will receive {count} boosts";
|
||||
"lng_giveaway_channels_add" = "Add Channel";
|
||||
"lng_giveaway_channels_about" = "Choose the channels the users need to join to take part in the giveaway.";
|
||||
"lng_giveaway_users_title" = "Users eligible for the giveaway";
|
||||
"lng_giveaway_users_all" = "All subscribers";
|
||||
"lng_giveaway_users_new" = "Only new subscribers";
|
||||
"lng_giveaway_users_about" = "Choose if you want to limit the giveaway only to the newly joined subscribers.";
|
||||
"lng_giveaway_start" = "Start Giveaway";
|
||||
"lng_giveaway_award" = "Gift Premium";
|
||||
"lng_giveaway_date_title" = "Date when giveaway ends";
|
||||
"lng_giveaway_date" = "Date and Time";
|
||||
"lng_giveaway_date_about#one" = "Choose when {count} subscriber of your channel will be randomly selected to receive Telegram Premium.";
|
||||
"lng_giveaway_date_about#other" = "Choose when {count} subscribers of your channel will be randomly selected to receive Telegram Premium.";
|
||||
"lng_giveaway_duration_title#one" = "Duration of Premium subscription";
|
||||
"lng_giveaway_duration_title#other" = "Duration of Premium subscriptions";
|
||||
"lng_giveaway_duration_price" = "{price} x {amount}";
|
||||
"lng_giveaway_duration_about" = "You can review the list of features and terms of use for Telegram Premium {link}.";
|
||||
"lng_giveaway_duration_about_link" = "here";
|
||||
"lng_giveaway_date_select" = "Select Date and Time";
|
||||
"lng_giveaway_date_confirm" = "Confirm";
|
||||
"lng_giveaway_channels_select#one" = "Select up to {count} channel";
|
||||
"lng_giveaway_channels_select#other" = "Select up to {count} channels";
|
||||
"lng_giveaway_recipients_save" = "Save Recipients";
|
||||
"lng_giveaway_recipients_deselect" = "Deselect All";
|
||||
|
||||
"lng_prize_title" = "Congratulations!";
|
||||
"lng_prize_about" = "You won a prize in a giveaway organized by {channel}.";
|
||||
"lng_prize_duration" = "Your prize is **Telegram Premium** subscription for {duration}.";
|
||||
"lng_prize_open" = "Open Gift Link";
|
||||
|
||||
"lng_prizes_title#one" = "Giveaway Prize";
|
||||
"lng_prizes_title#other" = "Giveaway Prizes";
|
||||
"lng_prizes_about#one" = "{count} Telegram Premium Subscription for {duration}.";
|
||||
"lng_prizes_about#other" = "{count} Telegram Premium Subscriptions for {duration}.";
|
||||
"lng_prizes_participants" = "Participants";
|
||||
"lng_prizes_participants_all#one" = "All subscribers of the channel:";
|
||||
"lng_prizes_participants_all#other" = "All subscribers of the channels:";
|
||||
"lng_prizes_participants_new#one" = "All users who joined the channel below after this date:";
|
||||
"lng_prizes_participants_new#other" = "All users who joined the channels below after this date:";
|
||||
"lng_prizes_date" = "Winners Selection Date";
|
||||
"lng_prizes_how_works" = "How does it work?";
|
||||
"lng_prizes_how_text#one" = "This giveaway is sponsored by the admins of {channel}, who aquired **{count} Telegram Premium** subscription for {duration} for its followers.";
|
||||
"lng_prizes_how_text#other" = "This giveaway is sponsored by the admins of {channel}, who aquired **{count} Telegram Premium** subscriptions for {duration} for its followers.";
|
||||
"lng_prizes_how_when_all_of_one#one" = "On {date}, Telegram will automatically select {count} random subscribers of {channel}.";
|
||||
"lng_prizes_how_when_all_of_one#other" = "On {date}, Telegram will automatically select {count} random subscribers of {channel}.";
|
||||
"lng_prizes_how_when_all_of_many#one" = "On {date}, Telegram will automatically select {count} random subscribers of {channel} or other listed channels.";
|
||||
"lng_prizes_how_when_all_of_many#other" = "On {date}, Telegram will automatically select {count} random subscribers of {channel} or other listed channels.";
|
||||
"lng_prizes_how_when_new_of_one#one" = "On {date}, Telegram will automatically select {count} random user that joined {channel} after {start_date}";
|
||||
"lng_prizes_how_when_new_of_one#other" = "On {date}, Telegram will automatically select {count} random users that joined {channel} after {start_date}";
|
||||
"lng_prizes_how_when_new_of_many#one" = "On {date}, Telegram will automatically select {count} random user that joined {channel} or other listed channels after {start_date}";
|
||||
"lng_prizes_how_when_new_of_many#other" = "On {date}, Telegram will automatically select {count} random users that joined {channel} or other listed channels after {start_date}";
|
||||
|
||||
"lng_gift_link_title" = "Gift Link";
|
||||
"lng_gift_link_about" = "This link allows you to activate\na **Telegram Premium** subscription.";
|
||||
"lng_gift_link_label_from" = "From";
|
||||
"lng_gift_link_label_to" = "To";
|
||||
"lng_gift_link_label_gift" = "Gift";
|
||||
"lng_gift_link_gift_premium" = "Telegram Premium for {duration}";
|
||||
"lng_gift_link_label_reason" = "Reason";
|
||||
"lng_gift_link_reason_giveaway" = "Giveaway";
|
||||
"lng_gift_link_label_date" = "Date";
|
||||
"lng_gift_link_also_send" = "You can also {link} to a friend as a gift.";
|
||||
"lng_gift_link_also_send_link" = "send this link";
|
||||
"lng_gift_link_use" = "Use Link";
|
||||
"lng_gift_link_used_title" = "Used Gift Link";
|
||||
"lng_gift_link_used_about" = "This link was used to activate\na **Telegram Premium** subscription.";
|
||||
"lng_gift_link_used_footer" = "This link was used on {date}.";
|
||||
|
||||
"lng_accounts_limit_title" = "Limit Reached";
|
||||
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected accounts.";
|
||||
"lng_accounts_limit1#other" = "You have reached the limit of **{count}** connected accounts.";
|
||||
|
|
|
@ -17,6 +17,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] GiftCode Parse(const MTPDpayments_checkedGiftCode &data) {
|
||||
return {
|
||||
.from = peerFromMTP(data.vfrom_id()),
|
||||
.to = data.vto_id() ? peerFromUser(*data.vto_id()) : PeerId(),
|
||||
.date = data.vdate().v,
|
||||
.used = false,// data.vused_date().value_or_empty(),
|
||||
.months = data.vmonths().v,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Premium::Premium(not_null<ApiWrap*> api)
|
||||
: _session(&api->session())
|
||||
|
@ -183,6 +196,52 @@ void Premium::reloadCloudSet() {
|
|||
}).send();
|
||||
}
|
||||
|
||||
void Premium::checkGiftCode(
|
||||
const QString &slug,
|
||||
Fn<void(GiftCode)> done) {
|
||||
if (_giftCodeRequestId) {
|
||||
if (_giftCodeSlug == slug) {
|
||||
return;
|
||||
}
|
||||
_api.request(_giftCodeRequestId).cancel();
|
||||
}
|
||||
_giftCodeSlug = slug;
|
||||
_giftCodeRequestId = _api.request(MTPpayments_CheckGiftCode(
|
||||
MTP_string(slug)
|
||||
)).done([=](const MTPpayments_CheckedGiftCode &result) {
|
||||
_giftCodeRequestId = 0;
|
||||
|
||||
const auto &data = result.data();
|
||||
_session->data().processUsers(data.vusers());
|
||||
_session->data().processChats(data.vchats());
|
||||
done(updateGiftCode(slug, Parse(data)));
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_giftCodeRequestId = 0;
|
||||
|
||||
done(updateGiftCode(slug, {}));
|
||||
}).send();
|
||||
}
|
||||
|
||||
GiftCode Premium::updateGiftCode(
|
||||
const QString &slug,
|
||||
const GiftCode &code) {
|
||||
auto &now = _giftCodes[slug];
|
||||
if (now != code) {
|
||||
now = code;
|
||||
_giftCodeUpdated.fire_copy(slug);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
rpl::producer<GiftCode> Premium::giftCodeValue(const QString &slug) const {
|
||||
return _giftCodeUpdated.events_starting_with_copy(
|
||||
slug
|
||||
) | rpl::filter(rpl::mappers::_1 == slug) | rpl::map([=] {
|
||||
const auto i = _giftCodes.find(slug);
|
||||
return (i != end(_giftCodes)) ? i->second : GiftCode();
|
||||
});
|
||||
}
|
||||
|
||||
const Data::SubscriptionOptions &Premium::subscriptionOptions() const {
|
||||
return _subscriptionOptions;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,22 @@ class Session;
|
|||
|
||||
namespace Api {
|
||||
|
||||
struct GiftCode {
|
||||
PeerId from = 0;
|
||||
PeerId to = 0;
|
||||
TimeId date = 0;
|
||||
TimeId used = 0; // 0 if not used.
|
||||
int months = 0;
|
||||
|
||||
explicit operator bool() const {
|
||||
return months != 0;
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const GiftCode&,
|
||||
const GiftCode&) = default;
|
||||
};
|
||||
|
||||
class Premium final {
|
||||
public:
|
||||
explicit Premium(not_null<ApiWrap*> api);
|
||||
|
@ -40,6 +56,13 @@ public:
|
|||
[[nodiscard]] int64 monthlyAmount() const;
|
||||
[[nodiscard]] QString monthlyCurrency() const;
|
||||
|
||||
void checkGiftCode(
|
||||
const QString &slug,
|
||||
Fn<void(GiftCode)> done);
|
||||
GiftCode updateGiftCode(const QString &slug, const GiftCode &code);
|
||||
[[nodiscard]] rpl::producer<GiftCode> giftCodeValue(
|
||||
const QString &slug) const;
|
||||
|
||||
[[nodiscard]] auto subscriptionOptions() const
|
||||
-> const Data::SubscriptionOptions &;
|
||||
|
||||
|
@ -71,6 +94,11 @@ private:
|
|||
int64 _monthlyAmount = 0;
|
||||
QString _monthlyCurrency;
|
||||
|
||||
mtpRequestId _giftCodeRequestId = 0;
|
||||
QString _giftCodeSlug;
|
||||
base::flat_map<QString, GiftCode> _giftCodes;
|
||||
rpl::event_stream<QString> _giftCodeUpdated;
|
||||
|
||||
Data::SubscriptionOptions _subscriptionOptions;
|
||||
|
||||
};
|
||||
|
|
|
@ -8,8 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/gift_premium_box.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_premium.h"
|
||||
#include "api/api_premium_option.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "boxes/peers/prepare_short_info_box.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_peer_values.h" // Data::PeerPremiumValue.
|
||||
#include "data/data_session.h"
|
||||
|
@ -22,12 +25,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/controls/userpic_button.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/effects/premium_stars_colored.h"
|
||||
#include "ui/effects/premium_top_bar.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/gradient_round_button.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/table_layout.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
@ -35,6 +40,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "styles/style_info.h"
|
||||
#include "styles/style_premium.h"
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kDiscountDivider = 5.;
|
||||
|
@ -225,6 +232,175 @@ void GiftBox(
|
|||
}, box->lifetime());
|
||||
}
|
||||
|
||||
struct GiftCodeLink {
|
||||
QString text;
|
||||
QString link;
|
||||
};
|
||||
[[nodiscard]] GiftCodeLink MakeGiftCodeLink(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &slug) {
|
||||
const auto path = u"giftcode/"_q + slug;
|
||||
return {
|
||||
session->createInternalLink(path),
|
||||
session->createInternalLinkFull(path),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> MakeLinkLabel(
|
||||
not_null<QWidget*> parent,
|
||||
rpl::producer<QString> text,
|
||||
rpl::producer<QString> link,
|
||||
std::shared_ptr<Ui::Show> show) {
|
||||
auto result = object_ptr<Ui::AbstractButton>(parent);
|
||||
const auto raw = result.data();
|
||||
|
||||
struct State {
|
||||
State(
|
||||
not_null<QWidget*> parent,
|
||||
rpl::producer<QString> value,
|
||||
rpl::producer<QString> link)
|
||||
: text(std::move(value))
|
||||
, link(std::move(link))
|
||||
, label(parent, text.value(), st::giveawayGiftCodeLink)
|
||||
, bg(st::roundRadiusLarge, st::windowBgOver) {
|
||||
}
|
||||
|
||||
rpl::variable<QString> text;
|
||||
rpl::variable<QString> link;
|
||||
Ui::FlatLabel label;
|
||||
Ui::RoundRect bg;
|
||||
};
|
||||
|
||||
const auto state = raw->lifetime().make_state<State>(
|
||||
raw,
|
||||
rpl::duplicate(text),
|
||||
std::move(link));
|
||||
state->label.setSelectable(true);
|
||||
|
||||
rpl::combine(
|
||||
raw->widthValue(),
|
||||
std::move(text)
|
||||
) | rpl::start_with_next([=](int outer, const auto&) {
|
||||
const auto textWidth = state->label.textMaxWidth();
|
||||
const auto skipLeft = st::giveawayGiftCodeLink.margin.left();
|
||||
const auto skipRight = st::giveawayGiftCodeLinkCopyWidth;
|
||||
const auto available = outer - skipRight - skipLeft;
|
||||
const auto use = std::min(textWidth, available);
|
||||
state->label.resizeToWidth(use);
|
||||
const auto left = (outer >= 2 * skipRight + textWidth)
|
||||
? ((outer - textWidth) / 2)
|
||||
: (outer - skipRight - use - skipLeft);
|
||||
state->label.move(left, 0);
|
||||
}, raw->lifetime());
|
||||
|
||||
raw->paintRequest() | rpl::start_with_next([=] {
|
||||
auto p = QPainter(raw);
|
||||
state->bg.paint(p, raw->rect());
|
||||
const auto outer = raw->width();
|
||||
const auto width = st::giveawayGiftCodeLinkCopyWidth;
|
||||
const auto &icon = st::giveawayGiftCodeLinkCopy;
|
||||
const auto left = outer - width + (width - icon.width()) / 2;
|
||||
const auto top = (raw->height() - icon.height()) / 2;
|
||||
icon.paint(p, left, top, raw->width());
|
||||
}, raw->lifetime());
|
||||
|
||||
state->label.setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
raw->resize(raw->width(), st::giveawayGiftCodeLinkHeight);
|
||||
raw->setClickedCallback([=] {
|
||||
QGuiApplication::clipboard()->setText(state->link.current());
|
||||
show->showToast(tr::lng_username_copied(tr::now));
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> DurationValue(int months) {
|
||||
return (months < 12)
|
||||
? tr::lng_months(lt_count, rpl::single(float64(months)))
|
||||
: tr::lng_years(lt_count, rpl::single(float64(months / 12)));
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> MakePeerTableValue(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
PeerId id) {
|
||||
auto result = object_ptr<Ui::AbstractButton>(parent);
|
||||
const auto raw = result.data();
|
||||
|
||||
const auto &st = st::giveawayGiftCodeUserpic;
|
||||
raw->resize(raw->width(), st.photoSize);
|
||||
|
||||
const auto peer = controller->session().data().peer(id);
|
||||
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(raw, peer, st);
|
||||
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
||||
raw,
|
||||
peer->name(),
|
||||
st::giveawayGiftCodeValue);
|
||||
raw->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
const auto position = st::giveawayGiftCodeNamePosition;
|
||||
label->resizeToNaturalWidth(width - position.x());
|
||||
label->moveToLeft(position.x(), position.y(), width);
|
||||
const auto top = (raw->height() - userpic->height()) / 2;
|
||||
userpic->moveToLeft(0, top, width);
|
||||
}, label->lifetime());
|
||||
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
label->setTextColorOverride(st::windowActiveTextFg->c);
|
||||
|
||||
raw->setClickedCallback([=] {
|
||||
controller->show(PrepareShortInfoBox(peer, controller));
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void AddTableRow(
|
||||
not_null<Ui::TableLayout*> table,
|
||||
rpl::producer<QString> label,
|
||||
object_ptr<Ui::RpWidget> value,
|
||||
style::margins valueMargins) {
|
||||
table->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
table,
|
||||
std::move(label),
|
||||
st::giveawayGiftCodeLabel),
|
||||
std::move(value),
|
||||
st::giveawayGiftCodeLabelMargin,
|
||||
valueMargins);
|
||||
}
|
||||
|
||||
void AddTableRow(
|
||||
not_null<Ui::TableLayout*> table,
|
||||
rpl::producer<QString> label,
|
||||
rpl::producer<QString> value) {
|
||||
AddTableRow(
|
||||
table,
|
||||
std::move(label),
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
table,
|
||||
std::move(value),
|
||||
st::giveawayGiftCodeValue),
|
||||
st::giveawayGiftCodeValueMargin);
|
||||
}
|
||||
|
||||
void AddTableRow(
|
||||
not_null<Ui::TableLayout*> table,
|
||||
rpl::producer<QString> label,
|
||||
not_null<Window::SessionController*> controller,
|
||||
PeerId id) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
AddTableRow(
|
||||
table,
|
||||
std::move(label),
|
||||
MakePeerTableValue(table, controller, id),
|
||||
st::giveawayGiftCodePeerMargin);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
GiftPremiumValidator::GiftPremiumValidator(
|
||||
|
@ -263,3 +439,148 @@ void GiftPremiumValidator::showBox(not_null<UserData*> user) {
|
|||
_requestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
void GiftCodeBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug) {
|
||||
struct State {
|
||||
rpl::variable<Api::GiftCode> data;
|
||||
rpl::variable<bool> used;
|
||||
};
|
||||
const auto session = &controller->session();
|
||||
const auto state = box->lifetime().make_state<State>(State{});
|
||||
state->data = session->api().premium().giftCodeValue(slug);
|
||||
state->used = state->data.value(
|
||||
) | rpl::map([=](const Api::GiftCode &data) {
|
||||
return data.used;
|
||||
});
|
||||
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->setStyle(st::giveawayGiftCodeBox);
|
||||
box->setNoContentMargin(true);
|
||||
|
||||
const auto bar = box->setPinnedToTopContent(
|
||||
object_ptr<Ui::Premium::TopBar>(
|
||||
box,
|
||||
st::giveawayGiftCodeCover,
|
||||
nullptr,
|
||||
rpl::conditional(
|
||||
state->used.value(),
|
||||
tr::lng_gift_link_used_title(),
|
||||
tr::lng_gift_link_title()),
|
||||
rpl::conditional(
|
||||
state->used.value(),
|
||||
tr::lng_gift_link_used_about(Ui::Text::RichLangValue),
|
||||
tr::lng_gift_link_about(Ui::Text::RichLangValue)),
|
||||
true));
|
||||
|
||||
const auto max = st::giveawayGiftCodeTopHeight;
|
||||
bar->setMaximumHeight(max);
|
||||
bar->setMinimumHeight(st::infoLayerTopBarHeight);
|
||||
|
||||
bar->resize(bar->width(), bar->maximumHeight());
|
||||
|
||||
const auto link = MakeGiftCodeLink(&controller->session(), slug);
|
||||
box->addRow(
|
||||
MakeLinkLabel(
|
||||
box,
|
||||
rpl::single(link.text),
|
||||
rpl::single(link.link),
|
||||
box->uiShow()),
|
||||
st::giveawayGiftCodeLinkMargin);
|
||||
|
||||
auto table = box->addRow(
|
||||
object_ptr<Ui::TableLayout>(
|
||||
box,
|
||||
st::giveawayGiftCodeTable),
|
||||
st::giveawayGiftCodeTableMargin);
|
||||
const auto current = state->data.current();
|
||||
AddTableRow(
|
||||
table,
|
||||
tr::lng_gift_link_label_from(),
|
||||
controller,
|
||||
current.from);
|
||||
AddTableRow(
|
||||
table,
|
||||
tr::lng_gift_link_label_to(),
|
||||
controller,
|
||||
current.to);
|
||||
AddTableRow(
|
||||
table,
|
||||
tr::lng_gift_link_label_gift(),
|
||||
tr::lng_gift_link_gift_premium(
|
||||
lt_duration,
|
||||
DurationValue(current.months)));
|
||||
AddTableRow(
|
||||
table,
|
||||
tr::lng_gift_link_label_reason(),
|
||||
tr::lng_gift_link_reason_giveaway());
|
||||
AddTableRow(
|
||||
table,
|
||||
tr::lng_gift_link_label_date(),
|
||||
rpl::single(langDateTime(base::unixtime::parse(current.date))));
|
||||
|
||||
auto shareLink = tr::lng_gift_link_also_send_link(
|
||||
) | rpl::map([](const QString &text) {
|
||||
return Ui::Text::Link(text);
|
||||
});
|
||||
auto richDate = [](const Api::GiftCode &data) {
|
||||
return TextWithEntities{
|
||||
langDateTime(base::unixtime::parse(data.used)),
|
||||
};
|
||||
};
|
||||
const auto footer = box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
rpl::conditional(
|
||||
state->used.value(),
|
||||
tr::lng_gift_link_used_footer(
|
||||
lt_date,
|
||||
state->data.value() | rpl::map(richDate),
|
||||
Ui::Text::WithEntities),
|
||||
tr::lng_gift_link_also_send(
|
||||
lt_link,
|
||||
std::move(shareLink),
|
||||
Ui::Text::WithEntities)),
|
||||
st::giveawayGiftCodeFooter),
|
||||
st::giveawayGiftCodeFooterMargin);
|
||||
footer->setClickHandlerFilter([=](const auto &...) {
|
||||
box->uiShow()->showToast(u"Sharing..."_q);
|
||||
return false;
|
||||
});
|
||||
|
||||
const auto close = Ui::CreateChild<Ui::IconButton>(
|
||||
box.get(),
|
||||
st::boxTitleClose);
|
||||
close->setClickedCallback([=] {
|
||||
box->closeBox();
|
||||
});
|
||||
box->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
close->moveToRight(0, 0);
|
||||
}, box->lifetime());
|
||||
|
||||
const auto button = box->addButton(rpl::conditional(
|
||||
state->used.value(),
|
||||
tr::lng_box_ok(),
|
||||
tr::lng_gift_link_use()
|
||||
), [=] {
|
||||
if (state->used.current()) {
|
||||
box->closeBox();
|
||||
} else {
|
||||
auto copy = state->data.current();
|
||||
copy.used = base::unixtime::now();
|
||||
state->data = std::move(copy);
|
||||
}
|
||||
});
|
||||
const auto buttonPadding = st::giveawayGiftCodeBox.buttonPadding;
|
||||
const auto buttonWidth = st::boxWideWidth
|
||||
- buttonPadding.left()
|
||||
- buttonPadding.right();
|
||||
button->widthValue() | rpl::filter([=] {
|
||||
return (button->widthNoMargins() != buttonWidth);
|
||||
}) | rpl::start_with_next([=] {
|
||||
button->resizeToWidth(buttonWidth);
|
||||
}, button->lifetime());
|
||||
}
|
||||
|
|
|
@ -11,6 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class UserData;
|
||||
|
||||
namespace Api {
|
||||
struct GiftCode;
|
||||
} // namespace Api
|
||||
|
||||
namespace Ui {
|
||||
class GenericBox;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
@ -29,3 +37,8 @@ private:
|
|||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
||||
void GiftCodeBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug);
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_text_entities.h"
|
||||
#include "api/api_chat_filters.h"
|
||||
#include "api/api_chat_invite.h"
|
||||
#include "api/api_premium.h"
|
||||
#include "base/qthelp_regex.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
|
@ -23,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/boxes/confirm_box.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "boxes/connection_box.h"
|
||||
#include "boxes/gift_premium_box.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/sessions_box.h"
|
||||
#include "boxes/language_box.h"
|
||||
|
@ -348,6 +350,21 @@ bool ResolveUsernameOrPhone(
|
|||
const auto domainParam = params.value(u"domain"_q);
|
||||
const auto appnameParam = params.value(u"appname"_q);
|
||||
|
||||
if (domainParam == u"giftcode"_q && !appnameParam.isEmpty()) {
|
||||
const auto done = [=](Api::GiftCode code) {
|
||||
if (!code) {
|
||||
controller->showToast(u"Gift code link expired"_q);
|
||||
} else {
|
||||
controller->show(
|
||||
Box(GiftCodeBox, controller, appnameParam));
|
||||
}
|
||||
};
|
||||
controller->session().api().premium().checkGiftCode(
|
||||
appnameParam,
|
||||
crl::guard(controller, done));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fix t.me/s/username links.
|
||||
const auto webChannelPreviewLink = (domainParam == u"s"_q)
|
||||
&& !appnameParam.isEmpty();
|
||||
|
@ -1078,7 +1095,7 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
"("
|
||||
"/?\\?|"
|
||||
"/?$|"
|
||||
"/[a-zA-Z0-9\\.\\_]+/?(\\?|$)|"
|
||||
"/[a-zA-Z0-9\\.\\_\\-]+/?(\\?|$)|"
|
||||
"/\\d+/?(\\?|$)|"
|
||||
"/s/\\d+/?(\\?|$)|"
|
||||
"/\\d+/\\d+/?(\\?|$)"
|
||||
|
@ -1103,7 +1120,7 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
added = u"&post="_q + postMatch->captured(1);
|
||||
} else if (const auto storyMatch = regex_match(u"^/s/(\\d+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) {
|
||||
added = u"&story="_q + storyMatch->captured(1);
|
||||
} else if (const auto appNameMatch = regex_match(u"^/([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) {
|
||||
} else if (const auto appNameMatch = regex_match(u"^/([a-zA-Z0-9\\.\\_\\-]+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) {
|
||||
added = u"&appname="_q + appNameMatch->captured(1);
|
||||
}
|
||||
return base + added + (params.isEmpty() ? QString() : '&' + params);
|
||||
|
|
|
@ -60,8 +60,8 @@ const style::InfoTopBar &TopBarStyle(Wrap wrap) {
|
|||
|
||||
[[nodiscard]] bool HasCustomTopBar(not_null<const Controller*> controller) {
|
||||
const auto section = controller->section();
|
||||
return (section.type() == Section::Type::Settings
|
||||
&& (section.settingsType() == ::Settings::PremiumId()));
|
||||
return (section.type() == Section::Type::Settings)
|
||||
&& section.settingsType()->hasCustomTopBar();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -788,8 +788,8 @@ void WrapWidget::showNewContent(
|
|||
newController->takeStepData(_controller.get());
|
||||
}
|
||||
auto newContent = object_ptr<ContentWidget>(nullptr);
|
||||
const auto enableBackButton = hasBackButton();
|
||||
const auto createInAdvance = needAnimation || enableBackButton;
|
||||
const auto withBackButton = willHaveBackButton(params);
|
||||
const auto createInAdvance = needAnimation || withBackButton;
|
||||
if (createInAdvance) {
|
||||
newContent = createContent(memento, newController.get());
|
||||
}
|
||||
|
@ -823,7 +823,7 @@ void WrapWidget::showNewContent(
|
|||
_historyStack.clear();
|
||||
}
|
||||
|
||||
if (enableBackButton) {
|
||||
if (withBackButton) {
|
||||
newContent->enableBackButton();
|
||||
}
|
||||
|
||||
|
@ -969,6 +969,17 @@ bool WrapWidget::hasBackButton() const {
|
|||
return (wrap() == Wrap::Narrow || hasStackHistory());
|
||||
}
|
||||
|
||||
bool WrapWidget::willHaveBackButton(
|
||||
const Window::SectionShow ¶ms) const {
|
||||
using Way = Window::SectionShow::Way;
|
||||
const auto willSaveToStack = (_content != nullptr)
|
||||
&& (params.way == Way::Forward);
|
||||
const auto willClearStack = (params.way == Way::ClearStack);
|
||||
const auto willHaveStack = !willClearStack
|
||||
&& (hasStackHistory() || willSaveToStack);
|
||||
return (wrap() == Wrap::Narrow) || willHaveStack;
|
||||
}
|
||||
|
||||
WrapWidget::~WrapWidget() = default;
|
||||
|
||||
} // namespace Info
|
||||
|
|
|
@ -176,6 +176,8 @@ private:
|
|||
void setupShortcuts();
|
||||
|
||||
[[nodiscard]] bool hasBackButton() const;
|
||||
[[nodiscard]] bool willHaveBackButton(
|
||||
const Window::SectionShow ¶ms) const;
|
||||
|
||||
not_null<RpWidget*> topWidget() const;
|
||||
|
||||
|
|
|
@ -424,8 +424,6 @@ notifyPreviewBottomSkip: 9px;
|
|||
settingsPremiumButtonPadding: margins(11px, 11px, 11px, 3px);
|
||||
settingsPremiumTopBarBackIcon: icon {{ "info/info_back", premiumButtonFg }};
|
||||
settingsPremiumTopBarBackIconOver: icon {{ "info/info_back", premiumButtonFg }};
|
||||
settingsPremiumStarSize: size(84px, 81px);
|
||||
settingsPremiumStarTopSkip: 37px;
|
||||
settingsPremiumTopBarBack: IconButton(infoTopBarBack) {
|
||||
icon: settingsPremiumTopBarBackIcon;
|
||||
iconOver: settingsPremiumTopBarBackIconOver;
|
||||
|
@ -467,21 +465,6 @@ settingsPremiumPreviewIconTitlePadding: margins(62px, 13px, 24px, 1px);
|
|||
settingsPremiumPreviewIconAboutPadding: margins(62px, 0px, 24px, 0px);
|
||||
settingsPremiumPreviewIconPosition: point(20px, 7px);
|
||||
|
||||
settingsPremiumTitlePadding: margins(0px, 18px, 0px, 11px);
|
||||
settingsPremiumAboutTextStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(12px);
|
||||
linkUnderline: kLinkUnderlineAlways;
|
||||
lineHeight: 18px;
|
||||
}
|
||||
settingsPremiumAbout: FlatLabel(defaultFlatLabel) {
|
||||
style: settingsPremiumAboutTextStyle;
|
||||
palette: TextPalette(defaultTextPalette) {
|
||||
linkFg: premiumButtonFg;
|
||||
}
|
||||
align: align(top);
|
||||
textFg: premiumButtonFg;
|
||||
minWidth: 190px;
|
||||
}
|
||||
settingsPremiumArrowShift: point(-5px, -1px);
|
||||
settingsPremiumArrow: icon{{ "settings/premium/arrow", menuIconFg }};
|
||||
settingsPremiumArrowOver: icon{{ "settings/premium/arrow", menuIconFgOver }};
|
||||
|
@ -499,12 +482,6 @@ settingsPremiumUserTitle: FlatLabel(boxTitle) {
|
|||
maxHeight: 0px;
|
||||
align: align(top);
|
||||
}
|
||||
settingsPremiumUserAbout: FlatLabel(boxDividerLabel) {
|
||||
style: settingsPremiumAboutTextStyle;
|
||||
minWidth: 315px;
|
||||
maxHeight: 0px;
|
||||
align: align(top);
|
||||
}
|
||||
|
||||
settingsPremiumLock: icon{{ "emoji/premium_lock", windowActiveTextFg, point(0px, 1px) }};
|
||||
settingsPremiumLockSkip: 3px;
|
||||
|
|
|
@ -56,6 +56,9 @@ struct AbstractSectionFactory {
|
|||
[[nodiscard]] virtual object_ptr<AbstractSection> create(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Window::SessionController*> controller) const = 0;
|
||||
[[nodiscard]] virtual bool hasCustomTopBar() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ~AbstractSectionFactory() = default;
|
||||
};
|
||||
|
|
|
@ -518,10 +518,10 @@ TopBarUser::TopBarUser(
|
|||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
rpl::producer<> showFinished)
|
||||
: TopBarAbstract(parent)
|
||||
: TopBarAbstract(parent, st::userPremiumCover)
|
||||
, _content(this)
|
||||
, _title(_content, st::settingsPremiumUserTitle)
|
||||
, _about(_content, st::settingsPremiumUserAbout)
|
||||
, _about(_content, st::userPremiumCover.about)
|
||||
, _ministars(_content)
|
||||
, _smallTop({
|
||||
.widget = object_ptr<Ui::RpWidget>(this),
|
||||
|
@ -1173,6 +1173,7 @@ QPointer<Ui::RpWidget> Premium::createPinnedToTop(
|
|||
};
|
||||
return Ui::CreateChild<Ui::Premium::TopBar>(
|
||||
parent.get(),
|
||||
st::defaultPremiumCover,
|
||||
clickContextOther,
|
||||
std::move(title),
|
||||
std::move(about));
|
||||
|
@ -1371,6 +1372,24 @@ QPointer<Ui::RpWidget> Premium::createPinnedToBottom(
|
|||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
struct SectionFactory<Premium> : AbstractSectionFactory {
|
||||
object_ptr<AbstractSection> create(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Window::SessionController*> controller
|
||||
) const final override {
|
||||
return object_ptr<Premium>(parent, controller);
|
||||
}
|
||||
bool hasCustomTopBar() const final override {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] static const std::shared_ptr<SectionFactory> &Instance() {
|
||||
static const auto result = std::make_shared<SectionFactory>();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
Type PremiumId() {
|
||||
return Premium::Id();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,43 @@ PremiumBubble {
|
|||
tailSize: size;
|
||||
font: font;
|
||||
}
|
||||
PremiumCover {
|
||||
starSize: size;
|
||||
starTopSkip: pixels;
|
||||
titlePadding: margins;
|
||||
titleFont: font;
|
||||
about: FlatLabel;
|
||||
}
|
||||
|
||||
premiumAboutTextStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(12px);
|
||||
linkUnderline: kLinkUnderlineAlways;
|
||||
lineHeight: 18px;
|
||||
}
|
||||
defaultPremiumCover: PremiumCover {
|
||||
starSize: size(84px, 81px);
|
||||
starTopSkip: 37px;
|
||||
titlePadding: margins(0px, 18px, 0px, 11px);
|
||||
titleFont: boxTitleFont;
|
||||
about: FlatLabel(defaultFlatLabel) {
|
||||
style: premiumAboutTextStyle;
|
||||
palette: TextPalette(defaultTextPalette) {
|
||||
linkFg: premiumButtonFg;
|
||||
}
|
||||
align: align(top);
|
||||
textFg: premiumButtonFg;
|
||||
minWidth: 190px;
|
||||
}
|
||||
}
|
||||
userPremiumCoverAbout: FlatLabel(boxDividerLabel) {
|
||||
style: premiumAboutTextStyle;
|
||||
minWidth: 315px;
|
||||
maxHeight: 0px;
|
||||
align: align(top);
|
||||
}
|
||||
userPremiumCover: PremiumCover(defaultPremiumCover) {
|
||||
about: userPremiumCoverAbout;
|
||||
}
|
||||
|
||||
defaultPremiumBoxLabel: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 220px;
|
||||
|
@ -239,3 +276,69 @@ boostReplaceIconSkip: 3px;
|
|||
boostReplaceIconOutline: 2px;
|
||||
boostReplaceIconAdd: point(4px, 2px);
|
||||
boostReplaceArrow: icon{{ "mediaview/next", windowSubTextFg }};
|
||||
|
||||
giveawayGiftCodeTopHeight: 195px;
|
||||
giveawayGiftCodeLink: FlatLabel(defaultFlatLabel) {
|
||||
margin: margins(10px, 12px, 10px, 8px);
|
||||
textFg: menuIconColor;
|
||||
maxHeight: 24px;
|
||||
}
|
||||
giveawayGiftCodeLinkCopy: icon{{ "menu/copy", menuIconColor }};
|
||||
giveawayGiftCodeLinkHeight: 42px;
|
||||
giveawayGiftCodeLinkCopyWidth: 40px;
|
||||
giveawayGiftCodeLinkMargin: margins(24px, 8px, 24px, 12px);
|
||||
|
||||
giveawayGiftCodeTable: Table(defaultTable) {
|
||||
labelMinWidth: 91px;
|
||||
}
|
||||
giveawayGiftCodeTableMargin: margins(24px, 4px, 24px, 4px);
|
||||
giveawayGiftCodeLabel: FlatLabel(defaultFlatLabel) {
|
||||
textFg: menuIconColor;
|
||||
maxHeight: 24px;
|
||||
style: TextStyle(semiboldTextStyle) {
|
||||
font: font(12px semibold);
|
||||
}
|
||||
}
|
||||
giveawayGiftCodeLabelMargin: margins(13px, 10px, 13px, 10px);
|
||||
giveawayGiftCodeValue: FlatLabel(defaultFlatLabel) {
|
||||
maxHeight: 24px;
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: font(12px);
|
||||
linkUnderline: kLinkUnderlineNever;
|
||||
}
|
||||
}
|
||||
giveawayGiftCodeValueMargin: margins(13px, 9px, 13px, 9px);
|
||||
giveawayGiftCodePeerMargin: margins(11px, 6px, 11px, 4px);
|
||||
giveawayGiftCodeUserpic: UserpicButton(defaultUserpicButton) {
|
||||
size: size(24px, 24px);
|
||||
photoSize: 24px;
|
||||
photoPosition: point(-1px, -1px);
|
||||
}
|
||||
giveawayGiftCodeNamePosition: point(32px, 4px);
|
||||
giveawayGiftCodeCover: PremiumCover(userPremiumCover) {
|
||||
starSize: size(92px, 90px);
|
||||
starTopSkip: 20px;
|
||||
titlePadding: margins(0px, 15px, 0px, 17px);
|
||||
titleFont: font(15px semibold);
|
||||
about: FlatLabel(userPremiumCoverAbout) {
|
||||
textFg: windowBoldFg;
|
||||
style: TextStyle(premiumAboutTextStyle) {
|
||||
lineHeight: 17px;
|
||||
}
|
||||
}
|
||||
}
|
||||
giveawayGiftCodeFooter: FlatLabel(defaultFlatLabel) {
|
||||
align: align(top);
|
||||
textFg: windowBoldFg;
|
||||
}
|
||||
giveawayGiftCodeFooterMargin: margins(0px, 9px, 0px, 4px);
|
||||
giveawayGiftCodeBox: Box(defaultBox) {
|
||||
buttonPadding: margins(22px, 11px, 22px, 22px);
|
||||
buttonHeight: 42px;
|
||||
button: RoundButton(defaultActiveButton) {
|
||||
height: 42px;
|
||||
textTop: 12px;
|
||||
font: font(13px semibold);
|
||||
}
|
||||
shadowIgnoreTopSkip: true;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_premium.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
|
||||
|
@ -90,6 +91,13 @@ QImage GenerateStarForLightTopBar(QRectF rect) {
|
|||
return frame;
|
||||
}
|
||||
|
||||
TopBarAbstract::TopBarAbstract(
|
||||
QWidget *parent,
|
||||
const style::PremiumCover &st)
|
||||
: RpWidget(parent)
|
||||
, _st(st) {
|
||||
}
|
||||
|
||||
void TopBarAbstract::setRoundEdges(bool value) {
|
||||
_roundEdges = value;
|
||||
update();
|
||||
|
@ -122,11 +130,11 @@ void TopBarAbstract::paintEdges(QPainter &p) const {
|
|||
QRectF TopBarAbstract::starRect(
|
||||
float64 topProgress,
|
||||
float64 sizeProgress) const {
|
||||
const auto starSize = st::settingsPremiumStarSize * sizeProgress;
|
||||
const auto starSize = _st.starSize * sizeProgress;
|
||||
return QRectF(
|
||||
QPointF(
|
||||
(width() - starSize.width()) / 2,
|
||||
st::settingsPremiumStarTopSkip * topProgress),
|
||||
_st.starTopSkip * topProgress),
|
||||
starSize);
|
||||
};
|
||||
|
||||
|
@ -143,18 +151,16 @@ void TopBarAbstract::computeIsDark() {
|
|||
|
||||
TopBar::TopBar(
|
||||
not_null<QWidget*> parent,
|
||||
const style::PremiumCover &st,
|
||||
Fn<QVariant()> clickContextOther,
|
||||
rpl::producer<QString> title,
|
||||
rpl::producer<TextWithEntities> about,
|
||||
bool light)
|
||||
: TopBarAbstract(parent)
|
||||
: TopBarAbstract(parent, st)
|
||||
, _light(light)
|
||||
, _titleFont(st::boxTitle.style.font)
|
||||
, _titlePadding(st::settingsPremiumTitlePadding)
|
||||
, _about(
|
||||
this,
|
||||
std::move(about),
|
||||
_light ? st::settingsPremiumUserAbout : st::settingsPremiumAbout)
|
||||
, _titleFont(st.titleFont)
|
||||
, _titlePadding(st.titlePadding)
|
||||
, _about(this, std::move(about), st.about)
|
||||
, _ministars(this) {
|
||||
std::move(
|
||||
title
|
||||
|
@ -219,7 +225,7 @@ void TopBar::setTextPosition(int x, int y) {
|
|||
|
||||
rpl::producer<int> TopBar::additionalHeight() const {
|
||||
return _about->heightValue(
|
||||
) | rpl::map([l = st::settingsPremiumAbout.style.lineHeight](int height) {
|
||||
) | rpl::map([l = st().about.style.lineHeight](int height) {
|
||||
return std::max(height - l * 2, 0);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,6 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/rp_widget.h"
|
||||
#include "ui/effects/premium_stars_colored.h"
|
||||
|
||||
namespace style {
|
||||
struct PremiumCover;
|
||||
} // namespace style
|
||||
|
||||
namespace st {
|
||||
extern const style::PremiumCover &defaultPremiumCover;
|
||||
} // namespace st
|
||||
|
||||
namespace Ui {
|
||||
class FlatLabel;
|
||||
} // namespace Ui
|
||||
|
@ -23,7 +31,9 @@ namespace Ui::Premium {
|
|||
|
||||
class TopBarAbstract : public RpWidget {
|
||||
public:
|
||||
using RpWidget::RpWidget;
|
||||
TopBarAbstract(
|
||||
QWidget *parent = nullptr,
|
||||
const style::PremiumCover &st = st::defaultPremiumCover);
|
||||
|
||||
void setRoundEdges(bool value);
|
||||
|
||||
|
@ -32,6 +42,10 @@ public:
|
|||
|
||||
[[nodiscard]] virtual rpl::producer<int> additionalHeight() const = 0;
|
||||
|
||||
[[nodiscard]] const style::PremiumCover &st() const {
|
||||
return _st;
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEdges(QPainter &p, const QBrush &brush) const;
|
||||
void paintEdges(QPainter &p) const;
|
||||
|
@ -44,6 +58,7 @@ protected:
|
|||
void computeIsDark();
|
||||
|
||||
private:
|
||||
const style::PremiumCover &_st;
|
||||
bool _roundEdges = true;
|
||||
bool _isDark = false;
|
||||
|
||||
|
@ -53,6 +68,7 @@ class TopBar final : public TopBarAbstract {
|
|||
public:
|
||||
TopBar(
|
||||
not_null<QWidget*> parent,
|
||||
const style::PremiumCover &st,
|
||||
Fn<QVariant()> clickContextOther,
|
||||
rpl::producer<QString> title,
|
||||
rpl::producer<TextWithEntities> about,
|
||||
|
|
Loading…
Add table
Reference in a new issue