mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added overview info to statistic for single message.
This commit is contained in:
parent
8497b83f7c
commit
9c1ef76e49
4 changed files with 118 additions and 47 deletions
|
@ -4079,6 +4079,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_stats_overview_group_mean_post_count" = "Posting Members";
|
"lng_stats_overview_group_mean_post_count" = "Posting Members";
|
||||||
"lng_stats_overview_message_private_shares" = "Private Shares";
|
"lng_stats_overview_message_private_shares" = "Private Shares";
|
||||||
"lng_stats_overview_message_public_shares" = "Public Shares";
|
"lng_stats_overview_message_public_shares" = "Public Shares";
|
||||||
|
"lng_stats_overview_message_views" = "Views";
|
||||||
"lng_stats_overview_message_public_share#one" = "{count} public share";
|
"lng_stats_overview_message_public_share#one" = "{count} public share";
|
||||||
"lng_stats_overview_message_public_share#other" = "{count} public shares";
|
"lng_stats_overview_message_public_share#other" = "{count} public shares";
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "settings/settings_common.h"
|
#include "settings/settings_common.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
|
@ -151,13 +150,13 @@ rpl::producer<int> PublicForwardsController::totalCountChanges() const {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void AddPublicForwards(
|
PublicShares AddPublicForwards(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
Fn<void(FullMsgId)> showPeerHistory,
|
Fn<void(FullMsgId)> showPeerHistory,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
FullMsgId contextId) {
|
FullMsgId contextId) {
|
||||||
if (!peer->isChannel()) {
|
if (!peer->isChannel()) {
|
||||||
return;
|
return rpl::never<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State final {
|
struct State final {
|
||||||
|
@ -174,18 +173,9 @@ void AddPublicForwards(
|
||||||
peer,
|
peer,
|
||||||
contextId);
|
contextId);
|
||||||
|
|
||||||
const auto wrap = container->add(
|
|
||||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
|
||||||
container,
|
|
||||||
object_ptr<Ui::VerticalLayout>(container)));
|
|
||||||
wrap->toggle(false, anim::type::instant);
|
|
||||||
|
|
||||||
auto title = state->controller.totalCountChanges(
|
auto title = state->controller.totalCountChanges(
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
) | rpl::map([=](int total) {
|
) | rpl::map([=](int total) {
|
||||||
if (total && !wrap->toggled()) {
|
|
||||||
wrap->toggle(true, anim::type::normal);
|
|
||||||
}
|
|
||||||
return total
|
return total
|
||||||
? tr::lng_stats_overview_message_public_share(
|
? tr::lng_stats_overview_message_public_share(
|
||||||
tr::now,
|
tr::now,
|
||||||
|
@ -197,13 +187,16 @@ void AddPublicForwards(
|
||||||
{
|
{
|
||||||
const auto &subtitlePadding = st::settingsButton.padding;
|
const auto &subtitlePadding = st::settingsButton.padding;
|
||||||
::Settings::AddSubsectionTitle(
|
::Settings::AddSubsectionTitle(
|
||||||
wrap->entity(),
|
container,
|
||||||
std::move(title),
|
std::move(title),
|
||||||
{ 0, -subtitlePadding.top(), 0, -subtitlePadding.bottom() });
|
{ 0, -subtitlePadding.top(), 0, -subtitlePadding.bottom() });
|
||||||
}
|
}
|
||||||
state->delegate.setContent(wrap->entity()->add(
|
state->delegate.setContent(container->add(
|
||||||
object_ptr<PeerListContent>(wrap->entity(), &state->controller)));
|
object_ptr<PeerListContent>(container, &state->controller)));
|
||||||
state->controller.setDelegate(&state->delegate);
|
state->controller.setDelegate(&state->delegate);
|
||||||
|
|
||||||
|
return state->controller.totalCountChanges(
|
||||||
|
) | rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Info::Statistics
|
} // namespace Info::Statistics
|
||||||
|
|
|
@ -15,7 +15,9 @@ class VerticalLayout;
|
||||||
|
|
||||||
namespace Info::Statistics {
|
namespace Info::Statistics {
|
||||||
|
|
||||||
void AddPublicForwards(
|
using PublicShares = rpl::producer<int>;
|
||||||
|
|
||||||
|
[[nodiscard]] PublicShares AddPublicForwards(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
Fn<void(FullMsgId)> showPeerHistory,
|
Fn<void(FullMsgId)> showPeerHistory,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
|
@ -45,7 +45,15 @@ struct Descriptor final {
|
||||||
struct AnyStats final {
|
struct AnyStats final {
|
||||||
Data::ChannelStatistics channel;
|
Data::ChannelStatistics channel;
|
||||||
Data::SupergroupStatistics supergroup;
|
Data::SupergroupStatistics supergroup;
|
||||||
Data::StatisticalGraph message;
|
struct Message {
|
||||||
|
explicit operator bool() const {
|
||||||
|
return !graph.chart.empty();
|
||||||
|
}
|
||||||
|
Data::StatisticalGraph graph;
|
||||||
|
int publicForwards = 0;
|
||||||
|
int privateForwards = 0;
|
||||||
|
int views = 0;
|
||||||
|
} message;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ProcessZoom(
|
void ProcessZoom(
|
||||||
|
@ -211,9 +219,9 @@ void FillStatistic(
|
||||||
// s.weekGraph,
|
// s.weekGraph,
|
||||||
// tr::lng_chart_title_group_week(),
|
// tr::lng_chart_title_group_week(),
|
||||||
// Type::StackLinear);
|
// Type::StackLinear);
|
||||||
} else if (const auto graph = stats.message; graph.chart) {
|
} else if (const auto message = stats.message) {
|
||||||
addChart(
|
addChart(
|
||||||
graph,
|
message.graph,
|
||||||
tr::lng_chart_title_message_interaction(),
|
tr::lng_chart_title_message_interaction(),
|
||||||
Type::DoubleLinear);
|
Type::DoubleLinear);
|
||||||
}
|
}
|
||||||
|
@ -278,6 +286,10 @@ void AddHeader(
|
||||||
st::statisticsLayerMargins + st::statisticsChartHeaderPadding);
|
st::statisticsLayerMargins + st::statisticsChartHeaderPadding);
|
||||||
header->resizeToWidth(header->width());
|
header->resizeToWidth(header->width());
|
||||||
header->setTitle(text(tr::now));
|
header->setTitle(text(tr::now));
|
||||||
|
if (!endDate || !startDate) {
|
||||||
|
header->setSubTitle({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto formatter = u"d MMM yyyy"_q;
|
const auto formatter = u"d MMM yyyy"_q;
|
||||||
const auto from = QDateTime::fromSecsSinceEpoch(startDate);
|
const auto from = QDateTime::fromSecsSinceEpoch(startDate);
|
||||||
const auto to = QDateTime::fromSecsSinceEpoch(endDate);
|
const auto to = QDateTime::fromSecsSinceEpoch(endDate);
|
||||||
|
@ -335,7 +347,9 @@ void FillOverview(
|
||||||
const auto addPrimary = [&](const Value &v) {
|
const auto addPrimary = [&](const Value &v) {
|
||||||
return Ui::CreateChild<Ui::FlatLabel>(
|
return Ui::CreateChild<Ui::FlatLabel>(
|
||||||
container,
|
container,
|
||||||
Lang::FormatCountToShort(v.value).string,
|
(v.value >= 0)
|
||||||
|
? Lang::FormatCountToShort(v.value).string
|
||||||
|
: QString(),
|
||||||
st::statisticsOverviewValue);
|
st::statisticsOverviewValue);
|
||||||
};
|
};
|
||||||
const auto addSub = [&](
|
const auto addSub = [&](
|
||||||
|
@ -352,6 +366,7 @@ void FillOverview(
|
||||||
container,
|
container,
|
||||||
text(),
|
text(),
|
||||||
st::statisticsOverviewSubtext);
|
st::statisticsOverviewSubtext);
|
||||||
|
sub->setTextColorOverride(st::windowSubTextFg->c);
|
||||||
|
|
||||||
primary->geometryValue(
|
primary->geometryValue(
|
||||||
) | rpl::start_with_next([=](const QRect &g) {
|
) | rpl::start_with_next([=](const QRect &g) {
|
||||||
|
@ -369,8 +384,11 @@ void FillOverview(
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto isChannel = (!!channel);
|
const auto isChannel = (!!channel);
|
||||||
|
const auto isMessage = (!!stats.message);
|
||||||
const auto topLeftLabel = isChannel
|
const auto topLeftLabel = isChannel
|
||||||
? addPrimary(channel.memberCount)
|
? addPrimary(channel.memberCount)
|
||||||
|
: isMessage
|
||||||
|
? addPrimary({ .value = float64(stats.message.views) })
|
||||||
: addPrimary(supergroup.memberCount);
|
: addPrimary(supergroup.memberCount);
|
||||||
const auto topRightLabel = isChannel
|
const auto topRightLabel = isChannel
|
||||||
? Ui::CreateChild<Ui::FlatLabel>(
|
? Ui::CreateChild<Ui::FlatLabel>(
|
||||||
|
@ -378,12 +396,18 @@ void FillOverview(
|
||||||
QString("%1%").arg(0.01
|
QString("%1%").arg(0.01
|
||||||
* std::round(channel.enabledNotificationsPercentage * 100.)),
|
* std::round(channel.enabledNotificationsPercentage * 100.)),
|
||||||
st::statisticsOverviewValue)
|
st::statisticsOverviewValue)
|
||||||
|
: isMessage
|
||||||
|
? addPrimary({ .value = float64(stats.message.publicForwards) })
|
||||||
: addPrimary(supergroup.messageCount);
|
: addPrimary(supergroup.messageCount);
|
||||||
const auto bottomLeftLabel = isChannel
|
const auto bottomLeftLabel = isChannel
|
||||||
? addPrimary(channel.meanViewCount)
|
? addPrimary(channel.meanViewCount)
|
||||||
|
: isMessage
|
||||||
|
? addPrimary({ .value = float64(stats.message.privateForwards) })
|
||||||
: addPrimary(supergroup.viewerCount);
|
: addPrimary(supergroup.viewerCount);
|
||||||
const auto bottomRightLabel = isChannel
|
const auto bottomRightLabel = isChannel
|
||||||
? addPrimary(channel.meanShareCount)
|
? addPrimary(channel.meanShareCount)
|
||||||
|
: isMessage
|
||||||
|
? addPrimary({ .value = -1. })
|
||||||
: addPrimary(supergroup.senderCount);
|
: addPrimary(supergroup.senderCount);
|
||||||
if (const auto &s = channel) {
|
if (const auto &s = channel) {
|
||||||
addSub(
|
addSub(
|
||||||
|
@ -419,6 +443,25 @@ void FillOverview(
|
||||||
bottomRightLabel,
|
bottomRightLabel,
|
||||||
s.senderCount,
|
s.senderCount,
|
||||||
tr::lng_stats_overview_group_mean_post_count);
|
tr::lng_stats_overview_group_mean_post_count);
|
||||||
|
} else if (const auto &s = stats.message) {
|
||||||
|
if (s.views >= 0) {
|
||||||
|
addSub(
|
||||||
|
topLeftLabel,
|
||||||
|
{},
|
||||||
|
tr::lng_stats_overview_message_views);
|
||||||
|
}
|
||||||
|
if (s.publicForwards >= 0) {
|
||||||
|
addSub(
|
||||||
|
topRightLabel,
|
||||||
|
{},
|
||||||
|
tr::lng_stats_overview_message_public_shares);
|
||||||
|
}
|
||||||
|
if (s.privateForwards >= 0) {
|
||||||
|
addSub(
|
||||||
|
bottomLeftLabel,
|
||||||
|
{},
|
||||||
|
tr::lng_stats_overview_message_private_shares);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
container->showChildren();
|
container->showChildren();
|
||||||
container->resize(container->width(), topLeftLabel->height() * 5);
|
container->resize(container->width(), topLeftLabel->height() * 5);
|
||||||
|
@ -555,24 +598,7 @@ Widget::Widget(
|
||||||
loaded->events_starting_with(false) | rpl::map(!rpl::mappers::_1),
|
loaded->events_starting_with(false) | rpl::map(!rpl::mappers::_1),
|
||||||
_showFinished.events());
|
_showFinished.events());
|
||||||
|
|
||||||
const auto applyStats = [=](const AnyStats &anyStats) {
|
const auto finishLoading = [=] {
|
||||||
const auto isMessage = !anyStats.message.chart.empty();
|
|
||||||
if (!anyStats.channel && !anyStats.supergroup && !isMessage) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isMessage) {
|
|
||||||
FillOverview(inner, anyStats);
|
|
||||||
FillStatistic(inner, descriptor, anyStats);
|
|
||||||
if (const auto channel = anyStats.channel) {
|
|
||||||
const auto showSection = [controller](
|
|
||||||
std::shared_ptr<Window::SectionMemento> memento) {
|
|
||||||
controller->showSection(std::move(memento));
|
|
||||||
};
|
|
||||||
FillRecentPosts(inner, descriptor, channel, showSection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FillStatistic(inner, descriptor, anyStats);
|
|
||||||
}
|
|
||||||
loaded->fire(true);
|
loaded->fire(true);
|
||||||
inner->resizeToWidth(width());
|
inner->resizeToWidth(width());
|
||||||
inner->showChildren();
|
inner->showChildren();
|
||||||
|
@ -584,22 +610,55 @@ Widget::Widget(
|
||||||
descriptor.api->request(
|
descriptor.api->request(
|
||||||
descriptor.peer
|
descriptor.peer
|
||||||
) | rpl::start_with_done([=] {
|
) | rpl::start_with_done([=] {
|
||||||
applyStats({
|
const auto anyStats = AnyStats{
|
||||||
descriptor.api->channelStats(),
|
descriptor.api->channelStats(),
|
||||||
descriptor.api->supergroupStats(),
|
descriptor.api->supergroupStats(),
|
||||||
});
|
};
|
||||||
|
|
||||||
|
FillOverview(inner, anyStats);
|
||||||
|
FillStatistic(inner, descriptor, anyStats);
|
||||||
|
if (const auto channel = anyStats.channel) {
|
||||||
|
const auto showSection = [controller](
|
||||||
|
std::shared_ptr<Window::SectionMemento> memento) {
|
||||||
|
controller->showSection(std::move(memento));
|
||||||
|
};
|
||||||
|
FillRecentPosts(inner, descriptor, channel, showSection);
|
||||||
|
}
|
||||||
|
finishLoading();
|
||||||
}, inner->lifetime());
|
}, inner->lifetime());
|
||||||
} else {
|
} else {
|
||||||
|
const auto weak = base::make_weak(controller);
|
||||||
|
|
||||||
descriptor.api->requestMessage(
|
descriptor.api->requestMessage(
|
||||||
descriptor.peer,
|
descriptor.peer,
|
||||||
contextId.msg
|
contextId.msg
|
||||||
) | rpl::take(
|
) | rpl::take(
|
||||||
1
|
1
|
||||||
) | rpl::start_with_next([=](const Data::StatisticalGraph &data) {
|
) | rpl::start_with_next([=](const Data::StatisticalGraph &data) {
|
||||||
applyStats({ .message = data });
|
descriptor.api->request(
|
||||||
|
descriptor.peer
|
||||||
|
) | rpl::start_with_done([=] {
|
||||||
|
const auto channel = descriptor.api->channelStats();
|
||||||
|
auto info = Data::StatisticsMessageInteractionInfo();
|
||||||
|
for (const auto &r : channel.recentMessageInteractions) {
|
||||||
|
if (r.messageId == contextId.msg) {
|
||||||
|
info = r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto wrapAbove = inner->add(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
inner,
|
||||||
|
object_ptr<Ui::VerticalLayout>(inner)));
|
||||||
|
wrapAbove->toggle(false, anim::type::instant);
|
||||||
|
|
||||||
|
const auto wrapBelow = inner->add(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
inner,
|
||||||
|
object_ptr<Ui::VerticalLayout>(inner)));
|
||||||
|
wrapBelow->toggle(false, anim::type::instant);
|
||||||
|
|
||||||
{
|
|
||||||
const auto weak = base::make_weak(controller);
|
|
||||||
auto showPeerHistory = [=](FullMsgId fullId) {
|
auto showPeerHistory = [=](FullMsgId fullId) {
|
||||||
if (const auto strong = weak.get()) {
|
if (const auto strong = weak.get()) {
|
||||||
controller->showPeerHistory(
|
controller->showPeerHistory(
|
||||||
|
@ -608,16 +667,32 @@ Widget::Widget(
|
||||||
fullId.msg);
|
fullId.msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
AddPublicForwards(
|
auto sharesCount = AddPublicForwards(
|
||||||
inner,
|
wrapBelow->entity(),
|
||||||
std::move(showPeerHistory),
|
std::move(showPeerHistory),
|
||||||
descriptor.peer,
|
descriptor.peer,
|
||||||
contextId);
|
contextId);
|
||||||
}
|
|
||||||
|
|
||||||
|
std::move(sharesCount) | rpl::take(
|
||||||
|
1
|
||||||
|
) | rpl::start_with_next([=](int count) {
|
||||||
|
const auto stats = AnyStats{
|
||||||
|
.message = {
|
||||||
|
.graph = data,
|
||||||
|
.publicForwards = count,
|
||||||
|
.privateForwards = info.forwardsCount - count,
|
||||||
|
.views = info.viewsCount,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FillOverview(wrapAbove->entity(), stats);
|
||||||
|
FillStatistic(wrapAbove->entity(), descriptor, stats);
|
||||||
|
|
||||||
inner->resizeToWidth(width());
|
wrapAbove->toggle(true, anim::type::instant);
|
||||||
|
wrapBelow->toggle(true, anim::type::instant);
|
||||||
|
|
||||||
|
finishLoading();
|
||||||
|
}, inner->lifetime());
|
||||||
|
}, inner->lifetime());
|
||||||
}, inner->lifetime());
|
}, inner->lifetime());
|
||||||
}
|
}
|
||||||
}, lifetime);
|
}, lifetime);
|
||||||
|
|
Loading…
Add table
Reference in a new issue