mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Added all chart widgets for statistic of channels.
This commit is contained in:
parent
a3fd4f3fac
commit
df53ddf837
4 changed files with 181 additions and 106 deletions
|
@ -871,14 +871,17 @@ int ChartWidget::resizeGetHeight(int newWidth) {
|
|||
|
||||
_filterButtons->fillButtons(texts, colors, ids, newWidth);
|
||||
}
|
||||
const auto filtersTopSkip = st::statisticsFilterButtonsPadding.top();
|
||||
const auto filtersHeight = _filterButtons
|
||||
? _filterButtons->height()
|
||||
? (_filterButtons->height()
|
||||
+ st::statisticsFilterButtonsPadding.bottom())
|
||||
: 0;
|
||||
const auto resultHeight = st::statisticsChartHeight
|
||||
const auto resultHeight = st::statisticsChartHeaderHeight
|
||||
+ st::statisticsChartHeight
|
||||
+ st::statisticsChartFooterHeight
|
||||
+ st::statisticsChartFooterSkip
|
||||
+ filtersHeight
|
||||
+ st::statisticsChartHeaderHeight;
|
||||
+ filtersTopSkip
|
||||
+ filtersHeight;
|
||||
{
|
||||
_header->setGeometry(
|
||||
0,
|
||||
|
@ -887,7 +890,10 @@ int ChartWidget::resizeGetHeight(int newWidth) {
|
|||
st::statisticsChartHeaderHeight);
|
||||
_footer->setGeometry(
|
||||
0,
|
||||
resultHeight - st::statisticsChartFooterHeight - filtersHeight,
|
||||
resultHeight
|
||||
- st::statisticsChartFooterHeight
|
||||
- filtersTopSkip
|
||||
- filtersHeight,
|
||||
newWidth,
|
||||
st::statisticsChartFooterHeight);
|
||||
if (_filterButtons) {
|
||||
|
@ -899,6 +905,7 @@ int ChartWidget::resizeGetHeight(int newWidth) {
|
|||
newWidth,
|
||||
resultHeight
|
||||
- st::statisticsChartFooterHeight
|
||||
- filtersTopSkip
|
||||
- filtersHeight
|
||||
- st::statisticsChartFooterSkip);
|
||||
|
||||
|
@ -1403,6 +1410,16 @@ void ChartWidget::setupFilterButtons() {
|
|||
void ChartWidget::setChartData(
|
||||
Data::StatisticalChart chartData,
|
||||
ChartViewType type) {
|
||||
if (width() < st::statisticsChartHeight) {
|
||||
sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
if (s.width() > st::statisticsChartHeight) {
|
||||
setChartData(chartData, type);
|
||||
_waitingSizeLifetime.destroy();
|
||||
}
|
||||
}, _waitingSizeLifetime);
|
||||
return;
|
||||
}
|
||||
_chartData = std::move(chartData);
|
||||
FillLineColorsByKey(_chartData);
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ private:
|
|||
bool _zoomEnabled = false;
|
||||
rpl::event_stream<float64> _zoomRequests;
|
||||
|
||||
rpl::lifetime _waitingSizeLifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Statistic
|
||||
|
|
|
@ -12,6 +12,8 @@ using "ui/widgets/widgets.style";
|
|||
|
||||
statisticsChartHeight: 150px;
|
||||
|
||||
statisticsChartEntryPadding: margins(0px, 8px, 0px, 8px);
|
||||
|
||||
statisticsDetailsArrowShift: 2px;
|
||||
statisticsDetailsArrowStroke: 1.5;
|
||||
statisticsDetailsPopupMargins: margins(8px, 8px, 8px, 8px);
|
||||
|
@ -37,6 +39,8 @@ statisticsChartFooterHeight: 52px;
|
|||
statisticsChartFlatCheckboxMargins: margins(4px, 4px, 4px, 4px);
|
||||
statisticsChartFlatCheckboxCheckWidth: 4px;
|
||||
|
||||
statisticsFilterButtonsPadding: margins(0px, 6px, 0px, 0px);
|
||||
|
||||
statisticsDetailsPopupHeaderStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(9px semibold);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,149 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace {
|
||||
|
||||
struct Descriptor final {
|
||||
not_null<PeerData*> peer;
|
||||
not_null<Api::Statistics*> api;
|
||||
not_null<QWidget*> toastParent;
|
||||
};
|
||||
|
||||
void ProcessZoom(
|
||||
const Descriptor &d,
|
||||
not_null<Statistic::ChartWidget*> widget,
|
||||
const QString &zoomToken,
|
||||
Statistic::ChartViewType type) {
|
||||
if (zoomToken.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
widget->zoomRequests(
|
||||
) | rpl::start_with_next([=](float64 x) {
|
||||
d.api->requestZoom(
|
||||
d.peer,
|
||||
zoomToken,
|
||||
x
|
||||
) | rpl::start_with_next_error_done([=](
|
||||
const Data::StatisticalGraph &graph) {
|
||||
if (graph.chart) {
|
||||
widget->setZoomedChartData(graph.chart, x, type);
|
||||
} else if (!graph.error.isEmpty()) {
|
||||
Ui::Toast::Show(d.toastParent, graph.error);
|
||||
}
|
||||
}, [=](const QString &error) {
|
||||
}, [=] {
|
||||
}, widget->lifetime());
|
||||
}, widget->lifetime());
|
||||
}
|
||||
|
||||
void ProcessChart(
|
||||
const Descriptor &d,
|
||||
not_null<Statistic::ChartWidget*> widget,
|
||||
const Data::StatisticalGraph &graphData,
|
||||
rpl::producer<QString> &&title,
|
||||
Statistic::ChartViewType type) {
|
||||
if (graphData.chart) {
|
||||
widget->setChartData(graphData.chart, type);
|
||||
ProcessZoom(d, widget, graphData.zoomToken, type);
|
||||
widget->setTitle(std::move(title));
|
||||
} else if (!graphData.zoomToken.isEmpty()) {
|
||||
d.api->requestZoom(
|
||||
d.peer,
|
||||
graphData.zoomToken,
|
||||
0
|
||||
) | rpl::start_with_next_error_done([=](
|
||||
const Data::StatisticalGraph &graph) {
|
||||
if (graph.chart) {
|
||||
widget->setChartData(graph.chart, type);
|
||||
ProcessZoom(d, widget, graph.zoomToken, type);
|
||||
widget->setTitle(rpl::duplicate(title));
|
||||
} else if (!graph.error.isEmpty()) {
|
||||
Ui::Toast::Show(d.toastParent, graph.error);
|
||||
}
|
||||
}, [=](const QString &error) {
|
||||
}, [=] {
|
||||
}, widget->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void FillChannelStatistic(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
const Descriptor &descriptor,
|
||||
const Data::ChannelStatistics &stats) {
|
||||
using Type = Statistic::ChartViewType;
|
||||
const auto &padding = st::statisticsChartEntryPadding;
|
||||
const auto addSkip = [&] {
|
||||
Settings::AddSkip(box->verticalLayout(), padding.bottom());
|
||||
Settings::AddDivider(box->verticalLayout());
|
||||
Settings::AddSkip(box->verticalLayout(), padding.top());
|
||||
};
|
||||
Settings::AddSkip(box->verticalLayout(), padding.top());
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.memberCountGraph,
|
||||
tr::lng_chart_title_member_count(),
|
||||
Type::Linear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.joinGraph,
|
||||
tr::lng_chart_title_join(),
|
||||
Type::Linear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.muteGraph,
|
||||
tr::lng_chart_title_mute(),
|
||||
Type::Linear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.viewCountByHourGraph,
|
||||
tr::lng_chart_title_view_count_by_hour(),
|
||||
Type::Linear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.viewCountBySourceGraph,
|
||||
tr::lng_chart_title_view_count_by_source(),
|
||||
Type::Stack);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.joinBySourceGraph,
|
||||
tr::lng_chart_title_join_by_source(),
|
||||
Type::Stack);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.languageGraph,
|
||||
tr::lng_chart_title_language(),
|
||||
Type::StackLinear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.messageInteractionGraph,
|
||||
tr::lng_chart_title_message_interaction(),
|
||||
Type::DoubleLinear);
|
||||
addSkip();
|
||||
ProcessChart(
|
||||
descriptor,
|
||||
box->addRow(object_ptr<Statistic::ChartWidget>(box)),
|
||||
stats.instantViewInteractionGraph,
|
||||
tr::lng_chart_title_instant_view_interaction(),
|
||||
Type::DoubleLinear);
|
||||
addSkip();
|
||||
|
||||
box->verticalLayout()->resizeToWidth(box->width());
|
||||
box->showChildren();
|
||||
}
|
||||
|
||||
void FillLoading(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
rpl::producer<bool> toggleOn) {
|
||||
|
@ -69,117 +212,26 @@ void FillLoading(
|
|||
} // namespace
|
||||
|
||||
void StatisticsBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
||||
|
||||
box->setTitle(tr::lng_stats_title());
|
||||
const auto loaded = box->lifetime().make_state<rpl::event_stream<bool>>();
|
||||
FillLoading(
|
||||
box,
|
||||
loaded->events_starting_with(false) | rpl::map(!rpl::mappers::_1));
|
||||
|
||||
const auto chartWidget = box->addRow(
|
||||
object_ptr<Statistic::ChartWidget>(box));
|
||||
const auto chartWidget2 = box->addRow(
|
||||
object_ptr<Statistic::ChartWidget>(box));
|
||||
const auto chartWidget3 = box->addRow(
|
||||
object_ptr<Statistic::ChartWidget>(box));
|
||||
const auto chartWidget4 = box->addRow(
|
||||
object_ptr<Statistic::ChartWidget>(box));
|
||||
const auto chartWidget5 = box->addRow(
|
||||
object_ptr<Statistic::ChartWidget>(box));
|
||||
const auto api = chartWidget->lifetime().make_state<Api::Statistics>(
|
||||
&peer->session().api());
|
||||
|
||||
const auto processZoom = [=](
|
||||
not_null<Statistic::ChartWidget*> widget,
|
||||
const QString &zoomToken,
|
||||
Statistic::ChartViewType type) {
|
||||
if (!zoomToken.isEmpty()) {
|
||||
widget->zoomRequests(
|
||||
) | rpl::start_with_next([=](float64 x) {
|
||||
api->requestZoom(
|
||||
peer,
|
||||
zoomToken,
|
||||
x
|
||||
) | rpl::start_with_next_error_done([=](
|
||||
const Data::StatisticalGraph &graph) {
|
||||
if (graph.chart) {
|
||||
widget->setZoomedChartData(graph.chart, x, type);
|
||||
} else if (!graph.error.isEmpty()) {
|
||||
Ui::Toast::Show(
|
||||
box->uiShow()->toastParent(),
|
||||
graph.error);
|
||||
}
|
||||
}, [=](const QString &error) {
|
||||
}, [=] {
|
||||
}, widget->lifetime());
|
||||
}, widget->lifetime());
|
||||
}
|
||||
const auto descriptor = Descriptor{
|
||||
peer,
|
||||
box->lifetime().make_state<Api::Statistics>(&peer->session().api()),
|
||||
box->uiShow()->toastParent(),
|
||||
};
|
||||
|
||||
const auto processChart = [=](
|
||||
not_null<Statistic::ChartWidget*> widget,
|
||||
const Data::StatisticalGraph &graphData,
|
||||
rpl::producer<QString> &&title,
|
||||
Statistic::ChartViewType type) {
|
||||
if (graphData.chart) {
|
||||
widget->setChartData(graphData.chart, type);
|
||||
processZoom(widget, graphData.zoomToken, type);
|
||||
widget->setTitle(std::move(title));
|
||||
} else if (!graphData.zoomToken.isEmpty()) {
|
||||
api->requestZoom(
|
||||
peer,
|
||||
graphData.zoomToken,
|
||||
0
|
||||
) | rpl::start_with_next_error_done([=](
|
||||
const Data::StatisticalGraph &graph) {
|
||||
if (graph.chart) {
|
||||
widget->setChartData(graph.chart, type);
|
||||
processZoom(widget, graph.zoomToken, type);
|
||||
widget->setTitle(rpl::duplicate(title));
|
||||
} else if (!graph.error.isEmpty()) {
|
||||
Ui::Toast::Show(
|
||||
box->uiShow()->toastParent(),
|
||||
graph.error);
|
||||
}
|
||||
}, [=](const QString &error) {
|
||||
}, [=] {
|
||||
}, widget->lifetime());
|
||||
}
|
||||
};
|
||||
|
||||
api->request(
|
||||
peer
|
||||
descriptor.api->request(
|
||||
descriptor.peer
|
||||
) | rpl::start_with_done([=] {
|
||||
const auto stats = api->channelStats();
|
||||
const auto stats = descriptor.api->channelStats();
|
||||
if (!stats) {
|
||||
return;
|
||||
}
|
||||
FillChannelStatistic(box, descriptor, stats);
|
||||
loaded->fire(true);
|
||||
using Type = Statistic::ChartViewType;
|
||||
processChart(
|
||||
chartWidget,
|
||||
stats.memberCountGraph,
|
||||
tr::lng_chart_title_member_count(),
|
||||
Type::Linear);
|
||||
processChart(
|
||||
chartWidget2,
|
||||
stats.joinGraph,
|
||||
tr::lng_chart_title_join(),
|
||||
Type::Linear);
|
||||
processChart(
|
||||
chartWidget3,
|
||||
stats.muteGraph,
|
||||
tr::lng_chart_title_mute(),
|
||||
Type::Linear);
|
||||
processChart(
|
||||
chartWidget4,
|
||||
stats.viewCountBySourceGraph,
|
||||
tr::lng_chart_title_view_count_by_source(),
|
||||
Type::Stack);
|
||||
processChart(
|
||||
chartWidget5,
|
||||
stats.joinBySourceGraph,
|
||||
tr::lng_chart_title_join_by_source(),
|
||||
Type::Stack);
|
||||
}, chartWidget->lifetime());
|
||||
box->setTitle(tr::lng_stats_title());
|
||||
}, box->lifetime());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue