Added support of stories in list of public forwards in statistics info.

This commit is contained in:
23rd 2023-12-06 21:27:33 +03:00 committed by John Preston
parent cccc2ce0f1
commit 98c6a3ff79
6 changed files with 115 additions and 45 deletions

View file

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_stories.h"
#include "data/data_story.h"
#include "history/history.h" #include "history/history.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "statistics/statistics_data_deserialize.h" #include "statistics/statistics_data_deserialize.h"
@ -475,9 +477,10 @@ void PublicForwards::requestStory(
_requestId = 0; _requestId = 0;
const auto &data = tlForwards.data(); const auto &data = tlForwards.data();
auto &owner = channel->owner();
channel->owner().processUsers(data.vusers()); owner.processUsers(data.vusers());
channel->owner().processChats(data.vchats()); owner.processChats(data.vchats());
const auto nextToken = Data::PublicForwardsSlice::OffsetToken({ const auto nextToken = Data::PublicForwardsSlice::OffsetToken({
.storyOffset = data.vnext_offset().value_or_empty(), .storyOffset = data.vnext_offset().value_or_empty(),
@ -494,23 +497,23 @@ void PublicForwards::requestStory(
const auto msgId = IdFromMessage(message); const auto msgId = IdFromMessage(message);
const auto peerId = PeerFromMessage(message); const auto peerId = PeerFromMessage(message);
const auto lastDate = DateFromMessage(message); const auto lastDate = DateFromMessage(message);
if (const auto peer = channel->owner().peerLoaded(peerId)) { if (const auto peer = owner.peerLoaded(peerId)) {
if (!lastDate) { if (!lastDate) {
return; return;
} }
channel->owner().addNewMessage( owner.addNewMessage(
message, message,
MessageFlags(), MessageFlags(),
NewMessageType::Existing); NewMessageType::Existing);
recentList.push_back({ .messageId = { peerId, msgId } }); recentList.push_back({ .messageId = { peerId, msgId } });
} }
}, [&](const MTPDpublicForwardStory &data) { }, [&](const MTPDpublicForwardStory &data) {
data.vstory().match([&](const MTPDstoryItem &d) { const auto story = owner.stories().applyFromWebpage(
recentList.push_back({ peerFromMTP(data.vpeer()),
.storyId = { peerFromMTP(data.vpeer()), d.vid().v } data.vstory());
}); if (story) {
}, [](const auto &) { recentList.push_back({ .storyId = story->fullId() });
}); }
}); });
} }

View file

@ -728,7 +728,12 @@ void InnerWidget::fill() {
AddPublicForwards( AddPublicForwards(
_state.publicForwardsFirstSlice, _state.publicForwardsFirstSlice,
inner, inner,
[=](FullMsgId id) { _showRequests.fire({ .history = id }); }, [=](RecentPostId id) {
_showRequests.fire({
.history = id.messageId,
.story = id.storyId,
});
},
descriptor.peer, descriptor.peer,
RecentPostId{ .messageId = _contextId, .storyId = _storyId }); RecentPostId{ .messageId = _contextId, .storyId = _storyId });
} }

View file

@ -33,6 +33,7 @@ public:
FullMsgId history; FullMsgId history;
FullMsgId messageStatistic; FullMsgId messageStatistic;
FullStoryId storyStatistic; FullStoryId storyStatistic;
FullStoryId story;
}; };
InnerWidget( InnerWidget(

View file

@ -9,22 +9,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_statistics.h" #include "api/api_statistics.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "data/data_boosts.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_stories.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "info/boosts/giveaway/boost_badge.h" #include "info/boosts/giveaway/boost_badge.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "ui/effects/outline_segments.h" // Ui::UnreadStoryOutlineGradient.
#include "ui/effects/toggle_arrow.h" #include "ui/effects/toggle_arrow.h"
#include "ui/empty_userpic.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/vertical_list.h" #include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "styles/style_dialogs.h" // dialogsStoriesFull.
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "styles/style_statistics.h" #include "styles/style_statistics.h"
#include "styles/style_window.h" #include "styles/style_window.h"
@ -93,7 +94,7 @@ void AddSubtitle(
struct PublicForwardsDescriptor final { struct PublicForwardsDescriptor final {
Data::PublicForwardsSlice firstSlice; Data::PublicForwardsSlice firstSlice;
Fn<void(FullMsgId)> showPeerHistory; Fn<void(Data::RecentPostId)> requestShow;
not_null<PeerData*> peer; not_null<PeerData*> peer;
Data::RecentPostId contextId; Data::RecentPostId contextId;
}; };
@ -110,24 +111,62 @@ struct BoostsDescriptor final {
not_null<PeerData*> peer; not_null<PeerData*> peer;
}; };
class PeerListRowWithMsgId : public PeerListRow { class PeerListRowWithFullId : public PeerListRow {
public: public:
using PeerListRow::PeerListRow; PeerListRowWithFullId(
not_null<PeerData*> peer,
Data::RecentPostId contextId);
void setMsgId(MsgId msgId); [[nodiscard]] PaintRoundImageCallback generatePaintUserpicCallback(
[[nodiscard]] MsgId msgId() const; bool) override;
[[nodiscard]] Data::RecentPostId contextId() const;
private: private:
MsgId _msgId; const Data::RecentPostId _contextId;
}; };
void PeerListRowWithMsgId::setMsgId(MsgId msgId) { PeerListRowWithFullId::PeerListRowWithFullId(
_msgId = msgId; not_null<PeerData*> peer,
Data::RecentPostId contextId)
: PeerListRow(peer)
, _contextId(contextId) {
} }
MsgId PeerListRowWithMsgId::msgId() const { PaintRoundImageCallback PeerListRowWithFullId::generatePaintUserpicCallback(
return _msgId; bool forceRound) {
if (!_contextId.storyId) {
return PeerListRow::generatePaintUserpicCallback(forceRound);
}
const auto peer = PeerListRow::peer();
auto userpic = PeerListRow::ensureUserpicView();
const auto line = st::dialogsStoriesFull.lineTwice;
const auto penWidth = line / 2.;
const auto offset = 1.5 * penWidth * 2;
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
const auto rect = QRect(QPoint(x, y), Size(size));
peer->paintUserpicLeft(
p,
userpic,
x + offset,
y + offset,
outerWidth,
size - offset * 2);
auto hq = PainterHighQualityEnabler(p);
auto gradient = Ui::UnreadStoryOutlineGradient();
gradient.setStart(rect.topRight());
gradient.setFinalStop(rect.bottomLeft());
p.setPen(QPen(gradient, penWidth));
p.setBrush(Qt::NoBrush);
p.drawEllipse(rect - Margins(penWidth));
};
}
Data::RecentPostId PeerListRowWithFullId::contextId() const {
return _contextId;
} }
class MembersController final : public PeerListController { class MembersController final : public PeerListController {
@ -237,11 +276,11 @@ public:
void loadMoreRows() override; void loadMoreRows() override;
private: private:
void appendRow(not_null<PeerData*> peer, MsgId msgId); void appendRow(not_null<PeerData*> peer, Data::RecentPostId contextId);
void applySlice(const Data::PublicForwardsSlice &slice); void applySlice(const Data::PublicForwardsSlice &slice);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
Fn<void(FullMsgId)> _showPeerHistory; Fn<void(Data::RecentPostId)> _requestShow;
Api::PublicForwards _api; Api::PublicForwards _api;
Data::PublicForwardsSlice _firstSlice; Data::PublicForwardsSlice _firstSlice;
@ -253,7 +292,7 @@ private:
PublicForwardsController::PublicForwardsController(PublicForwardsDescriptor d) PublicForwardsController::PublicForwardsController(PublicForwardsDescriptor d)
: _session(&d.peer->session()) : _session(&d.peer->session())
, _showPeerHistory(std::move(d.showPeerHistory)) , _requestShow(std::move(d.requestShow))
, _api(d.peer->asChannel(), d.contextId) , _api(d.peer->asChannel(), d.contextId)
, _firstSlice(std::move(d.firstSlice)) { , _firstSlice(std::move(d.firstSlice)) {
} }
@ -282,10 +321,13 @@ void PublicForwardsController::applySlice(
_apiToken = slice.token; _apiToken = slice.token;
for (const auto &item : slice.list) { for (const auto &item : slice.list) {
// TODO support stories. if (const auto &full = item.messageId) {
if (const auto fullId = item.messageId) { if (const auto peer = session().data().peerLoaded(full.peer)) {
if (const auto peer = session().data().peerLoaded(fullId.peer)) { appendRow(peer, item);
appendRow(peer, fullId.msg); }
} else if (const auto &full = item.storyId) {
if (const auto story = session().data().stories().lookup(full)) {
appendRow((*story)->peer(), item);
} }
} }
} }
@ -293,25 +335,32 @@ void PublicForwardsController::applySlice(
} }
void PublicForwardsController::rowClicked(not_null<PeerListRow*> row) { void PublicForwardsController::rowClicked(not_null<PeerListRow*> row) {
const auto rowWithMsgId = static_cast<PeerListRowWithMsgId*>(row.get()); const auto rowWithId = static_cast<PeerListRowWithFullId*>(row.get());
crl::on_main([=, msgId = rowWithMsgId->msgId(), peer = row->peer()] { crl::on_main([=, id = rowWithId->contextId()] { _requestShow(id); });
_showPeerHistory({ peer->id, msgId });
});
} }
void PublicForwardsController::appendRow( void PublicForwardsController::appendRow(
not_null<PeerData*> peer, not_null<PeerData*> peer,
MsgId msgId) { Data::RecentPostId contextId) {
if (delegate()->peerListFindRow(peer->id.value)) { if (delegate()->peerListFindRow(peer->id.value)) {
return; return;
} }
auto row = std::make_unique<PeerListRowWithMsgId>(peer); auto row = std::make_unique<PeerListRowWithFullId>(peer, contextId);
row->setMsgId(msgId);
const auto members = peer->asChannel()->membersCount(); const auto members = peer->isChannel()
const auto message = peer->owner().message({ peer->id, msgId }); ? peer->asChannel()->membersCount()
const auto views = message ? message->viewsCount() : 0; : 0;
const auto views = [&] {
if (contextId.messageId) {
const auto message = peer->owner().message(contextId.messageId);
return message ? message->viewsCount() : 0;
} else if (const auto &id = contextId.storyId) {
const auto story = peer->owner().stories().lookup(id);
return story ? (*story)->views() : 0;
}
return 0;
}();
const auto membersText = !members const auto membersText = !members
? QString() ? QString()
@ -321,7 +370,9 @@ void PublicForwardsController::appendRow(
const auto viewsText = views const auto viewsText = views
? tr::lng_stats_recent_messages_views({}, lt_count_decimal, views) ? tr::lng_stats_recent_messages_views({}, lt_count_decimal, views)
: QString(); : QString();
const auto resultText = (membersText.isEmpty() || viewsText.isEmpty()) const auto resultText = (membersText.isEmpty() && viewsText.isEmpty())
? tr::lng_stories_no_views(tr::now)
: (membersText.isEmpty() || viewsText.isEmpty())
? membersText + viewsText ? membersText + viewsText
: QString("%1, %2").arg(membersText, viewsText); : QString("%1, %2").arg(membersText, viewsText);
row->setCustomStatus(resultText); row->setCustomStatus(resultText);
@ -618,7 +669,7 @@ rpl::producer<int> BoostsController::totalBoostsValue() const {
void AddPublicForwards( void AddPublicForwards(
const Data::PublicForwardsSlice &firstSlice, const Data::PublicForwardsSlice &firstSlice,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
Fn<void(FullMsgId)> showPeerHistory, Fn<void(Data::RecentPostId)> requestShow,
not_null<PeerData*> peer, not_null<PeerData*> peer,
Data::RecentPostId contextId) { Data::RecentPostId contextId) {
if (!peer->isChannel()) { if (!peer->isChannel()) {
@ -633,7 +684,7 @@ void AddPublicForwards(
}; };
auto d = PublicForwardsDescriptor{ auto d = PublicForwardsDescriptor{
firstSlice, firstSlice,
std::move(showPeerHistory), std::move(requestShow),
peer, peer,
contextId, contextId,
}; };

View file

@ -26,7 +26,7 @@ namespace Info::Statistics {
void AddPublicForwards( void AddPublicForwards(
const Data::PublicForwardsSlice &firstSlice, const Data::PublicForwardsSlice &firstSlice,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
Fn<void(FullMsgId)> showPeerHistory, Fn<void(Data::RecentPostId)> requestShow,
not_null<PeerData*> peer, not_null<PeerData*> peer,
Data::RecentPostId contextId); Data::RecentPostId contextId);

View file

@ -7,10 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "info/statistics/info_statistics_widget.h" #include "info/statistics/info_statistics_widget.h"
#include "info/statistics/info_statistics_inner_widget.h" #include "data/data_session.h"
#include "data/data_stories.h"
#include "info/info_controller.h" #include "info/info_controller.h"
#include "info/info_memento.h" #include "info/info_memento.h"
#include "info/statistics/info_statistics_inner_widget.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h"
namespace Info::Statistics { namespace Info::Statistics {
@ -78,6 +81,13 @@ Widget::Widget(
controller->statisticsPeer(), controller->statisticsPeer(),
request.messageStatistic, request.messageStatistic,
request.storyStatistic)); request.storyStatistic));
} else if (const auto &s = request.story) {
if (const auto peer = controller->session().data().peer(s.peer)) {
controller->parentController()->openPeerStory(
peer,
s.story,
{ Data::StoriesContextSingle() });
}
} }
}, _inner->lifetime()); }, _inner->lifetime());
_inner->scrollToRequests( _inner->scrollToRequests(