Added ability to save state for recent posts in statistical info.
This commit is contained in:
parent
aee6b6e224
commit
a3d8db4ac0
|
@ -884,6 +884,7 @@ PRIVATE
|
|||
info/profile/info_profile_widget.h
|
||||
info/settings/info_settings_widget.cpp
|
||||
info/settings/info_settings_widget.h
|
||||
info/statistics/info_statistics_common.h
|
||||
info/statistics/info_statistics_inner_widget.cpp
|
||||
info/statistics/info_statistics_inner_widget.h
|
||||
info/statistics/info_statistics_list_controllers.cpp
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_statistics.h"
|
||||
|
||||
namespace Info::Statistics {
|
||||
|
||||
struct SavedState final {
|
||||
Data::AnyStatistics stats;
|
||||
base::flat_map<MsgId, QImage> recentPostPreviews;
|
||||
};
|
||||
|
||||
} // namespace Info::Statistics
|
|
@ -470,78 +470,6 @@ void FillOverview(
|
|||
::Settings::AddSkip(content, st::statisticsLayerOverviewMargins.bottom());
|
||||
}
|
||||
|
||||
void FillRecentPosts(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
const Descriptor &descriptor,
|
||||
const Data::ChannelStatistics &stats,
|
||||
Fn<void(FullMsgId)> showMessageStatistic) {
|
||||
if (stats.recentMessageInteractions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto wrap = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(container)));
|
||||
const auto content = wrap->entity();
|
||||
AddHeader(content, tr::lng_stats_recent_messages_title, { stats, {} });
|
||||
::Settings::AddSkip(content);
|
||||
|
||||
const auto addMessage = [=](
|
||||
not_null<Ui::VerticalLayout*> messageWrap,
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::StatisticsMessageInteractionInfo &info) {
|
||||
const auto button = messageWrap->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
messageWrap,
|
||||
rpl::never<QString>(),
|
||||
st::statisticsRecentPostButton));
|
||||
const auto raw = Ui::CreateChild<MessagePreview>(
|
||||
button,
|
||||
item,
|
||||
info.viewsCount,
|
||||
info.forwardsCount);
|
||||
raw->show();
|
||||
button->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
if (!s.isNull()) {
|
||||
raw->setGeometry(Rect(s)
|
||||
- st::statisticsRecentPostButton.padding);
|
||||
}
|
||||
}, raw->lifetime());
|
||||
button->setClickedCallback([=, fullId = item->fullId()] {
|
||||
showMessageStatistic(fullId);
|
||||
});
|
||||
::Settings::AddSkip(messageWrap);
|
||||
if (!wrap->toggled()) {
|
||||
wrap->toggle(true, anim::type::normal);
|
||||
}
|
||||
};
|
||||
|
||||
auto foundLoaded = false;
|
||||
const auto &peer = descriptor.peer;
|
||||
for (const auto &recent : stats.recentMessageInteractions) {
|
||||
const auto messageWrap = content->add(
|
||||
object_ptr<Ui::VerticalLayout>(content));
|
||||
const auto msgId = recent.messageId;
|
||||
if (const auto item = peer->owner().message(peer, msgId)) {
|
||||
addMessage(messageWrap, item, recent);
|
||||
foundLoaded = true;
|
||||
continue;
|
||||
}
|
||||
const auto callback = crl::guard(content, [=] {
|
||||
if (const auto item = peer->owner().message(peer, msgId)) {
|
||||
addMessage(messageWrap, item, recent);
|
||||
content->resizeToWidth(content->width());
|
||||
}
|
||||
});
|
||||
peer->session().api().requestMessageData(peer, msgId, callback);
|
||||
}
|
||||
if (!foundLoaded) {
|
||||
wrap->toggle(false, anim::type::instant);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
InnerWidget::InnerWidget(
|
||||
|
@ -581,7 +509,7 @@ void InnerWidget::load() {
|
|||
descriptor.api->request(
|
||||
descriptor.peer
|
||||
) | rpl::start_with_done([=] {
|
||||
_loadedStats = Data::AnyStatistics{
|
||||
_state.stats = Data::AnyStatistics{
|
||||
descriptor.api->channelStats(),
|
||||
descriptor.api->supergroupStats(),
|
||||
};
|
||||
|
@ -596,7 +524,7 @@ void InnerWidget::load() {
|
|||
_contextId);
|
||||
|
||||
api->request([=](const Data::MessageStatistics &data) {
|
||||
_loadedStats = Data::AnyStatistics{ .message = data };
|
||||
_state.stats = Data::AnyStatistics{ .message = data };
|
||||
fill();
|
||||
|
||||
finishLoading();
|
||||
|
@ -613,16 +541,13 @@ void InnerWidget::fill() {
|
|||
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;
|
||||
FillOverview(inner, _state.stats);
|
||||
FillStatistic(inner, descriptor, _state.stats);
|
||||
const auto &channel = _state.stats.channel;
|
||||
const auto &supergroup = _state.stats.supergroup;
|
||||
const auto &message = _state.stats.message;
|
||||
if (channel) {
|
||||
auto showMessage = [=](FullMsgId fullId) {
|
||||
_showRequests.fire({ .messageStatistic = fullId });
|
||||
};
|
||||
FillRecentPosts(inner, descriptor, channel, showMessage);
|
||||
fillRecentPosts();
|
||||
} else if (supergroup) {
|
||||
const auto showPeerInfo = [=](not_null<PeerData*> peer) {
|
||||
_showRequests.fire({ .info = peer->id });
|
||||
|
@ -677,15 +602,95 @@ void InnerWidget::fill() {
|
|||
}
|
||||
}
|
||||
|
||||
void InnerWidget::fillRecentPosts() {
|
||||
const auto &stats = _state.stats.channel;
|
||||
if (!stats || stats.recentMessageInteractions.empty()) {
|
||||
return;
|
||||
}
|
||||
_messagePreviews.reserve(stats.recentMessageInteractions.size());
|
||||
const auto container = this;
|
||||
|
||||
const auto wrap = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(container)));
|
||||
const auto content = wrap->entity();
|
||||
AddHeader(content, tr::lng_stats_recent_messages_title, { stats, {} });
|
||||
::Settings::AddSkip(content);
|
||||
|
||||
const auto addMessage = [=](
|
||||
not_null<Ui::VerticalLayout*> messageWrap,
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::StatisticsMessageInteractionInfo &info) {
|
||||
const auto button = messageWrap->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
messageWrap,
|
||||
rpl::never<QString>(),
|
||||
st::statisticsRecentPostButton));
|
||||
auto it = _state.recentPostPreviews.find(item->fullId().msg);
|
||||
auto cachedPreview = (it != end(_state.recentPostPreviews))
|
||||
? base::take(it->second)
|
||||
: QImage();
|
||||
const auto raw = Ui::CreateChild<MessagePreview>(
|
||||
button,
|
||||
item,
|
||||
info.viewsCount,
|
||||
info.forwardsCount,
|
||||
std::move(cachedPreview));
|
||||
|
||||
_messagePreviews.push_back(raw);
|
||||
raw->show();
|
||||
button->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
if (!s.isNull()) {
|
||||
raw->setGeometry(Rect(s)
|
||||
- st::statisticsRecentPostButton.padding);
|
||||
}
|
||||
}, raw->lifetime());
|
||||
button->setClickedCallback([=, fullId = item->fullId()] {
|
||||
_showRequests.fire({ .messageStatistic = fullId });
|
||||
});
|
||||
::Settings::AddSkip(messageWrap);
|
||||
if (!wrap->toggled()) {
|
||||
wrap->toggle(true, anim::type::normal);
|
||||
}
|
||||
};
|
||||
|
||||
auto foundLoaded = false;
|
||||
for (const auto &recent : stats.recentMessageInteractions) {
|
||||
const auto messageWrap = content->add(
|
||||
object_ptr<Ui::VerticalLayout>(content));
|
||||
const auto msgId = recent.messageId;
|
||||
if (const auto item = _peer->owner().message(_peer, msgId)) {
|
||||
addMessage(messageWrap, item, recent);
|
||||
foundLoaded = true;
|
||||
continue;
|
||||
}
|
||||
const auto callback = crl::guard(content, [=] {
|
||||
if (const auto item = _peer->owner().message(_peer, msgId)) {
|
||||
addMessage(messageWrap, item, recent);
|
||||
content->resizeToWidth(content->width());
|
||||
}
|
||||
});
|
||||
_peer->session().api().requestMessageData(_peer, msgId, callback);
|
||||
}
|
||||
if (!foundLoaded) {
|
||||
wrap->toggle(false, anim::type::instant);
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::saveState(not_null<Memento*> memento) {
|
||||
memento->setStates(base::take(_loadedStats));
|
||||
for (const auto &message : _messagePreviews) {
|
||||
message->saveState(_state);
|
||||
}
|
||||
memento->setState(base::take(_state));
|
||||
}
|
||||
|
||||
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
||||
_loadedStats = memento->states();
|
||||
if (_loadedStats.channel
|
||||
|| _loadedStats.supergroup
|
||||
|| _loadedStats.message) {
|
||||
_state = memento->state();
|
||||
if (_state.stats.channel
|
||||
|| _state.stats.supergroup
|
||||
|| _state.stats.message) {
|
||||
fill();
|
||||
} else {
|
||||
load();
|
||||
|
|
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/object_ptr.h"
|
||||
#include "data/data_statistics.h"
|
||||
#include "info/statistics/info_statistics_common.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
|
||||
|
@ -19,6 +19,7 @@ class Controller;
|
|||
namespace Info::Statistics {
|
||||
|
||||
class Memento;
|
||||
class MessagePreview;
|
||||
|
||||
class InnerWidget final : public Ui::VerticalLayout {
|
||||
public:
|
||||
|
@ -48,12 +49,15 @@ public:
|
|||
private:
|
||||
void load();
|
||||
void fill();
|
||||
void fillRecentPosts();
|
||||
|
||||
not_null<Controller*> _controller;
|
||||
not_null<PeerData*> _peer;
|
||||
FullMsgId _contextId;
|
||||
|
||||
Data::AnyStatistics _loadedStats;
|
||||
std::vector<not_null<MessagePreview*>> _messagePreviews;
|
||||
|
||||
SavedState _state;
|
||||
|
||||
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||
rpl::event_stream<ShowRequest> _showRequests;
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item.h"
|
||||
#include "history/history_item_helpers.h"
|
||||
#include "history/view/history_view_item_preview.h"
|
||||
#include "info/statistics/info_statistics_common.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
|
@ -69,7 +70,8 @@ MessagePreview::MessagePreview(
|
|||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<HistoryItem*> item,
|
||||
int views,
|
||||
int shares)
|
||||
int shares,
|
||||
QImage cachedPreview)
|
||||
: Ui::RpWidget(parent)
|
||||
, _item(item)
|
||||
, _date(
|
||||
|
@ -88,7 +90,8 @@ MessagePreview::MessagePreview(
|
|||
lt_count_decimal,
|
||||
shares))
|
||||
, _viewsWidth(_views.maxWidth())
|
||||
, _sharesWidth(_shares.maxWidth()) {
|
||||
, _sharesWidth(_shares.maxWidth())
|
||||
, _preview(std::move(cachedPreview)) {
|
||||
_text.setMarkedText(
|
||||
st::defaultPeerListItem.nameStyle,
|
||||
_item->toPreview({ .generateImages = false }).text,
|
||||
|
@ -97,7 +100,9 @@ MessagePreview::MessagePreview(
|
|||
.session = &item->history()->session(),
|
||||
.customEmojiRepaint = [=] { update(); },
|
||||
});
|
||||
if (_preview.isNull()) {
|
||||
processPreview(item);
|
||||
}
|
||||
}
|
||||
|
||||
void MessagePreview::processPreview(not_null<HistoryItem*> item) {
|
||||
|
@ -226,4 +231,10 @@ void MessagePreview::paintEvent(QPaintEvent *e) {
|
|||
});
|
||||
}
|
||||
|
||||
void MessagePreview::saveState(SavedState &state) const {
|
||||
if (!_lifetimeDownload) {
|
||||
state.recentPostPreviews[_item->fullId().msg] = _preview;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Info::Statistics
|
||||
|
|
|
@ -22,13 +22,18 @@ class SpoilerAnimation;
|
|||
|
||||
namespace Info::Statistics {
|
||||
|
||||
struct SavedState;
|
||||
|
||||
class MessagePreview final : public Ui::RpWidget {
|
||||
public:
|
||||
MessagePreview(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<HistoryItem*> item,
|
||||
int views,
|
||||
int shares);
|
||||
int shares,
|
||||
QImage cachedPreview);
|
||||
|
||||
void saveState(SavedState &state) const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
|
|
@ -31,12 +31,12 @@ Section Memento::section() const {
|
|||
return Section(Section::Type::Statistics);
|
||||
}
|
||||
|
||||
void Memento::setStates(Memento::States states) {
|
||||
_states = std::move(states);
|
||||
void Memento::setState(SavedState state) {
|
||||
_state = std::move(state);
|
||||
}
|
||||
|
||||
Memento::States Memento::states() {
|
||||
return base::take(_states);
|
||||
SavedState Memento::state() {
|
||||
return base::take(_state);
|
||||
}
|
||||
|
||||
object_ptr<ContentWidget> Memento::createWidget(
|
||||
|
|
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "info/info_content_widget.h"
|
||||
#include "data/data_statistics.h"
|
||||
#include "info/statistics/info_statistics_common.h"
|
||||
|
||||
namespace Info::Statistics {
|
||||
|
||||
|
@ -27,13 +27,11 @@ public:
|
|||
|
||||
Section section() const override;
|
||||
|
||||
using States = Data::AnyStatistics;
|
||||
|
||||
void setStates(States states);
|
||||
[[nodiscard]] States states();
|
||||
void setState(SavedState states);
|
||||
[[nodiscard]] SavedState state();
|
||||
|
||||
private:
|
||||
States _states;
|
||||
SavedState _state;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue