Added second rulers to currency chart in channel earn info section.

This commit is contained in:
23rd 2024-03-28 06:40:16 +03:00 committed by John Preston
parent 1563a85fea
commit 3311a50750
11 changed files with 131 additions and 76 deletions

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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<Main::Session*> session) {
const auto key = u"channel_revenue_withdrawal_enabled"_q;
return session->appConfig().get<bool>(key, false);
@ -480,7 +437,10 @@ void InnerWidget::fill() {
object_ptr<Statistic::ChartWidget>(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);

View file

@ -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<QString(float64)> leftCustomCaption,
Fn<QString(float64)> 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)

View file

@ -16,7 +16,8 @@ public:
int newMinHeight,
bool useMinHeight,
float64 rightRatio,
int valueDivider);
Fn<QString(float64)> leftCustomCaption = nullptr,
Fn<QString(float64)> rightCustomCaption = nullptr);
void computeRelative(
int newMaxHeight,

View file

@ -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();

View file

@ -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<LinesFilterController> 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) {

View file

@ -44,6 +44,9 @@ private:
int _rightLineId = 0;
const style::icon *_currencyIcon = nullptr;
Fn<QString(float64)> _leftCustomCaption = nullptr;
Fn<QString(float64)> _rightCustomCaption = nullptr;
std::vector<ChartRulersData> _rulers;
std::shared_ptr<LinesFilterController> _linesFilter;

View file

@ -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);

View file

@ -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