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

View file

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

View file

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

View file

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

View file

@ -26,7 +26,7 @@ namespace Info::Statistics {
void AddPublicForwards(
const Data::PublicForwardsSlice &firstSlice,
not_null<Ui::VerticalLayout*> container,
Fn<void(FullMsgId)> showPeerHistory,
Fn<void(Data::RecentPostId)> requestShow,
not_null<PeerData*> peer,
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_inner_widget.h"
#include "data/data_session.h"
#include "data/data_stories.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
#include "info/statistics/info_statistics_inner_widget.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
namespace Info::Statistics {
@ -78,6 +81,13 @@ Widget::Widget(
controller->statisticsPeer(),
request.messageStatistic,
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->scrollToRequests(