Nice starref join confirmation box.

This commit is contained in:
John Preston 2024-11-28 15:01:56 +04:00
parent 63c36f5907
commit 0e866a0266
7 changed files with 342 additions and 208 deletions

View file

@ -1647,6 +1647,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_star_ref_update" = "Update Affiliate Program";
"lng_star_ref_update_info" = "By updating an affiliate program, you agree to the {terms} of Affiliate Programs.";
"lng_star_ref_button_link" = "terms and conditions";
"lng_star_ref_tos_url" = "https://telegram.org/tos/mini-apps";
"lng_star_ref_warning_title" = "Warning";
"lng_star_ref_warning_text" = "Once you start the affiliate program, you won't be able to decrease its commission or duration. You can only increase these parameters or end the program, which will disable all previously distributed referral links.";
"lng_star_ref_warning_change" = "This change is irreversible. You won't be able to reduce commission or duration. You can only increase these parameters or end the program, which will disable all previously shared referral links.";

View file

@ -202,10 +202,11 @@ void Controller::prepare() {
const auto session = &_to->session();
auto above = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
above->add(
CreateBoostReplaceUserpics(
CreateUserpicsTransfer(
above.data(),
_selectedPeers.value(),
_to),
_to,
UserpicsTransferType::BoostReplace),
st::boxRowPadding + st::boostReplaceUserpicsPadding);
above->add(
object_ptr<Ui::FlatLabel>(
@ -366,10 +367,11 @@ object_ptr<Ui::BoxContent> ReassignBoostSingleBox(
});
box->verticalLayout()->insert(
0,
CreateBoostReplaceUserpics(
CreateUserpicsTransfer(
box,
rpl::single(std::vector{ peer }),
to),
to,
UserpicsTransferType::BoostReplace),
st::boxRowPadding + st::boostReplaceUserpicsPadding);
});
@ -536,10 +538,11 @@ object_ptr<Ui::BoxContent> ReassignBoostsBox(
return Box<PeerListBox>(std::move(controller), std::move(initBox));
}
object_ptr<Ui::RpWidget> CreateBoostReplaceUserpics(
object_ptr<Ui::RpWidget> CreateUserpicsTransfer(
not_null<Ui::RpWidget*> parent,
rpl::producer<std::vector<not_null<PeerData*>>> from,
not_null<PeerData*> to) {
not_null<PeerData*> to,
UserpicsTransferType type) {
struct State {
std::vector<not_null<PeerData*>> from;
std::vector<std::unique_ptr<Ui::UserpicButton>> buttons;
@ -640,13 +643,18 @@ object_ptr<Ui::RpWidget> CreateBoostReplaceUserpics(
button->render(&q, position, QRegion(), QWidget::DrawChildren);
}
state->painting = false;
const auto boosting = (type == UserpicsTransferType::BoostReplace);
const auto last = state->buttons.back().get();
const auto back = boosting ? last : right;
const auto add = st::boostReplaceIconAdd;
const auto skip = st::boostReplaceIconSkip;
const auto w = st::boostReplaceIcon.width() + 2 * skip;
const auto h = st::boostReplaceIcon.height() + 2 * skip;
const auto x = last->x() + last->width() - w + add.x();
const auto y = last->y() + last->height() - h + add.y();
const auto &icon = boosting
? st::boostReplaceIcon
: st::starrefJoinIcon;
const auto skip = boosting ? st::boostReplaceIconSkip : 0;
const auto w = icon.width() + 2 * skip;
const auto h = icon.height() + 2 * skip;
const auto x = back->x() + back->width() - w + add.x();
const auto y = back->y() + back->height() - h + add.y();
auto brush = QLinearGradient(QPointF(x + w, y + h), QPointF(x, y));
brush.setStops(Ui::Premium::ButtonGradientStops());
@ -654,7 +662,7 @@ object_ptr<Ui::RpWidget> CreateBoostReplaceUserpics(
pen.setWidthF(stroke);
q.setPen(pen);
q.drawEllipse(x - half, y - half, w + stroke, h + stroke);
st::boostReplaceIcon.paint(q, x + skip, y + skip, outerw);
icon.paint(q, x + skip, y + skip, outerw);
const auto size = st::boostReplaceArrow.size();
st::boostReplaceArrow.paint(

View file

@ -53,10 +53,15 @@ object_ptr<Ui::BoxContent> ReassignBoostsBox(
Fn<void(std::vector<int> slots, int groups, int channels)> reassign,
Fn<void()> cancel);
[[nodiscard]] object_ptr<Ui::RpWidget> CreateBoostReplaceUserpics(
enum class UserpicsTransferType {
BoostReplace,
StarRefJoin,
};
[[nodiscard]] object_ptr<Ui::RpWidget> CreateUserpicsTransfer(
not_null<Ui::RpWidget*> parent,
rpl::producer<std::vector<not_null<PeerData*>>> from,
not_null<PeerData*> to);
not_null<PeerData*> to,
UserpicsTransferType type);
[[nodiscard]] object_ptr<Ui::RpWidget> CreateUserpicsWithMoreBadge(
not_null<Ui::RpWidget*> parent,

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "base/timer_rpl.h"
#include "base/unixtime.h"
#include "boxes/peers/replace_boost_box.h" // CreateUserpicsTransfer.
#include "boxes/peer_list_box.h"
#include "core/click_handler_types.h"
#include "data/data_session.h"
@ -31,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h"
#include "ui/widgets/popup_menu.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/ui_utility.h"
@ -53,6 +55,19 @@ enum class JoinType {
Suggested,
};
struct ConnectedBotState {
StarRefProgram program;
QString link;
TimeId date = 0;
int users = 0;
bool revoked = false;
};
struct ConnectedBot {
not_null<UserData*> bot;
ConnectedBotState state;
};
using ConnectedBots = std::vector<ConnectedBot>;
class ListController final : public PeerListController {
public:
ListController(
@ -71,36 +86,17 @@ public:
[[nodiscard]] rpl::producer<int> rowCountValue() const;
//std::unique_ptr<PeerListRow> createRestoredRow(
// not_null<PeerData*> peer) override {
// return createRow(peer);
//}
//std::unique_ptr<PeerListState> saveState() const override;
//void restoreState(std::unique_ptr<PeerListState> state) override;
void setContentWidget(not_null<Ui::RpWidget*> widget);
[[nodiscard]] rpl::producer<int> unlockHeightValue() const;
private:
struct RowState {
StarRefProgram program;
QString link;
int users = 0;
};
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(ConnectedBot bot);
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(
not_null<PeerData*> peer,
RowState state);
void showLink(not_null<PeerData*> peer, RowState state);
struct SavedState : SavedStateBase {
};
const not_null<Controller*> _controller;
const not_null<PeerData*> _peer;
const JoinType _type = {};
base::flat_map<not_null<PeerData*>, RowState> _states;
base::flat_map<not_null<PeerData*>, ConnectedBotState> _states;
mtpRequestId _requestId = 0;
TimeId _offsetDate = 0;
@ -111,6 +107,246 @@ private:
};
[[nodiscard]] ConnectedBots Parse(
not_null<Main::Session*> session,
const MTPpayments_ConnectedStarRefBots &bots) {
const auto &data = bots.data();
session->data().processUsers(data.vusers());
const auto &list = data.vconnected_bots().v;
auto result = ConnectedBots();
for (const auto &bot : list) {
const auto &data = bot.data();
const auto botId = UserId(data.vbot_id());
const auto link = qs(data.vurl());
const auto date = data.vdate().v;
const auto commission = data.vcommission_permille().v;
const auto durationMonths
= data.vduration_months().value_or_empty();
const auto users = int(data.vparticipants().v);
const auto revoked = data.is_revoked();
result.push_back({
.bot = session->data().user(botId),
.state = {
.program = {
.commission = ushort(commission),
.durationMonths = uchar(durationMonths),
},
.link = link,
.date = date,
.users = users,
.revoked = revoked,
},
});
}
return result;
}
[[nodiscard]] rpl::producer<TextWithEntities> FormatProgramDuration(
StarRefProgram program) {
return !program.durationMonths
? tr::lng_star_ref_one_about_for_forever(Ui::Text::RichLangValue)
: (program.durationMonths < 12)
? tr::lng_star_ref_one_about_for_months(
lt_count,
rpl::single(program.durationMonths * 1.),
Ui::Text::RichLangValue)
: tr::lng_star_ref_one_about_for_years(
lt_count,
rpl::single((program.durationMonths / 12) * 1.),
Ui::Text::RichLangValue);
}
[[nodiscard]] not_null<Ui::RoundButton*> AddFullWidthButton(
not_null<Ui::BoxContent*> box,
rpl::producer<QString> text,
Fn<void()> callback = nullptr) {
const auto &boxSt = box->getDelegate()->style();
const auto result = box->addButton(std::move(text), std::move(callback));
rpl::combine(
box->widthValue(),
result->widthValue()
) | rpl::start_with_next([=](int width, int buttonWidth) {
const auto correct = width
- boxSt.buttonPadding.left()
- boxSt.buttonPadding.right();
if (correct > 0 && buttonWidth != correct) {
result->resizeToWidth(correct);
result->moveToLeft(
boxSt.buttonPadding.left(),
boxSt.buttonPadding.top(),
width);
}
}, result->lifetime());
return result;
}
[[nodiscard]] object_ptr<Ui::BoxContent> StarRefLinkBox(
ConnectedBot row,
not_null<PeerData*> peer) {
return Box([=](not_null<Ui::GenericBox*> box) {
box->setTitle(tr::lng_star_ref_link_title());
const auto bot = row.bot;
const auto program = row.state.program;
auto duration = !program.durationMonths
? tr::lng_star_ref_one_about_for_forever(Ui::Text::RichLangValue)
: (program.durationMonths < 12)
? tr::lng_star_ref_one_about_for_months(
lt_count,
rpl::single(program.durationMonths * 1.),
Ui::Text::RichLangValue)
: tr::lng_star_ref_one_about_for_years(
lt_count,
rpl::single((program.durationMonths / 12) * 1.),
Ui::Text::RichLangValue);
auto text = tr::lng_star_ref_link_about_channel(
lt_amount,
rpl::single(Ui::Text::Bold(FormatStarRefCommission(program.commission))),
lt_app,
rpl::single(Ui::Text::Bold(bot->name())),
lt_duration,
std::move(duration),
Ui::Text::WithEntities);
box->addRow(
object_ptr<Ui::FlatLabel>(box, std::move(text), st::boxLabel));
Ui::AddSkip(box->verticalLayout());
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
rpl::single(row.state.link) | Ui::Text::ToLink(),
st::boxLabel));
Ui::AddSkip(box->verticalLayout());
if (row.state.users > 0) {
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_link_copy_users(
lt_count,
rpl::single(row.state.users * 1.),
lt_app,
rpl::single(bot->name())),
st::boxLabel));
} else {
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_link_copy_none(
lt_app,
rpl::single(bot->name())),
st::boxLabel));
}
box->addButton(tr::lng_star_ref_link_copy(), [=] {
QApplication::clipboard()->setText(row.state.link);
box->uiShow()->showToast(tr::lng_username_copied(tr::now));
});
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
});
}
[[nodiscard]] object_ptr<Ui::BoxContent> JoinStarRefBox(
ConnectedBot row,
not_null<PeerData*> peer) {
Expects(row.bot->isUser());
return Box([=](not_null<Ui::GenericBox*> box) {
const auto show = box->uiShow();
const auto bot = row.bot;
const auto program = row.state.program;
box->setStyle(st::starrefFooterBox);
box->setNoContentMargin(true);
box->addTopButton(st::boxTitleClose, [=] {
box->closeBox();
});
box->addRow(
CreateUserpicsTransfer(
box,
rpl::single(std::vector{ not_null<PeerData*>(bot) }),
peer,
UserpicsTransferType::StarRefJoin),
st::boxRowPadding + st::starrefJoinUserpicsPadding);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_title(),
st::boxTitle)),
st::boxRowPadding + st::starrefJoinTitlePadding);
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_one_about(
lt_app,
rpl::single(Ui::Text::Bold(bot->name())),
lt_amount,
rpl::single(Ui::Text::Bold(
FormatStarRefCommission(program.commission))),
lt_duration,
FormatProgramDuration(program),
Ui::Text::WithEntities),
st::boxLabel),
st::boxRowPadding);
struct State {
QPointer<Ui::GenericBox> weak;
bool sent = false;
};
const auto state = std::make_shared<State>();
state->weak = box;
const auto send = [=] {
if (state->sent) {
return;
}
state->sent = true;
bot->session().api().request(MTPpayments_ConnectStarRefBot(
peer->input,
bot->asUser()->inputUser
)).done([=](const MTPpayments_ConnectedStarRefBots &result) {
const auto parsed = Parse(&bot->session(), result);
if (parsed.empty()) {
state->sent = false;
show->showToast(u"Failed."_q);
} else {
show->show(StarRefLinkBox(parsed.front(), peer));
if (const auto strong = state->weak.data()) {
strong->closeBox();
}
}
}).fail([=](const MTP::Error &error) {
state->sent = false;
show->showToast(u"Failed: "_q + error.type());
}).send();
};
const auto button = AddFullWidthButton(
box,
tr::lng_star_ref_one_join(),
send);
const auto footer = Ui::CreateChild<Ui::FlatLabel>(
button->parentWidget(),
tr::lng_star_ref_one_join_text(
lt_terms,
tr::lng_star_ref_button_link(
) | Ui::Text::ToLink(tr::lng_star_ref_tos_url(tr::now)),
Ui::Text::WithEntities),
st::starrefJoinFooter);
button->geometryValue() | rpl::start_with_next([=](QRect geometry) {
footer->resizeToWidth(geometry.width());
const auto &st = box->getDelegate()->style();
const auto top = geometry.y() + geometry.height();
const auto available = st.buttonPadding.bottom();
footer->moveToLeft(
geometry.left(),
top + (available - footer->height()) / 2);
}, footer->lifetime());
});
}
ListController::ListController(
not_null<Controller*> controller,
not_null<PeerData*> peer,
@ -131,20 +367,22 @@ Main::Session &ListController::session() const {
return _peer->session();
}
std::unique_ptr<PeerListRow> ListController::createRow(
not_null<PeerData*> peer,
RowState state) {
_states.emplace(peer, state);
auto result = std::make_unique<PeerListRow>(peer);
const auto program = state.program;
std::unique_ptr<PeerListRow> ListController::createRow(ConnectedBot bot) {
_states.emplace(bot.bot, bot.state);
auto result = std::make_unique<PeerListRow>(bot.bot);
const auto program = bot.state.program;
const auto duration = !program.durationMonths
? tr::lng_star_ref_duration_forever(tr::now)
: (program.durationMonths < 12)
? tr::lng_months(tr::now, lt_count, program.durationMonths)
: tr::lng_years(tr::now, lt_count, program.durationMonths / 12);
result->setCustomStatus(u"+%1%, %2"_q.arg(
QString::number(program.commission / 10.),
duration));
if (bot.state.revoked) {
result->setCustomStatus(u"Revoked"_q);
} else {
result->setCustomStatus(u"+%1%, %2"_q.arg(
QString::number(program.commission / 10.),
duration));
}
return result;
}
@ -170,32 +408,12 @@ void ListController::loadMoreRows() {
MTP_string(_offsetThing),
MTP_int(kPerPage)
)).done([=](const MTPpayments_ConnectedStarRefBots &result) {
const auto &data = result.data();
session().data().processUsers(data.vusers());
const auto &list = data.vconnected_bots().v;
if (list.empty()) {
const auto parsed = Parse(&session(), result);
if (parsed.empty()) {
_allLoaded = true;
} else {
for (const auto &bot : list) {
const auto &data = bot.data();
const auto botId = UserId(data.vbot_id());
_offsetThing = qs(data.vurl());
_offsetDate = data.vdate().v;
const auto commission = data.vcommission_permille().v;
const auto durationMonths
= data.vduration_months().value_or_empty();
const auto user = session().data().user(botId);
if (data.is_revoked()) {
continue;
}
delegate()->peerListAppendRow(createRow(user, {
.program = {
.commission = ushort(commission),
.durationMonths = uchar(durationMonths),
},
.link = _offsetThing,
.users = int(data.vparticipants().v),
}));
for (const auto &bot : parsed) {
delegate()->peerListAppendRow(createRow(bot));
}
delegate()->peerListRefreshRows();
_rowCount = delegate()->peerListFullRowsCount();
@ -226,10 +444,13 @@ void ListController::loadMoreRows() {
const auto durationMonths
= data.vduration_months().value_or_empty();
const auto user = session().data().user(botId);
delegate()->peerListAppendRow(createRow(user, {
.program = {
.commission = ushort(commission),
.durationMonths = uchar(durationMonths),
delegate()->peerListAppendRow(createRow({
.bot = user,
.state = {
.program = {
.commission = ushort(commission),
.durationMonths = uchar(durationMonths),
},
},
}));
}
@ -246,152 +467,25 @@ void ListController::loadMoreRows() {
rpl::producer<int> ListController::rowCountValue() const {
return _rowCount.value();
}
//
//std::unique_ptr<PeerListState> ListController::saveState() const {
// auto result = PeerListController::saveState();
// auto my = std::make_unique<SavedState>();
// result->controllerState = std::move(my);
// return result;
//}
//
//void ListController::restoreState(
// std::unique_ptr<PeerListState> state) {
// auto typeErasedState = state
// ? state->controllerState.get()
// : nullptr;
// if (dynamic_cast<SavedState*>(typeErasedState)) {
// PeerListController::restoreState(std::move(state));
// }
//}
void ListController::showLink(not_null<PeerData*> peer, RowState state) {
const auto window = _controller->parentController();
window->show(Box([=](not_null<Ui::GenericBox*> box) {
box->setTitle(tr::lng_star_ref_link_title());
const auto program = state.program;
auto duration = !program.durationMonths
? tr::lng_star_ref_one_about_for_forever(Ui::Text::RichLangValue)
: (program.durationMonths < 12)
? tr::lng_star_ref_one_about_for_months(
lt_count,
rpl::single(program.durationMonths * 1.),
Ui::Text::RichLangValue)
: tr::lng_star_ref_one_about_for_years(
lt_count,
rpl::single((program.durationMonths / 12) * 1.),
Ui::Text::RichLangValue);
auto text = tr::lng_star_ref_link_about_channel(
lt_amount,
rpl::single(Ui::Text::Bold(QString::number(program.commission / 10.) + '%')),
lt_app,
rpl::single(Ui::Text::Bold(peer->name())),
lt_duration,
std::move(duration),
Ui::Text::WithEntities);
box->addRow(
object_ptr<Ui::FlatLabel>(box, std::move(text), st::boxLabel));
Ui::AddSkip(box->verticalLayout());
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
rpl::single(state.link) | Ui::Text::ToLink(),
st::boxLabel));
Ui::AddSkip(box->verticalLayout());
if (state.users > 0) {
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_link_copy_users(
lt_count,
rpl::single(state.users * 1.),
lt_app,
rpl::single(peer->name())),
st::boxLabel));
} else {
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_star_ref_link_copy_none(
lt_app,
rpl::single(peer->name())),
st::boxLabel));
}
box->addButton(tr::lng_star_ref_link_copy(), [=] {
QApplication::clipboard()->setText(state.link);
window->showToast(tr::lng_username_copied(tr::now));
});
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
}));
}
void ListController::rowClicked(not_null<PeerListRow*> row) {
const auto peer = row->peer();
const auto i = _states.find(peer);
const auto bot = row->peer()->asUser();
const auto i = _states.find(bot);
Assert(i != end(_states));
const auto state = i->second;
const auto program = state.program;
const auto window = _controller->parentController();
if (_type == JoinType::Joined || !state.link.isEmpty()) {
showLink(row->peer(), state);
window->show(StarRefLinkBox({ bot, state }, _peer));
} else {
const auto join = [=](Fn<void()> close) {
session().api().request(MTPpayments_ConnectStarRefBot(
_peer->input,
peer->asUser()->inputUser
)).done([=](const MTPpayments_ConnectedStarRefBots &result) {
window->showToast(u"Connected!"_q);
close();
}).fail([=](const MTP::Error &error) {
window->showToast(u"Failed: "_q + error.type());
}).send();
};
auto duration = !program.durationMonths
? tr::lng_star_ref_one_about_for_forever(Ui::Text::RichLangValue)
: (program.durationMonths < 12)
? tr::lng_star_ref_one_about_for_months(
lt_count,
rpl::single(program.durationMonths * 1.),
Ui::Text::RichLangValue)
: tr::lng_star_ref_one_about_for_years(
lt_count,
rpl::single((program.durationMonths / 12) * 1.),
Ui::Text::RichLangValue);
auto text = tr::lng_star_ref_one_about(
lt_app,
rpl::single(Ui::Text::Bold(peer->name())),
lt_amount,
rpl::single(Ui::Text::Bold(QString::number(program.commission / 10.) + '%')),
lt_duration,
std::move(duration),
Ui::Text::WithEntities);
auto added = tr::lng_star_ref_one_join_text(
lt_terms,
tr::lng_star_ref_button_link() | Ui::Text::ToLink(),
Ui::Text::WithEntities);
auto joined = rpl::combine(
std::move(text),
std::move(added)
) | rpl::map([=](TextWithEntities a, TextWithEntities b) {
return a.append("\n\n").append(b);
});
window->show(Ui::MakeConfirmBox({
.text = std::move(joined),
.confirmed = join,
.confirmText = tr::lng_star_ref_one_join(),
.title = tr::lng_star_ref_title(),
}));
window->show(JoinStarRefBox({ bot, state }, _peer));
}
}
base::unique_qptr<Ui::PopupMenu> ListController::rowContextMenu(
QWidget *parent,
not_null<PeerListRow*> row) {
const auto peer = row->peer();
const auto i = _states.find(peer);
const auto bot = row->peer()->asUser();
const auto i = _states.find(bot);
Assert(i != end(_states));
const auto state = i->second;
if (state.link.isEmpty()) {
@ -403,7 +497,7 @@ base::unique_qptr<Ui::PopupMenu> ListController::rowContextMenu(
const auto addAction = Ui::Menu::CreateAddActionCallback(result.get());
addAction(tr::lng_star_ref_list_my_open(tr::now), [=] {
_controller->parentController()->showPeerHistory(peer);
_controller->parentController()->showPeerHistory(bot);
}, &st::menuIconBot);
addAction(tr::lng_star_ref_list_my_copy(tr::now), [=] {
QApplication::clipboard()->setText(state.link);
@ -774,5 +868,9 @@ std::shared_ptr<Info::Memento> Make(not_null<PeerData*> peer) {
std::make_shared<Memento>(peer)));
}
QString FormatStarRefCommission(ushort commission) {
return QString::number(commission / 10.) + '%';
}
} // namespace Info::BotStarRef::Join

View file

@ -76,4 +76,6 @@ private:
[[nodiscard]] std::shared_ptr<Info::Memento> Make(not_null<PeerData*> peer);
[[nodiscard]] QString FormatStarRefCommission(ushort commission);
} // namespace Info::BotStarRef::Join

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h"
#include "core/click_handler_types.h"
#include "data/data_user.h"
#include "info/bot/starref/info_bot_starref_join_widget.h"
#include "info/profile/info_profile_icon.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
@ -495,7 +496,7 @@ void InnerWidget::setupCommission() {
commission,
setCommission,
setCommission,
[=](int value) { return QString::number(value / 10.) + '%'; },
[=](int value) { return Join::FormatStarRefCommission(value); },
_state.exists),
st::boxRowPadding);
@ -852,7 +853,8 @@ std::unique_ptr<Ui::RpWidget> Widget::setupBottom() {
? tr::lng_star_ref_update_info
: tr::lng_star_ref_start_info)(
lt_terms,
tr::lng_star_ref_button_link() | Ui::Text::ToLink(),
tr::lng_star_ref_button_link(
) | Ui::Text::ToLink(tr::lng_star_ref_tos_url(tr::now)),
Ui::Text::WithEntities),
st::boxDividerLabel),
QMargins(margins.left(), 0, margins.right(), 0));

View file

@ -81,6 +81,24 @@ starrefCover: PremiumCover(userPremiumCover) {
titlePadding: margins(0px, 12px, 0px, 11px);
}
starrefCoverHeight: 180px;
starrefFooterBox: Box(defaultBox) {
buttonPadding: margins(22px, 11px, 22px, 54px);
buttonHeight: 42px;
button: RoundButton(defaultActiveButton) {
height: 42px;
textTop: 12px;
style: semiboldTextStyle;
}
shadowIgnoreTopSkip: true;
}
starrefJoinIcon: icon{{ "payments/small_star", premiumButtonFg }};
starrefJoinUserpicsPadding: margins(0px, 32px, 0px, 10px);
starrefJoinTitlePadding: margins(0px, 0px, 0px, 12px);
starrefJoinFooter: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;
align: align(top);
minWidth: 240px;
}
defaultPremiumBoxLabel: FlatLabel(defaultFlatLabel) {
minWidth: 220px;