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;
|
||||
};
|
||||
|
||||
struct AnyStatistics final {
|
||||
Data::ChannelStatistics channel;
|
||||
Data::SupergroupStatistics supergroup;
|
||||
Data::MessageStatistics message;
|
||||
};
|
||||
|
||||
} // 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_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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue