/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/boosts/info_boosts_inner_widget.h" #include "api/api_statistics.h" #include "boxes/peers/edit_peer_invite_link.h" #include "info/info_controller.h" #include "lang/lang_keys.h" #include "settings/settings_common.h" #include "statistics/widgets/chart_header_widget.h" #include "ui/boxes/boost_box.h" #include "ui/controls/invite_link_buttons.h" #include "ui/controls/invite_link_label.h" #include "ui/rect.h" #include "ui/widgets/labels.h" #include "styles/style_info.h" #include "styles/style_statistics.h" #include namespace Info::Boosts { namespace { void AddHeader( not_null content, tr::phrase<> text) { const auto header = content->add( object_ptr(content), st::statisticsLayerMargins + st::statisticsChartHeaderPadding); header->resizeToWidth(header->width()); header->setTitle(text(tr::now)); header->setSubTitle({}); } void FillOverview( not_null content, const Data::BoostStatus &status) { const auto &stats = status.overview; ::Settings::AddSkip(content, st::statisticsLayerOverviewMargins.top()); AddHeader(content, tr::lng_stats_overview_title); ::Settings::AddSkip(content); const auto diffBetweenHeaders = 0 + st::statisticsOverviewValue.style.font->height - st::statisticsHeaderTitleTextStyle.font->height; const auto container = content->add( object_ptr(content), st::statisticsLayerMargins); const auto addPrimary = [&](float64 v) { return Ui::CreateChild( container, (v >= 0) ? Lang::FormatCountToShort(v).string : QString(), st::statisticsOverviewValue); }; const auto addSub = [&]( not_null primary, float64 percentage, tr::phrase<> text) { const auto second = Ui::CreateChild( container, percentage ? u"%1%"_q.arg(std::abs(std::round(percentage * 10.) / 10.)) : QString(), st::statisticsOverviewSecondValue); second->setTextColorOverride(st::windowSubTextFg->c); const auto sub = Ui::CreateChild( container, text(), st::statisticsOverviewSubtext); sub->setTextColorOverride(st::windowSubTextFg->c); primary->geometryValue( ) | rpl::start_with_next([=](const QRect &g) { const auto &padding = st::statisticsOverviewSecondValuePadding; second->moveToLeft( rect::right(g) + padding.left(), g.y() + padding.top()); sub->moveToLeft( g.x(), st::statisticsChartHeaderHeight - st::statisticsOverviewSubtext.style.font->height + g.y() + diffBetweenHeaders); }, primary->lifetime()); }; const auto topLeftLabel = addPrimary(stats.level); const auto topRightLabel = addPrimary(stats.premiumMemberCount); const auto bottomLeftLabel = addPrimary(stats.boostCount); const auto bottomRightLabel = addPrimary( stats.nextLevelBoostCount - stats.boostCount); addSub( topLeftLabel, 0, tr::lng_boosts_level); addSub( topRightLabel, stats.premiumMemberPercentage, tr::lng_boosts_premium_audience); addSub( bottomLeftLabel, 0, tr::lng_boosts_existing); addSub( bottomRightLabel, 0, tr::lng_boosts_next_level); container->showChildren(); container->resize(container->width(), topLeftLabel->height() * 5); container->sizeValue( ) | rpl::start_with_next([=](const QSize &s) { const auto halfWidth = s.width() / 2; { const auto &p = st::statisticsOverviewValuePadding; topLeftLabel->moveToLeft(p.left(), p.top()); } topRightLabel->moveToLeft( topLeftLabel->x() + halfWidth + st::statisticsOverviewRightSkip, topLeftLabel->y()); bottomLeftLabel->moveToLeft( topLeftLabel->x(), topLeftLabel->y() + st::statisticsOverviewMidSkip); bottomRightLabel->moveToLeft( topRightLabel->x(), bottomLeftLabel->y()); }, container->lifetime()); ::Settings::AddSkip(content, st::statisticsLayerOverviewMargins.bottom()); } void FillShareLink( not_null content, std::shared_ptr show, const QString &link, not_null peer) { const auto weak = Ui::MakeWeak(content); const auto copyLink = crl::guard(weak, [=] { QGuiApplication::clipboard()->setText(link); show->showToast(tr::lng_channel_public_link_copied(tr::now)); }); const auto shareLink = crl::guard(weak, [=] { show->showBox(ShareInviteLinkBox(peer, link)); }); const auto label = content->lifetime().make_state( content, rpl::single(link), nullptr); content->add( label->take(), st::inviteLinkFieldPadding); label->clicks( ) | rpl::start_with_next(copyLink, label->lifetime()); const auto copyShareWrap = content->add( object_ptr(content)); Ui::AddCopyShareLinkButtons(copyShareWrap, copyLink, shareLink); copyShareWrap->widgetAt(0)->showChildren(); ::Settings::AddSkip(content, st::inviteLinkFieldPadding.bottom()); } } // namespace InnerWidget::InnerWidget( QWidget *parent, not_null controller, not_null peer) : VerticalLayout(parent) , _controller(controller) , _peer(peer) , _show(controller->uiShow()) { const auto api = lifetime().make_state(peer); const auto fakeShowed = lifetime().make_state>(); _showFinished.events( ) | rpl::take(1) | rpl::start_with_next([=] { api->request( ) | rpl::start_with_error_done([](const QString &error) { }, [=] { const auto status = api->boostStatus(); const auto inner = this; Ui::FillBoostLimit( fakeShowed->events(), rpl::single(status.overview.isBoosted), inner, Ui::BoostBoxData{ .boost = Ui::BoostCounters{ .level = status.overview.level, .boosts = status.overview.boostCount, .thisLevelBoosts = status.overview.currentLevelBoostCount, .nextLevelBoosts = status.overview.nextLevelBoostCount, .mine = status.overview.isBoosted, } }); FillOverview(inner, status); ::Settings::AddSkip(inner); AddHeader(inner, tr::lng_boosts_link_title); FillShareLink(inner, _show, status.link, peer); ::Settings::AddSkip(inner); ::Settings::AddDividerText(inner, tr::lng_boosts_link_subtext()); resizeToWidth(width()); crl::on_main([=]{ fakeShowed->fire({}); }); }, lifetime()); }, lifetime()); } rpl::producer InnerWidget::scrollToRequests() const { return _scrollToRequests.events(); } auto InnerWidget::showRequests() const -> rpl::producer { return _showRequests.events(); } void InnerWidget::showFinished() { _showFinished.fire({}); } not_null InnerWidget::peer() const { return _peer; } } // namespace Info::Boosts