mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added second rulers to currency chart in channel earn info section.
This commit is contained in:
parent
1563a85fea
commit
3311a50750
11 changed files with 131 additions and 76 deletions
|
@ -65,7 +65,7 @@ struct StatisticalChart {
|
||||||
bool isFooterHidden = false;
|
bool isFooterHidden = false;
|
||||||
bool hasPercentages = false;
|
bool hasPercentages = false;
|
||||||
bool weekFormat = false;
|
bool weekFormat = false;
|
||||||
bool isCurrency = false;
|
float64 currencyRate = 0.;
|
||||||
|
|
||||||
// View data.
|
// View data.
|
||||||
int dayStringMaxWidth = 0;
|
int dayStringMaxWidth = 0;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -16,12 +16,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_premium_limits.h"
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/stickers/data_custom_emoji.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/channel_statistics/earn/info_earn_widget.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
|
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
|
||||||
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
|
||||||
#include "main/main_app_config.h"
|
#include "main/main_app_config.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "statistics/chart_widget.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/text/text_utilities.h"
|
||||||
#include "ui/vertical_list.h"
|
#include "ui/vertical_list.h"
|
||||||
#include "ui/widgets/fields/input_field.h"
|
#include "ui/widgets/fields/input_field.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_channel_earn.h"
|
#include "styles/style_channel_earn.h"
|
||||||
|
@ -53,50 +54,6 @@ namespace {
|
||||||
|
|
||||||
using EarnInt = Data::EarnInt;
|
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) {
|
[[nodiscard]] bool WithdrawalEnabled(not_null<Main::Session*> session) {
|
||||||
const auto key = u"channel_revenue_withdrawal_enabled"_q;
|
const auto key = u"channel_revenue_withdrawal_enabled"_q;
|
||||||
return session->appConfig().get<bool>(key, false);
|
return session->appConfig().get<bool>(key, false);
|
||||||
|
@ -480,7 +437,10 @@ void InnerWidget::fill() {
|
||||||
object_ptr<Statistic::ChartWidget>(container),
|
object_ptr<Statistic::ChartWidget>(container),
|
||||||
st::statisticsLayerMargins);
|
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());
|
widget->setTitle(tr::lng_channel_earn_chart_revenue());
|
||||||
}
|
}
|
||||||
Ui::AddSkip(container);
|
Ui::AddSkip(container);
|
||||||
|
|
|
@ -28,13 +28,6 @@ constexpr auto kStep = 5.;
|
||||||
: QString::number(absoluteValue);
|
: 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
|
} // namespace
|
||||||
|
|
||||||
ChartRulersData::ChartRulersData(
|
ChartRulersData::ChartRulersData(
|
||||||
|
@ -42,7 +35,8 @@ ChartRulersData::ChartRulersData(
|
||||||
int newMinHeight,
|
int newMinHeight,
|
||||||
bool useMinHeight,
|
bool useMinHeight,
|
||||||
float64 rightRatio,
|
float64 rightRatio,
|
||||||
int valueDivider) {
|
Fn<QString(float64)> leftCustomCaption,
|
||||||
|
Fn<QString(float64)> rightCustomCaption) {
|
||||||
if (!useMinHeight) {
|
if (!useMinHeight) {
|
||||||
const auto v = (newMaxHeight > 100)
|
const auto v = (newMaxHeight > 100)
|
||||||
? Round(newMaxHeight)
|
? Round(newMaxHeight)
|
||||||
|
@ -100,12 +94,14 @@ ChartRulersData::ChartRulersData(
|
||||||
const auto value = int(i * step);
|
const auto value = int(i * step);
|
||||||
line.absoluteValue = newMinHeight + value;
|
line.absoluteValue = newMinHeight + value;
|
||||||
line.relativeValue = 1. - value / float64(diffAbsoluteValue);
|
line.relativeValue = 1. - value / float64(diffAbsoluteValue);
|
||||||
line.caption = valueDivider
|
line.caption = leftCustomCaption
|
||||||
? FormatF(line.absoluteValue / float64(valueDivider))
|
? leftCustomCaption(line.absoluteValue)
|
||||||
: Format(line.absoluteValue);
|
: Format(line.absoluteValue);
|
||||||
if (rightRatio > 0) {
|
if (rightRatio > 0 || rightCustomCaption) {
|
||||||
const auto v = (newMinHeight + i * step) / rightRatio;
|
const auto v = (newMinHeight + i * step) / rightRatio;
|
||||||
line.scaledLineCaption = (!skipFloatValues)
|
line.scaledLineCaption = rightCustomCaption
|
||||||
|
? rightCustomCaption(line.absoluteValue)
|
||||||
|
: (!skipFloatValues)
|
||||||
? Format(v)
|
? Format(v)
|
||||||
: ((v - int(v)) < 0.01)
|
: ((v - int(v)) < 0.01)
|
||||||
? Format(v)
|
? Format(v)
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
int newMinHeight,
|
int newMinHeight,
|
||||||
bool useMinHeight,
|
bool useMinHeight,
|
||||||
float64 rightRatio,
|
float64 rightRatio,
|
||||||
int valueDivider);
|
Fn<QString(float64)> leftCustomCaption = nullptr,
|
||||||
|
Fn<QString(float64)> rightCustomCaption = nullptr);
|
||||||
|
|
||||||
void computeRelative(
|
void computeRelative(
|
||||||
int newMaxHeight,
|
int newMaxHeight,
|
||||||
|
|
|
@ -132,13 +132,6 @@ Data::StatisticalChart StatisticalChartFromJSON(const QByteArray &json) {
|
||||||
result.weekFormat = tooltipFormat.contains(u"'week'"_q);
|
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 colors = root.value(u"colors"_q).toObject();
|
||||||
const auto names = root.value(u"names"_q).toObject();
|
const auto names = root.value(u"names"_q).toObject();
|
||||||
|
|
|
@ -8,12 +8,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "statistics/view/chart_rulers_view.h"
|
#include "statistics/view/chart_rulers_view.h"
|
||||||
|
|
||||||
#include "data/data_channel_earn.h" // Data::kEarnMultiplier.
|
#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/chart_lines_filter_controller.h"
|
||||||
#include "statistics/statistics_common.h"
|
#include "statistics/statistics_common.h"
|
||||||
#include "styles/style_basic.h"
|
#include "styles/style_basic.h"
|
||||||
#include "styles/style_statistics.h"
|
#include "styles/style_statistics.h"
|
||||||
|
|
||||||
namespace Statistic {
|
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;
|
ChartRulersView::ChartRulersView() = default;
|
||||||
|
|
||||||
|
@ -22,10 +34,18 @@ void ChartRulersView::setChartData(
|
||||||
ChartViewType type,
|
ChartViewType type,
|
||||||
std::shared_ptr<LinesFilterController> linesFilter) {
|
std::shared_ptr<LinesFilterController> linesFilter) {
|
||||||
_rulers.clear();
|
_rulers.clear();
|
||||||
_isDouble = (type == ChartViewType::DoubleLinear);
|
_isDouble = (type == ChartViewType::DoubleLinear)
|
||||||
_currencyIcon = chartData.isCurrency
|
|| chartData.currencyRate;
|
||||||
? &st::statisticsCurrencyIcon
|
if (chartData.currencyRate) {
|
||||||
: nullptr;
|
_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)) {
|
if (_isDouble && (chartData.lines.size() == 2)) {
|
||||||
_linesFilter = std::move(linesFilter);
|
_linesFilter = std::move(linesFilter);
|
||||||
_leftPen = QPen(chartData.lines.front().color);
|
_leftPen = QPen(chartData.lines.front().color);
|
||||||
|
@ -96,8 +116,10 @@ void ChartRulersView::paintCaptionsToRulers(
|
||||||
: _isLeftLineScaled
|
: _isLeftLineScaled
|
||||||
? line.scaledLineCaption
|
? line.scaledLineCaption
|
||||||
: line.caption);
|
: line.caption);
|
||||||
if (hasLinesFilter) {
|
if (hasLinesFilter || _rightCustomCaption) {
|
||||||
p.setOpacity(rulerAlpha * _linesFilter->alpha(_rightLineId));
|
if (_linesFilter) {
|
||||||
|
p.setOpacity(rulerAlpha * _linesFilter->alpha(_rightLineId));
|
||||||
|
}
|
||||||
p.setPen(_rightPen);
|
p.setPen(_rightPen);
|
||||||
p.drawText(
|
p.drawText(
|
||||||
r.width() - line.rightCaptionWidth,
|
r.width() - line.rightCaptionWidth,
|
||||||
|
@ -142,7 +164,8 @@ void ChartRulersView::add(Limits newHeight, bool animated) {
|
||||||
newHeight.min,
|
newHeight.min,
|
||||||
true,
|
true,
|
||||||
_isDouble ? _scaledLineRatio : 0.,
|
_isDouble ? _scaledLineRatio : 0.,
|
||||||
_currencyIcon ? Data::kEarnMultiplier : 0);
|
_leftCustomCaption,
|
||||||
|
_rightCustomCaption);
|
||||||
if (_isDouble) {
|
if (_isDouble) {
|
||||||
const auto &font = st::statisticsDetailsBottomCaptionStyle.font;
|
const auto &font = st::statisticsDetailsBottomCaptionStyle.font;
|
||||||
for (auto &line : newLinesData.lines) {
|
for (auto &line : newLinesData.lines) {
|
||||||
|
|
|
@ -44,6 +44,9 @@ private:
|
||||||
int _rightLineId = 0;
|
int _rightLineId = 0;
|
||||||
const style::icon *_currencyIcon = nullptr;
|
const style::icon *_currencyIcon = nullptr;
|
||||||
|
|
||||||
|
Fn<QString(float64)> _leftCustomCaption = nullptr;
|
||||||
|
Fn<QString(float64)> _rightCustomCaption = nullptr;
|
||||||
|
|
||||||
std::vector<ChartRulersData> _rulers;
|
std::vector<ChartRulersData> _rulers;
|
||||||
|
|
||||||
std::shared_ptr<LinesFilterController> _linesFilter;
|
std::shared_ptr<LinesFilterController> _linesFilter;
|
||||||
|
|
|
@ -134,7 +134,7 @@ PointDetailsWidget::PointDetailsWidget(
|
||||||
, _chartData(chartData)
|
, _chartData(chartData)
|
||||||
, _textStyle(st::statisticsDetailsPopupStyle)
|
, _textStyle(st::statisticsDetailsPopupStyle)
|
||||||
, _headerStyle(st::statisticsDetailsPopupHeaderStyle)
|
, _headerStyle(st::statisticsDetailsPopupHeaderStyle)
|
||||||
, _valueIcon(chartData.isCurrency ? &st::statisticsCurrencyIcon : nullptr) {
|
, _valueIcon(chartData.currencyRate ? &st::statisticsCurrencyIcon : nullptr) {
|
||||||
|
|
||||||
if (zoomEnabled) {
|
if (zoomEnabled) {
|
||||||
rpl::single(rpl::empty_value()) | rpl::then(
|
rpl::single(rpl::empty_value()) | rpl::then(
|
||||||
|
@ -282,7 +282,7 @@ void PointDetailsWidget::setXIndex(int xIndex) {
|
||||||
textLine.name.setText(_textStyle, dataLine.name);
|
textLine.name.setText(_textStyle, dataLine.name);
|
||||||
textLine.value.setText(
|
textLine.value.setText(
|
||||||
_textStyle,
|
_textStyle,
|
||||||
_chartData.isCurrency
|
_chartData.currencyRate
|
||||||
? QString::number(dataLine.y[xIndex] / multiplier)
|
? QString::number(dataLine.y[xIndex] / multiplier)
|
||||||
: QString("%L1").arg(dataLine.y[xIndex]));
|
: QString("%L1").arg(dataLine.y[xIndex]));
|
||||||
hasPositiveValues |= (dataLine.y[xIndex] > 0);
|
hasPositiveValues |= (dataLine.y[xIndex] > 0);
|
||||||
|
|
|
@ -131,6 +131,9 @@ PRIVATE
|
||||||
info/channel_statistics/boosts/giveaway/select_countries_box.cpp
|
info/channel_statistics/boosts/giveaway/select_countries_box.cpp
|
||||||
info/channel_statistics/boosts/giveaway/select_countries_box.h
|
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.cpp
|
||||||
intro/intro_code_input.h
|
intro/intro_code_input.h
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue