mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 07:33:52 +02:00
Added initial ability to save and restore state of statistical info.
This commit is contained in:
parent
caf32cccd3
commit
ec5e846374
5 changed files with 163 additions and 74 deletions
|
@ -113,4 +113,10 @@ struct MessageStatistics final {
|
||||||
int views = 0;
|
int views = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AnyStatistics final {
|
||||||
|
Data::ChannelStatistics channel;
|
||||||
|
Data::SupergroupStatistics supergroup;
|
||||||
|
Data::MessageStatistics message;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/statistics/info_statistics_inner_widget.h"
|
#include "info/statistics/info_statistics_inner_widget.h"
|
||||||
|
|
||||||
|
#include "info/statistics/info_statistics_widget.h"
|
||||||
#include "api/api_statistics.h"
|
#include "api/api_statistics.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
|
@ -42,12 +43,6 @@ struct Descriptor final {
|
||||||
not_null<QWidget*> toastParent;
|
not_null<QWidget*> toastParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnyStats final {
|
|
||||||
Data::ChannelStatistics channel;
|
|
||||||
Data::SupergroupStatistics supergroup;
|
|
||||||
Data::MessageStatistics message;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ProcessZoom(
|
void ProcessZoom(
|
||||||
const Descriptor &d,
|
const Descriptor &d,
|
||||||
not_null<Statistic::ChartWidget*> widget,
|
not_null<Statistic::ChartWidget*> widget,
|
||||||
|
@ -112,7 +107,7 @@ void ProcessChart(
|
||||||
void FillStatistic(
|
void FillStatistic(
|
||||||
not_null<Ui::VerticalLayout*> content,
|
not_null<Ui::VerticalLayout*> content,
|
||||||
const Descriptor &descriptor,
|
const Descriptor &descriptor,
|
||||||
const AnyStats &stats) {
|
const Data::AnyStatistics &stats) {
|
||||||
using Type = Statistic::ChartViewType;
|
using Type = Statistic::ChartViewType;
|
||||||
const auto &padding = st::statisticsChartEntryPadding;
|
const auto &padding = st::statisticsChartEntryPadding;
|
||||||
const auto &m = st::statisticsLayerMargins;
|
const auto &m = st::statisticsLayerMargins;
|
||||||
|
@ -266,7 +261,7 @@ void FillLoading(
|
||||||
void AddHeader(
|
void AddHeader(
|
||||||
not_null<Ui::VerticalLayout*> content,
|
not_null<Ui::VerticalLayout*> content,
|
||||||
tr::phrase<> text,
|
tr::phrase<> text,
|
||||||
const AnyStats &stats) {
|
const Data::AnyStatistics &stats) {
|
||||||
const auto startDate = stats.channel
|
const auto startDate = stats.channel
|
||||||
? stats.channel.startDate
|
? stats.channel.startDate
|
||||||
: stats.supergroup.startDate;
|
: stats.supergroup.startDate;
|
||||||
|
@ -294,7 +289,7 @@ void AddHeader(
|
||||||
|
|
||||||
void FillOverview(
|
void FillOverview(
|
||||||
not_null<Ui::VerticalLayout*> content,
|
not_null<Ui::VerticalLayout*> content,
|
||||||
const AnyStats &stats) {
|
const Data::AnyStatistics &stats) {
|
||||||
using Value = Data::StatisticalValue;
|
using Value = Data::StatisticalValue;
|
||||||
|
|
||||||
const auto &channel = stats.channel;
|
const auto &channel = stats.channel;
|
||||||
|
@ -552,11 +547,14 @@ InnerWidget::InnerWidget(
|
||||||
, _controller(controller)
|
, _controller(controller)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _contextId(contextId) {
|
, _contextId(contextId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerWidget::load() {
|
||||||
const auto inner = this;
|
const auto inner = this;
|
||||||
|
|
||||||
const auto descriptor = Descriptor{
|
const auto descriptor = Descriptor{
|
||||||
peer,
|
_peer,
|
||||||
lifetime().make_state<Api::Statistics>(&peer->session().api()),
|
lifetime().make_state<Api::Statistics>(&_peer->session().api()),
|
||||||
_controller->uiShow()->toastParent(),
|
_controller->uiShow()->toastParent(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -573,84 +571,27 @@ InnerWidget::InnerWidget(
|
||||||
|
|
||||||
_showFinished.events(
|
_showFinished.events(
|
||||||
) | rpl::take(1) | rpl::start_with_next([=] {
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
if (!contextId) {
|
if (!_contextId) {
|
||||||
descriptor.api->request(
|
descriptor.api->request(
|
||||||
descriptor.peer
|
descriptor.peer
|
||||||
) | rpl::start_with_done([=] {
|
) | rpl::start_with_done([=] {
|
||||||
const auto anyStats = AnyStats{
|
_loadedStats = Data::AnyStatistics{
|
||||||
descriptor.api->channelStats(),
|
descriptor.api->channelStats(),
|
||||||
descriptor.api->supergroupStats(),
|
descriptor.api->supergroupStats(),
|
||||||
};
|
};
|
||||||
|
fill();
|
||||||
|
|
||||||
FillOverview(inner, anyStats);
|
|
||||||
FillStatistic(inner, descriptor, anyStats);
|
|
||||||
const auto &channel = anyStats.channel;
|
|
||||||
const auto &supergroup = anyStats.supergroup;
|
|
||||||
if (channel) {
|
|
||||||
auto showMessage = [=](FullMsgId fullId) {
|
|
||||||
_showRequests.fire({ .messageStatistic = fullId });
|
|
||||||
};
|
|
||||||
FillRecentPosts(inner, descriptor, channel, showMessage);
|
|
||||||
} else if (supergroup) {
|
|
||||||
const auto showPeerInfo = [=](not_null<PeerData*> peer) {
|
|
||||||
_showRequests.fire({ .info = peer->id });
|
|
||||||
};
|
|
||||||
const auto addSkip = [&](
|
|
||||||
not_null<Ui::VerticalLayout*> c) {
|
|
||||||
::Settings::AddSkip(c);
|
|
||||||
::Settings::AddDivider(c);
|
|
||||||
::Settings::AddSkip(c);
|
|
||||||
::Settings::AddSkip(c);
|
|
||||||
};
|
|
||||||
if (!supergroup.topSenders.empty()) {
|
|
||||||
AddMembersList(
|
|
||||||
{ .topSenders = supergroup.topSenders },
|
|
||||||
inner,
|
|
||||||
showPeerInfo,
|
|
||||||
descriptor.peer,
|
|
||||||
tr::lng_stats_members_title());
|
|
||||||
}
|
|
||||||
if (!supergroup.topAdministrators.empty()) {
|
|
||||||
addSkip(inner);
|
|
||||||
AddMembersList(
|
|
||||||
{ .topAdministrators
|
|
||||||
= supergroup.topAdministrators },
|
|
||||||
inner,
|
|
||||||
showPeerInfo,
|
|
||||||
descriptor.peer,
|
|
||||||
tr::lng_stats_admins_title());
|
|
||||||
}
|
|
||||||
if (!supergroup.topInviters.empty()) {
|
|
||||||
addSkip(inner);
|
|
||||||
AddMembersList(
|
|
||||||
{ .topInviters = supergroup.topInviters },
|
|
||||||
inner,
|
|
||||||
showPeerInfo,
|
|
||||||
descriptor.peer,
|
|
||||||
tr::lng_stats_inviters_title());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finishLoading();
|
finishLoading();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
} else {
|
} else {
|
||||||
const auto lifetimeApi = lifetime().make_state<rpl::lifetime>();
|
const auto lifetimeApi = lifetime().make_state<rpl::lifetime>();
|
||||||
const auto api = lifetimeApi->make_state<Api::MessageStatistics>(
|
const auto api = lifetimeApi->make_state<Api::MessageStatistics>(
|
||||||
descriptor.peer->asChannel(),
|
descriptor.peer->asChannel(),
|
||||||
contextId);
|
_contextId);
|
||||||
|
|
||||||
api->request([=](const Data::MessageStatistics &data) {
|
api->request([=](const Data::MessageStatistics &data) {
|
||||||
const auto stats = AnyStats{ .message = data };
|
_loadedStats = Data::AnyStatistics{ .message = data };
|
||||||
FillOverview(inner, stats);
|
fill();
|
||||||
FillStatistic(inner, descriptor, stats);
|
|
||||||
auto showPeerHistory = [=](FullMsgId fullId) {
|
|
||||||
_showRequests.fire({ .history = fullId });
|
|
||||||
};
|
|
||||||
AddPublicForwards(
|
|
||||||
*api,
|
|
||||||
inner,
|
|
||||||
std::move(showPeerHistory),
|
|
||||||
descriptor.peer,
|
|
||||||
contextId);
|
|
||||||
|
|
||||||
finishLoading();
|
finishLoading();
|
||||||
lifetimeApi->destroy();
|
lifetimeApi->destroy();
|
||||||
|
@ -659,6 +600,93 @@ InnerWidget::InnerWidget(
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InnerWidget::fill() {
|
||||||
|
const auto inner = this;
|
||||||
|
const auto descriptor = Descriptor{
|
||||||
|
_peer,
|
||||||
|
lifetime().make_state<Api::Statistics>(&_peer->session().api()),
|
||||||
|
_controller->uiShow()->toastParent(),
|
||||||
|
};
|
||||||
|
FillOverview(inner, _loadedStats);
|
||||||
|
FillStatistic(inner, descriptor, _loadedStats);
|
||||||
|
const auto &channel = _loadedStats.channel;
|
||||||
|
const auto &supergroup = _loadedStats.supergroup;
|
||||||
|
const auto &message = _loadedStats.message;
|
||||||
|
if (channel) {
|
||||||
|
auto showMessage = [=](FullMsgId fullId) {
|
||||||
|
_showRequests.fire({ .messageStatistic = fullId });
|
||||||
|
};
|
||||||
|
FillRecentPosts(inner, descriptor, channel, showMessage);
|
||||||
|
} else if (supergroup) {
|
||||||
|
const auto showPeerInfo = [=](not_null<PeerData*> peer) {
|
||||||
|
_showRequests.fire({ .info = peer->id });
|
||||||
|
};
|
||||||
|
const auto addSkip = [&](
|
||||||
|
not_null<Ui::VerticalLayout*> c) {
|
||||||
|
::Settings::AddSkip(c);
|
||||||
|
::Settings::AddDivider(c);
|
||||||
|
::Settings::AddSkip(c);
|
||||||
|
::Settings::AddSkip(c);
|
||||||
|
};
|
||||||
|
if (!supergroup.topSenders.empty()) {
|
||||||
|
AddMembersList(
|
||||||
|
{ .topSenders = supergroup.topSenders },
|
||||||
|
inner,
|
||||||
|
showPeerInfo,
|
||||||
|
descriptor.peer,
|
||||||
|
tr::lng_stats_members_title());
|
||||||
|
}
|
||||||
|
if (!supergroup.topAdministrators.empty()) {
|
||||||
|
addSkip(inner);
|
||||||
|
AddMembersList(
|
||||||
|
{ .topAdministrators
|
||||||
|
= supergroup.topAdministrators },
|
||||||
|
inner,
|
||||||
|
showPeerInfo,
|
||||||
|
descriptor.peer,
|
||||||
|
tr::lng_stats_admins_title());
|
||||||
|
}
|
||||||
|
if (!supergroup.topInviters.empty()) {
|
||||||
|
addSkip(inner);
|
||||||
|
AddMembersList(
|
||||||
|
{ .topInviters = supergroup.topInviters },
|
||||||
|
inner,
|
||||||
|
showPeerInfo,
|
||||||
|
descriptor.peer,
|
||||||
|
tr::lng_stats_inviters_title());
|
||||||
|
}
|
||||||
|
} else if (message) {
|
||||||
|
auto showPeerHistory = [=](FullMsgId fullId) {
|
||||||
|
_showRequests.fire({ .history = fullId });
|
||||||
|
};
|
||||||
|
const auto api = lifetime().make_state<Api::MessageStatistics>(
|
||||||
|
descriptor.peer->asChannel(),
|
||||||
|
_contextId);
|
||||||
|
AddPublicForwards(
|
||||||
|
*api,
|
||||||
|
inner,
|
||||||
|
std::move(showPeerHistory),
|
||||||
|
descriptor.peer,
|
||||||
|
_contextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerWidget::saveState(not_null<Memento*> memento) {
|
||||||
|
memento->setStates(base::take(_loadedStats));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
||||||
|
_loadedStats = memento->states();
|
||||||
|
if (_loadedStats.channel
|
||||||
|
|| _loadedStats.supergroup
|
||||||
|
|| _loadedStats.message) {
|
||||||
|
fill();
|
||||||
|
} else {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
Ui::RpWidget::resizeToWidth(width());
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
||||||
return _scrollToRequests.events();
|
return _scrollToRequests.events();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
|
#include "data/data_statistics.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
|
||||||
|
@ -17,6 +18,8 @@ class Controller;
|
||||||
|
|
||||||
namespace Info::Statistics {
|
namespace Info::Statistics {
|
||||||
|
|
||||||
|
class Memento;
|
||||||
|
|
||||||
class InnerWidget final : public Ui::VerticalLayout {
|
class InnerWidget final : public Ui::VerticalLayout {
|
||||||
public:
|
public:
|
||||||
struct ShowRequest final {
|
struct ShowRequest final {
|
||||||
|
@ -39,11 +42,19 @@ public:
|
||||||
|
|
||||||
void showFinished();
|
void showFinished();
|
||||||
|
|
||||||
|
void saveState(not_null<Memento*> memento);
|
||||||
|
void restoreState(not_null<Memento*> memento);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void load();
|
||||||
|
void fill();
|
||||||
|
|
||||||
not_null<Controller*> _controller;
|
not_null<Controller*> _controller;
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
FullMsgId _contextId;
|
FullMsgId _contextId;
|
||||||
|
|
||||||
|
Data::AnyStatistics _loadedStats;
|
||||||
|
|
||||||
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||||
rpl::event_stream<ShowRequest> _showRequests;
|
rpl::event_stream<ShowRequest> _showRequests;
|
||||||
rpl::event_stream<> _showFinished;
|
rpl::event_stream<> _showFinished;
|
||||||
|
|
|
@ -31,11 +31,20 @@ Section Memento::section() const {
|
||||||
return Section(Section::Type::Statistics);
|
return Section(Section::Type::Statistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Memento::setStates(Memento::States states) {
|
||||||
|
_states = std::move(states);
|
||||||
|
}
|
||||||
|
|
||||||
|
Memento::States Memento::states() {
|
||||||
|
return base::take(_states);
|
||||||
|
}
|
||||||
|
|
||||||
object_ptr<ContentWidget> Memento::createWidget(
|
object_ptr<ContentWidget> Memento::createWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
const QRect &geometry) {
|
const QRect &geometry) {
|
||||||
auto result = object_ptr<Widget>(parent, controller);
|
auto result = object_ptr<Widget>(parent, controller);
|
||||||
|
result->setInternalState(geometry, this);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +97,14 @@ rpl::producer<QString> Widget::title() {
|
||||||
: tr::lng_stats_title();
|
: tr::lng_stats_title();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::setInternalState(
|
||||||
|
const QRect &geometry,
|
||||||
|
not_null<Memento*> memento) {
|
||||||
|
setGeometry(geometry);
|
||||||
|
Ui::SendPendingMoveResizeEvents(this);
|
||||||
|
restoreState(memento);
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<bool> Widget::desiredShadowVisibility() const {
|
rpl::producer<bool> Widget::desiredShadowVisibility() const {
|
||||||
return rpl::single<bool>(true);
|
return rpl::single<bool>(true);
|
||||||
}
|
}
|
||||||
|
@ -98,9 +115,20 @@ void Widget::showFinished() {
|
||||||
|
|
||||||
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
|
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
|
||||||
auto result = std::make_shared<Memento>(controller());
|
auto result = std::make_shared<Memento>(controller());
|
||||||
|
saveState(result.get());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::saveState(not_null<Memento*> memento) {
|
||||||
|
memento->setScrollTop(scrollTopSave());
|
||||||
|
_inner->saveState(memento);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::restoreState(not_null<Memento*> memento) {
|
||||||
|
_inner->restoreState(memento);
|
||||||
|
scrollTopRestore(memento->scrollTop());
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Info::Memento> Make(
|
std::shared_ptr<Info::Memento> Make(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
FullMsgId contextId) {
|
FullMsgId contextId) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "info/info_content_widget.h"
|
#include "info/info_content_widget.h"
|
||||||
|
#include "data/data_statistics.h"
|
||||||
|
|
||||||
namespace Info::Statistics {
|
namespace Info::Statistics {
|
||||||
|
|
||||||
|
@ -26,6 +27,14 @@ public:
|
||||||
|
|
||||||
Section section() const override;
|
Section section() const override;
|
||||||
|
|
||||||
|
using States = Data::AnyStatistics;
|
||||||
|
|
||||||
|
void setStates(States states);
|
||||||
|
[[nodiscard]] States states();
|
||||||
|
|
||||||
|
private:
|
||||||
|
States _states;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Widget final : public ContentWidget {
|
class Widget final : public ContentWidget {
|
||||||
|
@ -40,7 +49,14 @@ public:
|
||||||
[[nodiscard]] not_null<PeerData*> peer() const;
|
[[nodiscard]] not_null<PeerData*> peer() const;
|
||||||
[[nodiscard]] FullMsgId contextId() const;
|
[[nodiscard]] FullMsgId contextId() const;
|
||||||
|
|
||||||
|
void setInternalState(
|
||||||
|
const QRect &geometry,
|
||||||
|
not_null<Memento*> memento);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void saveState(not_null<Memento*> memento);
|
||||||
|
void restoreState(not_null<Memento*> memento);
|
||||||
|
|
||||||
std::shared_ptr<ContentMemento> doCreateMemento() override;
|
std::shared_ptr<ContentMemento> doCreateMemento() override;
|
||||||
|
|
||||||
const not_null<InnerWidget*> _inner;
|
const not_null<InnerWidget*> _inner;
|
||||||
|
|
Loading…
Add table
Reference in a new issue