Added initial ability to save and restore state of statistical info.

This commit is contained in:
23rd 2023-10-11 02:40:10 +03:00 committed by John Preston
parent caf32cccd3
commit ec5e846374
5 changed files with 163 additions and 74 deletions

View File

@ -113,4 +113,10 @@ struct MessageStatistics final {
int views = 0;
};
struct AnyStatistics final {
Data::ChannelStatistics channel;
Data::SupergroupStatistics supergroup;
Data::MessageStatistics message;
};
} // namespace Data

View File

@ -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_widget.h"
#include "api/api_statistics.h"
#include "apiwrap.h"
#include "data/data_peer.h"
@ -42,12 +43,6 @@ struct Descriptor final {
not_null<QWidget*> toastParent;
};
struct AnyStats final {
Data::ChannelStatistics channel;
Data::SupergroupStatistics supergroup;
Data::MessageStatistics message;
};
void ProcessZoom(
const Descriptor &d,
not_null<Statistic::ChartWidget*> widget,
@ -112,7 +107,7 @@ void ProcessChart(
void FillStatistic(
not_null<Ui::VerticalLayout*> content,
const Descriptor &descriptor,
const AnyStats &stats) {
const Data::AnyStatistics &stats) {
using Type = Statistic::ChartViewType;
const auto &padding = st::statisticsChartEntryPadding;
const auto &m = st::statisticsLayerMargins;
@ -266,7 +261,7 @@ void FillLoading(
void AddHeader(
not_null<Ui::VerticalLayout*> content,
tr::phrase<> text,
const AnyStats &stats) {
const Data::AnyStatistics &stats) {
const auto startDate = stats.channel
? stats.channel.startDate
: stats.supergroup.startDate;
@ -294,7 +289,7 @@ void AddHeader(
void FillOverview(
not_null<Ui::VerticalLayout*> content,
const AnyStats &stats) {
const Data::AnyStatistics &stats) {
using Value = Data::StatisticalValue;
const auto &channel = stats.channel;
@ -552,11 +547,14 @@ InnerWidget::InnerWidget(
, _controller(controller)
, _peer(peer)
, _contextId(contextId) {
}
void InnerWidget::load() {
const auto inner = this;
const auto descriptor = Descriptor{
peer,
lifetime().make_state<Api::Statistics>(&peer->session().api()),
_peer,
lifetime().make_state<Api::Statistics>(&_peer->session().api()),
_controller->uiShow()->toastParent(),
};
@ -573,84 +571,27 @@ InnerWidget::InnerWidget(
_showFinished.events(
) | rpl::take(1) | rpl::start_with_next([=] {
if (!contextId) {
if (!_contextId) {
descriptor.api->request(
descriptor.peer
) | rpl::start_with_done([=] {
const auto anyStats = AnyStats{
_loadedStats = Data::AnyStatistics{
descriptor.api->channelStats(),
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();
}, lifetime());
} else {
const auto lifetimeApi = lifetime().make_state<rpl::lifetime>();
const auto api = lifetimeApi->make_state<Api::MessageStatistics>(
descriptor.peer->asChannel(),
contextId);
_contextId);
api->request([=](const Data::MessageStatistics &data) {
const auto stats = AnyStats{ .message = data };
FillOverview(inner, stats);
FillStatistic(inner, descriptor, stats);
auto showPeerHistory = [=](FullMsgId fullId) {
_showRequests.fire({ .history = fullId });
};
AddPublicForwards(
*api,
inner,
std::move(showPeerHistory),
descriptor.peer,
contextId);
_loadedStats = Data::AnyStatistics{ .message = data };
fill();
finishLoading();
lifetimeApi->destroy();
@ -659,6 +600,93 @@ InnerWidget::InnerWidget(
}, 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 {
return _scrollToRequests.events();
}

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/object_ptr.h"
#include "data/data_statistics.h"
#include "ui/widgets/scroll_area.h"
#include "ui/wrap/vertical_layout.h"
@ -17,6 +18,8 @@ class Controller;
namespace Info::Statistics {
class Memento;
class InnerWidget final : public Ui::VerticalLayout {
public:
struct ShowRequest final {
@ -39,11 +42,19 @@ public:
void showFinished();
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
private:
void load();
void fill();
not_null<Controller*> _controller;
not_null<PeerData*> _peer;
FullMsgId _contextId;
Data::AnyStatistics _loadedStats;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
rpl::event_stream<ShowRequest> _showRequests;
rpl::event_stream<> _showFinished;

View File

@ -31,11 +31,20 @@ Section Memento::section() const {
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(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) {
auto result = object_ptr<Widget>(parent, controller);
result->setInternalState(geometry, this);
return result;
}
@ -88,6 +97,14 @@ rpl::producer<QString> Widget::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 {
return rpl::single<bool>(true);
}
@ -98,9 +115,20 @@ void Widget::showFinished() {
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
auto result = std::make_shared<Memento>(controller());
saveState(result.get());
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(
not_null<PeerData*> peer,
FullMsgId contextId) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "info/info_content_widget.h"
#include "data/data_statistics.h"
namespace Info::Statistics {
@ -26,6 +27,14 @@ public:
Section section() const override;
using States = Data::AnyStatistics;
void setStates(States states);
[[nodiscard]] States states();
private:
States _states;
};
class Widget final : public ContentWidget {
@ -40,7 +49,14 @@ public:
[[nodiscard]] not_null<PeerData*> peer() const;
[[nodiscard]] FullMsgId contextId() const;
void setInternalState(
const QRect &geometry,
not_null<Memento*> memento);
private:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
std::shared_ptr<ContentMemento> doCreateMemento() override;
const not_null<InnerWidget*> _inner;