Added initial support of statistical charts in earn channel section.

This commit is contained in:
23rd 2024-03-26 05:49:31 +03:00 committed by John Preston
parent 393d9e9f1f
commit 9c52f245ac
14 changed files with 84 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

View file

@ -4988,6 +4988,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_earn_learn_coin_title" = "What is {emoji} TON?";
"lng_channel_earn_learn_coin_about" = "TON is a blockchain platform and cryptocurrency that Telegram uses for its record scalability and ultra low commissions on transactions. {link}";
"lng_channel_earn_learn_close" = "Got it";
"lng_channel_earn_chart_top_hours" = "Ad impressions";
"lng_channel_earn_chart_revenue" = "Ad revenue";
"lng_contact_add" = "Add";
"lng_contact_send_message" = "message";

View file

@ -65,6 +65,7 @@ struct StatisticalChart {
bool isFooterHidden = false;
bool hasPercentages = false;
bool weekFormat = false;
bool isCurrency = false;
// View data.
int dayStringMaxWidth = 0;

View file

@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "statistics/chart_widget.h"
#include "ui/controls/userpic_button.h"
#include "ui/effects/animation_value_f.h"
#include "ui/layers/generic_box.h"
@ -223,6 +224,33 @@ void InnerWidget::fill() {
makeContext(label));
};
{
using Type = Statistic::ChartViewType;
Ui::AddSkip(container);
Ui::AddSkip(container);
if (data.topHoursGraph.chart) {
const auto widget = container->add(
object_ptr<Statistic::ChartWidget>(container),
st::statisticsLayerMargins);
widget->setChartData(data.topHoursGraph.chart, Type::Linear);
widget->setTitle(tr::lng_channel_earn_chart_top_hours());
}
if (data.revenueGraph.chart) {
Ui::AddSkip(container);
Ui::AddDivider(container);
Ui::AddSkip(container);
Ui::AddSkip(container);
const auto widget = container->add(
object_ptr<Statistic::ChartWidget>(container),
st::statisticsLayerMargins);
widget->setChartData(data.revenueGraph.chart, Type::StackBar);
widget->setTitle(tr::lng_channel_earn_chart_revenue());
}
Ui::AddSkip(container);
}
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,

View file

@ -28,13 +28,21 @@ 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(
int newMaxHeight,
int newMinHeight,
bool useMinHeight,
float64 rightRatio) {
float64 rightRatio,
int valueDivider) {
if (!useMinHeight) {
const auto v = (newMaxHeight > 100)
? Round(newMaxHeight)
@ -92,7 +100,9 @@ ChartRulersData::ChartRulersData(
const auto value = int(i * step);
line.absoluteValue = newMinHeight + value;
line.relativeValue = 1. - value / float64(diffAbsoluteValue);
line.caption = Format(line.absoluteValue);
line.caption = valueDivider
? FormatF(line.absoluteValue / float64(valueDivider))
: Format(line.absoluteValue);
if (rightRatio > 0) {
const auto v = (newMinHeight + i * step) / rightRatio;
line.scaledLineCaption = (!skipFloatValues)

View file

@ -15,7 +15,8 @@ public:
int newMaxHeight,
int newMinHeight,
bool useMinHeight,
float64 rightRatio);
float64 rightRatio,
int valueDivider);
void computeRelative(
int newMaxHeight,

View file

@ -172,3 +172,5 @@ boostsListGiftMiniIcon: icon{{ "boosts/mini_gift", historyPeer8UserpicBg2 }};
boostsListGiveawayMiniIcon: icon{{ "boosts/mini_giveaway", historyPeer4UserpicBg2 }};
boostsListUnclaimedIcon: icon{{ "boosts/boost_unknown", premiumButtonFg }};
boostsListUnknownIcon: icon{{ "boosts/boost_unclaimed", premiumButtonFg }};
statisticsCurrencyIcon: icon {{ "statistics/mini_currency_graph", windowSubTextFg }};

View file

@ -61,7 +61,7 @@ Data::StatisticalChart StatisticalChartFromJSON(const QByteArray &json) {
line.isHiddenOnStart = ranges::contains(hiddenLines, columnId);
line.y.resize(length);
for (auto i = 0; i < length; i++) {
const auto value = array.at(i + 1).toInt();
const auto value = array.at(i + 1).toInteger();
line.y[i] = value;
if (value > line.maxValue) {
line.maxValue = value;
@ -132,6 +132,13 @@ 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

@ -23,6 +23,9 @@ void ChartRulersView::setChartData(
std::shared_ptr<LinesFilterController> linesFilter) {
_rulers.clear();
_isDouble = (type == ChartViewType::DoubleLinear);
_currencyIcon = chartData.isCurrency
? &st::statisticsCurrencyIcon
: nullptr;
if (_isDouble && (chartData.lines.size() == 2)) {
_linesFilter = std::move(linesFilter);
_leftPen = QPen(chartData.lines.front().color);
@ -69,6 +72,7 @@ void ChartRulersView::paintCaptionsToRulers(
for (auto &ruler : _rulers) {
const auto rulerAlpha = alpha * ruler.alpha;
p.setOpacity(rulerAlpha);
const auto left = _currencyIcon ? _currencyIcon->width() : 0;
for (const auto &line : ruler.lines) {
const auto y = offset + r.height() * line.relativeValue;
const auto hasLinesFilter = _isDouble && _linesFilter;
@ -78,8 +82,14 @@ void ChartRulersView::paintCaptionsToRulers(
} else {
p.setPen(st::windowSubTextFg);
}
if (_currencyIcon) {
const auto iconTop = y
- _currencyIcon->height()
+ st::statisticsChartRulerCaptionSkip;
_currencyIcon->paint(p, 0, iconTop, r.width());
}
p.drawText(
0,
left,
y,
(!_isDouble)
? line.caption
@ -131,7 +141,8 @@ void ChartRulersView::add(Limits newHeight, bool animated) {
newHeight.max,
newHeight.min,
true,
_isDouble ? _scaledLineRatio : 0.);
_isDouble ? _scaledLineRatio : 0.,
_currencyIcon ? 1000000000 : 0);
if (_isDouble) {
const auto &font = st::statisticsDetailsBottomCaptionStyle.font;
for (auto &line : newLinesData.lines) {

View file

@ -42,6 +42,7 @@ private:
QPen _rightPen;
int _leftLineId = 0;
int _rightLineId = 0;
const style::icon *_currencyIcon = nullptr;
std::vector<ChartRulersData> _rulers;

View file

@ -132,7 +132,8 @@ PointDetailsWidget::PointDetailsWidget(
, _zoomEnabled(zoomEnabled)
, _chartData(chartData)
, _textStyle(st::statisticsDetailsPopupStyle)
, _headerStyle(st::statisticsDetailsPopupHeaderStyle) {
, _headerStyle(st::statisticsDetailsPopupHeaderStyle)
, _valueIcon(chartData.isCurrency ? &st::statisticsCurrencyIcon : nullptr) {
if (zoomEnabled) {
rpl::single(rpl::empty_value()) | rpl::then(
@ -201,6 +202,7 @@ PointDetailsWidget::PointDetailsWidget(
+ rect::m::sum::h(st::statisticsDetailsPopupPadding)
+ st::statisticsDetailsPopupPadding.left() // Between strings.
+ maxNameTextWidth
+ (_valueIcon ? _valueIcon->width() : 0)
+ _maxPercentageWidth;
}();
sizeValue(
@ -278,7 +280,9 @@ void PointDetailsWidget::setXIndex(int xIndex) {
textLine.name.setText(_textStyle, dataLine.name);
textLine.value.setText(
_textStyle,
QString("%L1").arg(dataLine.y[xIndex]));
_chartData.isCurrency
? QString::number(dataLine.y[xIndex] / float64(1000000000))
: QString("%L1").arg(dataLine.y[xIndex]));
hasPositiveValues |= (dataLine.y[xIndex] > 0);
textLine.valueColor = QColor(dataLine.color);
_lines.push_back(std::move(textLine));
@ -381,6 +385,14 @@ void PointDetailsWidget::paintEvent(QPaintEvent *e) {
.outerWidth = _textRect.width(),
.availableWidth = valueWidth,
};
if (_valueIcon) {
_valueIcon->paint(
p,
valueContext.position.x() - _valueIcon->width(),
lineY,
valueContext.outerWidth,
line.valueColor);
}
const auto nameContext = Ui::Text::PaintContext{
.position = QPoint(
_textRect.x() + _maxPercentageWidth,

View file

@ -47,6 +47,7 @@ private:
const style::TextStyle &_textStyle;
const style::TextStyle &_headerStyle;
Ui::Text::String _header;
const style::icon *_valueIcon = nullptr;
void invalidateCache();