From 778317e1b2aa3703dd0d867a19a14bdf545f35b0 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 21 Mar 2024 04:43:53 +0300 Subject: [PATCH] Added initial slider for earn settings to channel earn info section. --- Telegram/Resources/langs/lang.strings | 4 +- .../boxes/peers/edit_peer_color_box.cpp | 66 ++++---- .../boxes/peers/edit_peer_color_box.h | 10 ++ .../earn/info_earn_inner_widget.cpp | 143 +++++++++++++++++- 4 files changed, 182 insertions(+), 41 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3d734f568..a61422998 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4971,8 +4971,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_channel_earn_off" = "Switch Off Ads"; "lng_channel_earn_off_about" = "You will not be eligible for any rewards if you switch off ads."; "lng_channel_earn_cpm_min" = "No Ads"; -"lng_channel_earn_cpm#one" = "{count} CPM"; -"lng_channel_earn_cpm#other" = "{count} CPM"; +"lng_channel_earn_cpm#one" = "{emoji} {count} CPM"; +"lng_channel_earn_cpm#other" = "{emoji} {count} CPM"; "lng_channel_earn_learn_title" = "Earn From Your Channel"; "lng_channel_earn_learn_in_subtitle" = "Telegram Ads"; "lng_channel_earn_learn_in_about" = "Telegram can display ads in your channel."; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index 50470657a..018d07915 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -521,39 +521,6 @@ void LevelBadge::paintEvent(QPaintEvent *e) { _text.draw(p, context); } -void AddLevelBadge( - int level, - not_null button, - Ui::RpWidget *right, - not_null channel, - const QMargins &padding, - rpl::producer text) { - if (channel->levelHint() >= level) { - return; - } - const auto badge = Ui::CreateChild( - button.get(), - level, - &channel->session()); - badge->show(); - const auto sampleLeft = st::settingsColorSamplePadding.left(); - const auto badgeLeft = padding.left() + sampleLeft; - rpl::combine( - button->sizeValue(), - std::move(text) - ) | rpl::start_with_next([=](const QSize &s, const QString &) { - if (s.isNull()) { - return; - } - badge->moveToLeft( - button->fullTextWidth() + badgeLeft, - (s.height() - badge->height()) / 2); - const auto rightEdge = right ? right->pos().x() : button->width(); - badge->setMinimal((rect::right(badge) + sampleLeft) > rightEdge); - badge->setVisible((rect::right(badge) + sampleLeft) < rightEdge); - }, badge->lifetime()); -} - struct SetValues { uint8 colorIndex = 0; DocumentId backgroundEmojiId = 0; @@ -1165,6 +1132,39 @@ int ColorSelector::resizeGetHeight(int newWidth) { } // namespace +void AddLevelBadge( + int level, + not_null button, + Ui::RpWidget *right, + not_null channel, + const QMargins &padding, + rpl::producer text) { + if (channel->levelHint() >= level) { + return; + } + const auto badge = Ui::CreateChild( + button.get(), + level, + &channel->session()); + badge->show(); + const auto sampleLeft = st::settingsColorSamplePadding.left(); + const auto badgeLeft = padding.left() + sampleLeft; + rpl::combine( + button->sizeValue(), + std::move(text) + ) | rpl::start_with_next([=](const QSize &s, const QString &) { + if (s.isNull()) { + return; + } + badge->moveToLeft( + button->fullTextWidth() + badgeLeft, + (s.height() - badge->height()) / 2); + const auto rightEdge = right ? right->pos().x() : button->width(); + badge->setMinimal((rect::right(badge) + sampleLeft) > rightEdge); + badge->setVisible((rect::right(badge) + sampleLeft) < rightEdge); + }, badge->lifetime()); +} + void EditPeerColorBox( not_null box, std::shared_ptr show, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h index cf83bfc74..2272123a1 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h @@ -20,14 +20,24 @@ class Show; } // namespace ChatHelpers namespace Ui { +class RpWidget; class GenericBox; class ChatStyle; class ChatTheme; class VerticalLayout; struct AskBoostReason; class RpWidget; +class SettingsButton; } // namespace Ui +void AddLevelBadge( + int level, + not_null button, + Ui::RpWidget *right, + not_null channel, + const QMargins &padding, + rpl::producer text); + void EditPeerColorBox( not_null box, std::shared_ptr show, diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp index d37989e61..ff1422e26 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/random.h" #include "base/unixtime.h" +#include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge. #include "chat_helpers/stickers_emoji_pack.h" #include "core/ui_integration.h" // Core::MarkedTextContext. #include "data/data_peer.h" @@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/profile/info_profile_values.h" // Info::Profile::NameValue. #include "lang/lang_keys.h" #include "main/main_session.h" +#include "settings/settings_common.h" #include "statistics/widgets/chart_header_widget.h" #include "ui/controls/userpic_button.h" #include "ui/effects/animation_value.h" @@ -30,14 +32,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/vertical_list.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/wrap/slide_wrap.h" +#include "ui/wrap/slide_wrap.h" #include "styles/style_boxes.h" #include "styles/style_channel_earn.h" #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" #include "styles/style_layers.h" +#include "styles/style_settings.h" #include "styles/style_statistics.h" #include @@ -92,10 +97,8 @@ void AddRecipient(not_null box, const TextWithEntities &t) { }); } -void AddEmojiToMajor( - not_null label, - not_null session, - float64 value) { +[[nodiscard]] TextWithEntities EmojiCurrency( + not_null session) { auto emoji = TextWithEntities{ .text = (QString(QChar(0xD83D)) + QChar(0xDC8E)), }; @@ -105,6 +108,14 @@ void AddEmojiToMajor( emoji = Data::SingleCustomEmoji(sticker.document); } } + return emoji; +} + +void AddEmojiToMajor( + not_null label, + not_null session, + float64 value) { + auto emoji = EmojiCurrency(session); label->setMarkedText( emoji.append(' ').append(QString::number(int64(value))), Core::MarkedTextContext{ @@ -142,6 +153,7 @@ void InnerWidget::fill() { const auto container = this; constexpr auto kMinus = QChar(0x2212); + constexpr auto kApproximately = QChar(0x2248); const auto currency = u"TON"_q; const auto multiplier = 3.8; // Debug. @@ -224,7 +236,7 @@ void InnerWidget::fill() { container, object_ptr( container, - QString(QChar(0x2248)) + QString(kApproximately) + QChar('$') + QString::number(value * multiplier), st::channelEarnOverviewSubMinorLabel))); @@ -346,7 +358,7 @@ void InnerWidget::fill() { st::channelEarnOverviewMinorLabel); const auto secondMinorLabel = Ui::CreateChild( line, - QString(QChar(0x2248)) + QString(kApproximately) + QChar('$') + QString::number(value * multiplier), st::channelEarnOverviewSubMinorLabel); @@ -651,6 +663,125 @@ void InnerWidget::fill() { Ui::AddSkip(container); Ui::AddDivider(container); Ui::AddSkip(container); + if (const auto channel = _peer->asChannel()) { + constexpr auto kMaxCPM = 50; // Debug. + const auto &phrase = tr::lng_channel_earn_off; + const auto button = container->add(object_ptr( + container, + phrase(), + st::settingsButtonNoIcon)); + + constexpr auto kMinLevel = 30; // Debug. + AddLevelBadge( + kMinLevel, + button, + nullptr, + channel, + QMargins(st::boxRowPadding.left(), 0, 0, 0), + phrase()); + + const auto wrap = container->add( + object_ptr>( + container, + object_ptr(container)), + st::boxRowPadding); + const auto inner = wrap->entity(); + Ui::AddSkip(inner); + Ui::AddSkip(inner); + const auto line = inner->add(object_ptr(inner)); + Ui::AddSkip(inner); + Ui::AddSkip(inner); + const auto left = Ui::CreateChild( + line, + tr::lng_channel_earn_cpm_min(), + st::defaultFlatLabel); + const auto center = Ui::CreateChild( + line, + st::defaultFlatLabel); + const auto right = Ui::CreateChild( + line, + st::defaultFlatLabel); + AddEmojiToMajor(right, session, kMaxCPM); + const auto slider = Ui::CreateChild( + line, + st::settingsScale); + rpl::combine( + line->sizeValue(), + left->sizeValue(), + center->sizeValue(), + right->sizeValue() + ) | rpl::start_with_next([=]( + const QSize &s, + const QSize &leftSize, + const QSize ¢erSize, + const QSize &rightSize) { + const auto sliderHeight = st::settingsScale.seekSize.height(); + line->resize( + line->width(), + leftSize.height() + sliderHeight * 2); + { + const auto r = line->rect(); + slider->setGeometry( + 0, + r.height() - sliderHeight, + r.width(), + sliderHeight); + } + left->moveToLeft(0, 0); + right->moveToRight(0, 0); + center->moveToLeft((s.width() - centerSize.width()) / 2, 0); + }, line->lifetime()); + + const auto updateLabels = [=](int cpm) { + const auto activeColor = st::windowActiveTextFg->c; + left->setTextColorOverride(!cpm + ? std::make_optional(activeColor) + : std::nullopt); + + if (cpm > 0 && cpm < kMaxCPM) { + center->setMarkedText( + tr::lng_channel_earn_cpm( + tr::now, + lt_count, + cpm, + lt_emoji, + EmojiCurrency(session), + Ui::Text::RichLangValue), + Core::MarkedTextContext{ + .session = session, + .customEmojiRepaint = [center] { center->update(); }, + }); + } else { + center->setText({}); + } + center->setTextColorOverride(activeColor); + + right->setTextColorOverride((cpm == kMaxCPM) + ? std::make_optional(activeColor) + : std::nullopt); + }; + const auto current = kMaxCPM / 2; + slider->setPseudoDiscrete( + kMaxCPM + 1, + [=](int index) { return index; }, + current, + updateLabels, + updateLabels); + updateLabels(current); + + wrap->toggle(false, anim::type::instant); + button->toggleOn( + rpl::single(false) // Debug. + )->toggledChanges( + ) | rpl::filter([=](bool toggled) { + return true; + }) | rpl::start_with_next([=](bool toggled) { + wrap->toggle(toggled, anim::type::normal); + }, container->lifetime()); + + Ui::AddDividerText(container, tr::lng_channel_earn_off_about()); + } + Ui::AddSkip(container); } void InnerWidget::saveState(not_null memento) {