From 3311a50750bd2c1e1174e7d875051c35c77d2dfa Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 28 Mar 2024 06:40:16 +0300 Subject: [PATCH] Added second rulers to currency chart in channel earn info section. --- .../SourceFiles/data/data_statistics_chart.h | 2 +- .../channel_statistics/earn/earn_format.cpp | 58 +++++++++++++++++++ .../channel_statistics/earn/earn_format.h | 18 ++++++ .../earn/info_earn_inner_widget.cpp | 52 ++--------------- .../statistics/chart_rulers_data.cpp | 20 +++---- .../statistics/chart_rulers_data.h | 3 +- .../statistics_data_deserialize.cpp | 7 --- .../statistics/view/chart_rulers_view.cpp | 37 +++++++++--- .../statistics/view/chart_rulers_view.h | 3 + .../widgets/point_details_widget.cpp | 4 +- Telegram/cmake/td_ui.cmake | 3 + 11 files changed, 131 insertions(+), 76 deletions(-) create mode 100644 Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp create mode 100644 Telegram/SourceFiles/info/channel_statistics/earn/earn_format.h diff --git a/Telegram/SourceFiles/data/data_statistics_chart.h b/Telegram/SourceFiles/data/data_statistics_chart.h index 48309e49f..5a29ebef7 100644 --- a/Telegram/SourceFiles/data/data_statistics_chart.h +++ b/Telegram/SourceFiles/data/data_statistics_chart.h @@ -65,7 +65,7 @@ struct StatisticalChart { bool isFooterHidden = false; bool hasPercentages = false; bool weekFormat = false; - bool isCurrency = false; + float64 currencyRate = 0.; // View data. int dayStringMaxWidth = 0; diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp new file mode 100644 index 000000000..e79fa89ce --- /dev/null +++ b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp @@ -0,0 +1,58 @@ +/* +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/channel_statistics/earn/earn_format.h" + +namespace Info::ChannelEarn { + +using EarnInt = Data::EarnInt; + +constexpr auto kMinorPartLength = 9; +constexpr auto kZero = QChar('0'); +constexpr auto kDot = QChar('.'); + +QString MajorPart(EarnInt value) { + const auto string = QString::number(value); + const auto diff = int(string.size()) - kMinorPartLength; + return (diff <= 0) ? QString(kZero) : string.mid(0, diff); +} + +QString MinorPart(EarnInt value) { + if (!value) { + return QString(kDot) + kZero + kZero; + } + const auto string = QString::number(value); + const auto diff = int(string.size()) - kMinorPartLength; + const auto result = (diff < 0) + ? kDot + u"%1"_q.arg(0, std::abs(diff), 10, kZero) + string + : kDot + string.mid(diff); + const auto begin = (result.constData()); + const auto end = (begin + result.size()); + auto ch = end - 1; + auto zeroCount = 0; + while (ch != begin) { + if ((*ch) == kZero) { + zeroCount++; + } else { + break; + } + ch--; + } + return result.chopped(zeroCount); +} + +QString ToUsd(EarnInt value, float64 rate) { + constexpr auto kApproximately = QChar(0x2248); + const auto multiplier = EarnInt(rate * Data::kEarnMultiplier); + const auto result = (value * multiplier) / Data::kEarnMultiplier; + return QString(kApproximately) + + QChar('$') + + MajorPart(result) + + MinorPart(result); +} + +} // namespace Info::ChannelEarn diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.h b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.h new file mode 100644 index 000000000..4a7b401ab --- /dev/null +++ b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.h @@ -0,0 +1,18 @@ +/* +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 +*/ +#pragma once + +#include "data/data_channel_earn.h" + +namespace Info::ChannelEarn { + +[[nodiscard]] QString MajorPart(Data::EarnInt value); +[[nodiscard]] QString MinorPart(Data::EarnInt value); +[[nodiscard]] QString ToUsd(Data::EarnInt value, float64 rate); + +} // namespace Info::ChannelEarn 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 b79a6855e..fb190736c 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 @@ -16,12 +16,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_premium_limits.h" #include "data/data_session.h" #include "data/stickers/data_custom_emoji.h" +#include "info/channel_statistics/earn/earn_format.h" #include "info/channel_statistics/earn/info_earn_widget.h" #include "info/info_controller.h" #include "info/profile/info_profile_values.h" // Info::Profile::NameValue. #include "info/statistics/info_statistics_inner_widget.h" // FillLoading. #include "lang/lang_keys.h" -#include "ui/widgets/popup_menu.h" #include "main/main_app_config.h" #include "main/main_session.h" #include "statistics/chart_widget.h" @@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/vertical_list.h" #include "ui/widgets/fields/input_field.h" +#include "ui/widgets/popup_menu.h" #include "ui/wrap/slide_wrap.h" #include "styles/style_boxes.h" #include "styles/style_channel_earn.h" @@ -53,50 +54,6 @@ namespace { using EarnInt = Data::EarnInt; -constexpr auto kMinorPartLength = 9; -constexpr auto kZero = QChar('0'); -constexpr auto kDot = QChar('.'); - -[[nodiscard]] QString MajorPart(EarnInt value) { - const auto string = QString::number(value); - const auto diff = int(string.size()) - kMinorPartLength; - return (diff <= 0) ? QString(kZero) : string.mid(0, diff); -} - -[[nodiscard]] QString MinorPart(EarnInt value) { - if (!value) { - return QString(kDot) + kZero + kZero; - } - const auto string = QString::number(value); - const auto diff = int(string.size()) - kMinorPartLength; - const auto result = (diff < 0) - ? kDot + u"%1"_q.arg(0, std::abs(diff), 10, kZero) + string - : kDot + string.mid(diff); - const auto begin = (result.constData()); - const auto end = (begin + result.size()); - auto ch = end - 1; - auto zeroCount = 0; - while (ch != begin) { - if ((*ch) == kZero) { - zeroCount++; - } else { - break; - } - ch--; - } - return result.chopped(zeroCount); -} - -[[nodiscard]] QString ToUsd(EarnInt value, float64 rate) { - constexpr auto kApproximately = QChar(0x2248); - const auto multiplier = EarnInt(rate * Data::kEarnMultiplier); - const auto result = (value * multiplier) / Data::kEarnMultiplier; - return QString(kApproximately) - + QChar('$') - + MajorPart(result) - + MinorPart(result); -} - [[nodiscard]] bool WithdrawalEnabled(not_null session) { const auto key = u"channel_revenue_withdrawal_enabled"_q; return session->appConfig().get(key, false); @@ -480,7 +437,10 @@ void InnerWidget::fill() { object_ptr(container), st::statisticsLayerMargins); - widget->setChartData(data.revenueGraph.chart, Type::StackBar); + auto chart = data.revenueGraph.chart; + chart.currencyRate = multiplier; + + widget->setChartData(chart, Type::StackBar); widget->setTitle(tr::lng_channel_earn_chart_revenue()); } Ui::AddSkip(container); diff --git a/Telegram/SourceFiles/statistics/chart_rulers_data.cpp b/Telegram/SourceFiles/statistics/chart_rulers_data.cpp index 99aec0198..1b4e9c33a 100644 --- a/Telegram/SourceFiles/statistics/chart_rulers_data.cpp +++ b/Telegram/SourceFiles/statistics/chart_rulers_data.cpp @@ -28,13 +28,6 @@ constexpr auto kStep = 5.; : QString::number(absoluteValue); } -[[nodiscard]] QString FormatF(float64 absoluteValue) { - constexpr auto kTooMuch = int(10'000); - return (absoluteValue >= kTooMuch) - ? Lang::FormatCountToShort(absoluteValue).string - : QString::number(absoluteValue); -} - } // namespace ChartRulersData::ChartRulersData( @@ -42,7 +35,8 @@ ChartRulersData::ChartRulersData( int newMinHeight, bool useMinHeight, float64 rightRatio, - int valueDivider) { + Fn leftCustomCaption, + Fn rightCustomCaption) { if (!useMinHeight) { const auto v = (newMaxHeight > 100) ? Round(newMaxHeight) @@ -100,12 +94,14 @@ ChartRulersData::ChartRulersData( const auto value = int(i * step); line.absoluteValue = newMinHeight + value; line.relativeValue = 1. - value / float64(diffAbsoluteValue); - line.caption = valueDivider - ? FormatF(line.absoluteValue / float64(valueDivider)) + line.caption = leftCustomCaption + ? leftCustomCaption(line.absoluteValue) : Format(line.absoluteValue); - if (rightRatio > 0) { + if (rightRatio > 0 || rightCustomCaption) { const auto v = (newMinHeight + i * step) / rightRatio; - line.scaledLineCaption = (!skipFloatValues) + line.scaledLineCaption = rightCustomCaption + ? rightCustomCaption(line.absoluteValue) + : (!skipFloatValues) ? Format(v) : ((v - int(v)) < 0.01) ? Format(v) diff --git a/Telegram/SourceFiles/statistics/chart_rulers_data.h b/Telegram/SourceFiles/statistics/chart_rulers_data.h index 4df719ac0..4b5d63202 100644 --- a/Telegram/SourceFiles/statistics/chart_rulers_data.h +++ b/Telegram/SourceFiles/statistics/chart_rulers_data.h @@ -16,7 +16,8 @@ public: int newMinHeight, bool useMinHeight, float64 rightRatio, - int valueDivider); + Fn leftCustomCaption = nullptr, + Fn rightCustomCaption = nullptr); void computeRelative( int newMaxHeight, diff --git a/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp b/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp index df7345d75..e6368052e 100644 --- a/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp +++ b/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp @@ -132,13 +132,6 @@ Data::StatisticalChart StatisticalChartFromJSON(const QByteArray &json) { result.weekFormat = tooltipFormat.contains(u"'week'"_q); } } - { - const auto tickFormatIt = root.constFind(u"yTickFormatter"_q); - if (tickFormatIt != root.constEnd()) { - const auto tickFormat = tickFormatIt->toString(); - result.isCurrency = tickFormat.contains(u"TON"_q); - } - } const auto colors = root.value(u"colors"_q).toObject(); const auto names = root.value(u"names"_q).toObject(); diff --git a/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp b/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp index 859db9e1a..334f0eead 100644 --- a/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp +++ b/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp @@ -8,12 +8,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "statistics/view/chart_rulers_view.h" #include "data/data_channel_earn.h" // Data::kEarnMultiplier. +#include "info/channel_statistics/earn/earn_format.h" +#include "lang/lang_keys.h" #include "statistics/chart_lines_filter_controller.h" #include "statistics/statistics_common.h" #include "styles/style_basic.h" #include "styles/style_statistics.h" namespace Statistic { +namespace { + +[[nodiscard]] QString FormatF(float64 absoluteValue) { + constexpr auto kTooMuch = int(10'000); + return (absoluteValue >= kTooMuch) + ? Lang::FormatCountToShort(absoluteValue).string + : QString::number(absoluteValue); +} + +} // namespace ChartRulersView::ChartRulersView() = default; @@ -22,10 +34,18 @@ void ChartRulersView::setChartData( ChartViewType type, std::shared_ptr linesFilter) { _rulers.clear(); - _isDouble = (type == ChartViewType::DoubleLinear); - _currencyIcon = chartData.isCurrency - ? &st::statisticsCurrencyIcon - : nullptr; + _isDouble = (type == ChartViewType::DoubleLinear) + || chartData.currencyRate; + if (chartData.currencyRate) { + _currencyIcon = &st::statisticsCurrencyIcon; + _leftCustomCaption = [=](float64 value) { + return FormatF(value / float64(Data::kEarnMultiplier)); + }; + _rightCustomCaption = [=, rate = chartData.currencyRate](float64 v) { + return Info::ChannelEarn::ToUsd(v, rate).mid(1); + }; + _rightPen = QPen(st::windowSubTextFg); + } if (_isDouble && (chartData.lines.size() == 2)) { _linesFilter = std::move(linesFilter); _leftPen = QPen(chartData.lines.front().color); @@ -96,8 +116,10 @@ void ChartRulersView::paintCaptionsToRulers( : _isLeftLineScaled ? line.scaledLineCaption : line.caption); - if (hasLinesFilter) { - p.setOpacity(rulerAlpha * _linesFilter->alpha(_rightLineId)); + if (hasLinesFilter || _rightCustomCaption) { + if (_linesFilter) { + p.setOpacity(rulerAlpha * _linesFilter->alpha(_rightLineId)); + } p.setPen(_rightPen); p.drawText( r.width() - line.rightCaptionWidth, @@ -142,7 +164,8 @@ void ChartRulersView::add(Limits newHeight, bool animated) { newHeight.min, true, _isDouble ? _scaledLineRatio : 0., - _currencyIcon ? Data::kEarnMultiplier : 0); + _leftCustomCaption, + _rightCustomCaption); if (_isDouble) { const auto &font = st::statisticsDetailsBottomCaptionStyle.font; for (auto &line : newLinesData.lines) { diff --git a/Telegram/SourceFiles/statistics/view/chart_rulers_view.h b/Telegram/SourceFiles/statistics/view/chart_rulers_view.h index ba355fd50..44326d15e 100644 --- a/Telegram/SourceFiles/statistics/view/chart_rulers_view.h +++ b/Telegram/SourceFiles/statistics/view/chart_rulers_view.h @@ -44,6 +44,9 @@ private: int _rightLineId = 0; const style::icon *_currencyIcon = nullptr; + Fn _leftCustomCaption = nullptr; + Fn _rightCustomCaption = nullptr; + std::vector _rulers; std::shared_ptr _linesFilter; diff --git a/Telegram/SourceFiles/statistics/widgets/point_details_widget.cpp b/Telegram/SourceFiles/statistics/widgets/point_details_widget.cpp index d30cfa7d6..4bd871ffa 100644 --- a/Telegram/SourceFiles/statistics/widgets/point_details_widget.cpp +++ b/Telegram/SourceFiles/statistics/widgets/point_details_widget.cpp @@ -134,7 +134,7 @@ PointDetailsWidget::PointDetailsWidget( , _chartData(chartData) , _textStyle(st::statisticsDetailsPopupStyle) , _headerStyle(st::statisticsDetailsPopupHeaderStyle) -, _valueIcon(chartData.isCurrency ? &st::statisticsCurrencyIcon : nullptr) { +, _valueIcon(chartData.currencyRate ? &st::statisticsCurrencyIcon : nullptr) { if (zoomEnabled) { rpl::single(rpl::empty_value()) | rpl::then( @@ -282,7 +282,7 @@ void PointDetailsWidget::setXIndex(int xIndex) { textLine.name.setText(_textStyle, dataLine.name); textLine.value.setText( _textStyle, - _chartData.isCurrency + _chartData.currencyRate ? QString::number(dataLine.y[xIndex] / multiplier) : QString("%L1").arg(dataLine.y[xIndex])); hasPositiveValues |= (dataLine.y[xIndex] > 0); diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index e52a53bf4..3cd0defa7 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -131,6 +131,9 @@ PRIVATE info/channel_statistics/boosts/giveaway/select_countries_box.cpp info/channel_statistics/boosts/giveaway/select_countries_box.h + info/channel_statistics/earn/earn_format.cpp + info/channel_statistics/earn/earn_format.h + intro/intro_code_input.cpp intro/intro_code_input.h