mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Added list of public forwards for story statistics.
This commit is contained in:
parent
dfe55b26a2
commit
2542ec5d93
8 changed files with 157 additions and 56 deletions
|
@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "apiwrap.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -352,7 +351,7 @@ Data::SupergroupStatistics Statistics::supergroupStats() const {
|
|||
|
||||
PublicForwards::PublicForwards(
|
||||
not_null<ChannelData*> channel,
|
||||
FullMsgId fullId)
|
||||
Data::RecentPostId fullId)
|
||||
: StatisticsRequestSender(channel)
|
||||
, _fullId(fullId) {
|
||||
}
|
||||
|
@ -360,9 +359,20 @@ PublicForwards::PublicForwards(
|
|||
void PublicForwards::request(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done) {
|
||||
if (_requestId) {
|
||||
return;
|
||||
if (!_requestId) {
|
||||
if (_fullId.messageId) {
|
||||
requestMessage(token, std::move(done));
|
||||
} else if (_fullId.storyId) {
|
||||
requestStory(token, std::move(done));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PublicForwards::requestMessage(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done) {
|
||||
Expects(_fullId.messageId);
|
||||
|
||||
const auto offsetPeer = channel()->owner().peer(token.fullId.peer);
|
||||
const auto tlOffsetPeer = offsetPeer
|
||||
? offsetPeer->input
|
||||
|
@ -370,13 +380,13 @@ void PublicForwards::request(
|
|||
constexpr auto kLimit = tl::make_int(100);
|
||||
_requestId = makeRequest(MTPstats_GetMessagePublicForwards(
|
||||
channel()->inputChannel,
|
||||
MTP_int(_fullId.msg),
|
||||
MTP_int(_fullId.messageId.msg),
|
||||
MTP_int(token.rate),
|
||||
tlOffsetPeer,
|
||||
MTP_int(token.fullId.msg),
|
||||
kLimit
|
||||
)).done([=, channel = channel()](const MTPmessages_Messages &result) {
|
||||
using Messages = QVector<FullMsgId>;
|
||||
using Messages = QVector<Data::RecentPostId>;
|
||||
_requestId = 0;
|
||||
|
||||
auto nextToken = Data::PublicForwardsSlice::OffsetToken();
|
||||
|
@ -393,7 +403,7 @@ void PublicForwards::request(
|
|||
MessageFlags(),
|
||||
NewMessageType::Existing);
|
||||
nextToken.fullId = { peerId, msgId };
|
||||
result.push_back(nextToken.fullId);
|
||||
result.push_back({ .messageId = nextToken.fullId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,11 +458,79 @@ void PublicForwards::request(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void PublicForwards::requestStory(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done) {
|
||||
Expects(_fullId.storyId);
|
||||
|
||||
constexpr auto kLimit = tl::make_int(100);
|
||||
_requestId = makeRequest(MTPstats_GetStoryPublicForwards(
|
||||
channel()->input,
|
||||
MTP_int(_fullId.storyId.story),
|
||||
MTP_string(token.storyOffset),
|
||||
kLimit
|
||||
)).done([=, channel = channel()](
|
||||
const MTPstats_PublicForwards &tlForwards) {
|
||||
using Messages = QVector<Data::RecentPostId>;
|
||||
_requestId = 0;
|
||||
|
||||
const auto &data = tlForwards.data();
|
||||
|
||||
channel->owner().processUsers(data.vusers());
|
||||
channel->owner().processChats(data.vchats());
|
||||
|
||||
const auto nextToken = Data::PublicForwardsSlice::OffsetToken({
|
||||
.storyOffset = data.vnext_offset().value_or_empty(),
|
||||
});
|
||||
|
||||
const auto allLoaded = nextToken.storyOffset.isEmpty()
|
||||
|| (nextToken.storyOffset == token.storyOffset);
|
||||
const auto fullCount = data.vcount().v;
|
||||
|
||||
auto recentList = Messages();
|
||||
for (const auto &tlForward : data.vforwards().v) {
|
||||
tlForward.match([&](const MTPDpublicForwardMessage &data) {
|
||||
const auto &message = data.vmessage();
|
||||
const auto msgId = IdFromMessage(message);
|
||||
const auto peerId = PeerFromMessage(message);
|
||||
const auto lastDate = DateFromMessage(message);
|
||||
if (const auto peer = channel->owner().peerLoaded(peerId)) {
|
||||
if (!lastDate) {
|
||||
return;
|
||||
}
|
||||
channel->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 &) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_lastTotal = std::max(_lastTotal, fullCount);
|
||||
done({
|
||||
.list = std::move(recentList),
|
||||
.total = _lastTotal,
|
||||
.allLoaded = allLoaded,
|
||||
.token = nextToken,
|
||||
});
|
||||
}).fail([=] {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
MessageStatistics::MessageStatistics(
|
||||
not_null<ChannelData*> channel,
|
||||
FullMsgId fullId)
|
||||
: StatisticsRequestSender(channel)
|
||||
, _publicForwards(channel, fullId)
|
||||
, _publicForwards(channel, { .messageId = fullId })
|
||||
, _fullId(fullId) {
|
||||
}
|
||||
|
||||
|
@ -460,7 +538,7 @@ MessageStatistics::MessageStatistics(
|
|||
not_null<ChannelData*> channel,
|
||||
FullStoryId storyId)
|
||||
: StatisticsRequestSender(channel)
|
||||
, _publicForwards(channel, {})
|
||||
, _publicForwards(channel, { .storyId = storyId })
|
||||
, _storyId(storyId) {
|
||||
}
|
||||
|
||||
|
@ -476,7 +554,7 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
|
|||
const Data::StatisticalGraph &messageGraph,
|
||||
const Data::StatisticalGraph &reactionsGraph,
|
||||
const Data::StatisticsMessageInteractionInfo &info) {
|
||||
_publicForwards.request({}, [=](Data::PublicForwardsSlice slice) {
|
||||
const auto callback = [=](Data::PublicForwardsSlice slice) {
|
||||
const auto total = slice.total;
|
||||
_firstSlice = std::move(slice);
|
||||
done({
|
||||
|
@ -487,7 +565,8 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
|
|||
.views = info.viewsCount,
|
||||
.reactions = info.reactionsCount,
|
||||
});
|
||||
});
|
||||
};
|
||||
_publicForwards.request({}, callback);
|
||||
};
|
||||
|
||||
const auto requestPrivateForwards = [=](
|
||||
|
@ -553,22 +632,27 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
|
|||
MTP_vector<MTPint>(1, MTP_int(_storyId.story)))
|
||||
).done([=](const MTPstories_Stories &result) {
|
||||
const auto &storyItem = result.data().vstories().v.front();
|
||||
storyItem.match([&](const MTPDstoryItem &data) {
|
||||
auto info = storyItem.match([&](const MTPDstoryItem &data) {
|
||||
if (!data.vviews()) {
|
||||
return;
|
||||
return Data::StatisticsMessageInteractionInfo();
|
||||
}
|
||||
const auto &tlViews = data.vviews()->data();
|
||||
done({
|
||||
.messageInteractionGraph = messageGraph,
|
||||
.reactionsByEmotionGraph = reactionsGraph,
|
||||
.publicForwards = -1,
|
||||
.privateForwards = tlViews.vforwards_count().value_or(0),
|
||||
.views = tlViews.vviews_count().v,
|
||||
.reactions = tlViews.vreactions_count().value_or(0),
|
||||
});
|
||||
return Data::StatisticsMessageInteractionInfo{
|
||||
.storyId = data.vid().v,
|
||||
.viewsCount = tlViews.vviews_count().v,
|
||||
.forwardsCount = tlViews.vforwards_count().value_or(0),
|
||||
.reactionsCount = tlViews.vreactions_count().value_or(0),
|
||||
};
|
||||
}, [](const auto &) {
|
||||
return Data::StatisticsMessageInteractionInfo();
|
||||
});
|
||||
|
||||
requestFirstPublicForwards(
|
||||
messageGraph,
|
||||
reactionsGraph,
|
||||
std::move(info));
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
requestFirstPublicForwards(messageGraph, reactionsGraph, {});
|
||||
}).send();
|
||||
};
|
||||
|
||||
|
|
|
@ -68,14 +68,23 @@ private:
|
|||
|
||||
class PublicForwards final : public StatisticsRequestSender {
|
||||
public:
|
||||
PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId);
|
||||
PublicForwards(
|
||||
not_null<ChannelData*> channel,
|
||||
Data::RecentPostId fullId);
|
||||
|
||||
void request(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done);
|
||||
|
||||
private:
|
||||
const FullMsgId _fullId;
|
||||
void requestMessage(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done);
|
||||
void requestStory(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done);
|
||||
|
||||
const Data::RecentPostId _fullId;
|
||||
mtpRequestId _requestId = 0;
|
||||
int _lastTotal = 0;
|
||||
|
||||
|
|
|
@ -133,12 +133,27 @@ struct AnyStatistics final {
|
|||
Data::StoryStatistics story;
|
||||
};
|
||||
|
||||
struct RecentPostId final {
|
||||
FullMsgId messageId;
|
||||
FullStoryId storyId;
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return messageId || storyId;
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return valid();
|
||||
}
|
||||
friend inline auto operator<=>(RecentPostId, RecentPostId) = default;
|
||||
friend inline bool operator==(RecentPostId, RecentPostId) = default;
|
||||
};
|
||||
|
||||
struct PublicForwardsSlice final {
|
||||
struct OffsetToken final {
|
||||
int rate = 0;
|
||||
FullMsgId fullId;
|
||||
QString storyOffset;
|
||||
};
|
||||
QVector<FullMsgId> list;
|
||||
QVector<RecentPostId> list;
|
||||
int total = 0;
|
||||
bool allLoaded = false;
|
||||
OffsetToken token;
|
||||
|
|
|
@ -11,23 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Info::Statistics {
|
||||
|
||||
struct RecentPostId final {
|
||||
FullMsgId messageId;
|
||||
FullStoryId storyId;
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return messageId || storyId;
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return valid();
|
||||
}
|
||||
friend inline auto operator<=>(RecentPostId, RecentPostId) = default;
|
||||
friend inline bool operator==(RecentPostId, RecentPostId) = default;
|
||||
};
|
||||
|
||||
struct SavedState final {
|
||||
Data::AnyStatistics stats;
|
||||
base::flat_map<RecentPostId, QImage> recentPostPreviews;
|
||||
base::flat_map<Data::RecentPostId, QImage> recentPostPreviews;
|
||||
Data::PublicForwardsSlice publicForwardsFirstSlice;
|
||||
int recentPostsExpanded = 0;
|
||||
};
|
||||
|
|
|
@ -641,7 +641,7 @@ void InnerWidget::load() {
|
|||
.message = _contextId ? data : Data::StoryStatistics(),
|
||||
.story = _storyId ? data : Data::StoryStatistics(),
|
||||
};
|
||||
if (_contextId) {
|
||||
if (_contextId || _storyId) {
|
||||
_state.publicForwardsFirstSlice = api->firstSlice();
|
||||
}
|
||||
fill();
|
||||
|
@ -726,13 +726,14 @@ void InnerWidget::fill() {
|
|||
descriptor.peer,
|
||||
tr::lng_stats_inviters_title());
|
||||
}
|
||||
} else if (message) {
|
||||
} else if (_state.stats.message || _state.stats.story) {
|
||||
using namespace Data;
|
||||
AddPublicForwards(
|
||||
_state.publicForwardsFirstSlice,
|
||||
inner,
|
||||
[=](FullMsgId id) { _showRequests.fire({ .history = id }); },
|
||||
descriptor.peer,
|
||||
_contextId);
|
||||
RecentPostId{ .messageId = _contextId, .storyId = _storyId });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +763,7 @@ void InnerWidget::fillRecentPosts() {
|
|||
messageWrap,
|
||||
rpl::never<QString>(),
|
||||
st::statisticsRecentPostButton));
|
||||
const auto fullRecentId = RecentPostId{
|
||||
const auto fullRecentId = Data::RecentPostId{
|
||||
.messageId = maybeItem ? maybeItem->fullId() : FullMsgId(),
|
||||
.storyId = maybeStory ? maybeStory->fullId() : FullStoryId(),
|
||||
};
|
||||
|
@ -886,7 +887,8 @@ void InnerWidget::restoreState(not_null<Memento*> memento) {
|
|||
_state = memento->state();
|
||||
if (_state.stats.channel
|
||||
|| _state.stats.supergroup
|
||||
|| _state.stats.message) {
|
||||
|| _state.stats.message
|
||||
|| _state.stats.story) {
|
||||
fill();
|
||||
} else {
|
||||
load();
|
||||
|
|
|
@ -91,11 +91,11 @@ void AddSubtitle(
|
|||
return resultText;
|
||||
}
|
||||
|
||||
struct Descriptor final {
|
||||
struct PublicForwardsDescriptor final {
|
||||
Data::PublicForwardsSlice firstSlice;
|
||||
Fn<void(FullMsgId)> showPeerHistory;
|
||||
not_null<PeerData*> peer;
|
||||
FullMsgId contextId;
|
||||
Data::RecentPostId contextId;
|
||||
};
|
||||
|
||||
struct MembersDescriptor final {
|
||||
|
@ -229,7 +229,7 @@ void MembersController::rowClicked(not_null<PeerListRow*> row) {
|
|||
|
||||
class PublicForwardsController final : public PeerListController {
|
||||
public:
|
||||
explicit PublicForwardsController(Descriptor d);
|
||||
explicit PublicForwardsController(PublicForwardsDescriptor d);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void prepare() override;
|
||||
|
@ -251,7 +251,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
PublicForwardsController::PublicForwardsController(Descriptor d)
|
||||
PublicForwardsController::PublicForwardsController(PublicForwardsDescriptor d)
|
||||
: _session(&d.peer->session())
|
||||
, _showPeerHistory(std::move(d.showPeerHistory))
|
||||
, _api(d.peer->asChannel(), d.contextId)
|
||||
|
@ -282,8 +282,11 @@ void PublicForwardsController::applySlice(
|
|||
_apiToken = slice.token;
|
||||
|
||||
for (const auto &item : slice.list) {
|
||||
if (const auto peer = session().data().peerLoaded(item.peer)) {
|
||||
appendRow(peer, item.msg);
|
||||
// TODO support stories.
|
||||
if (const auto fullId = item.messageId) {
|
||||
if (const auto peer = session().data().peerLoaded(fullId.peer)) {
|
||||
appendRow(peer, fullId.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
|
@ -617,23 +620,24 @@ void AddPublicForwards(
|
|||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(FullMsgId)> showPeerHistory,
|
||||
not_null<PeerData*> peer,
|
||||
FullMsgId contextId) {
|
||||
Data::RecentPostId contextId) {
|
||||
if (!peer->isChannel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct State final {
|
||||
State(Descriptor d) : controller(std::move(d)) {
|
||||
State(PublicForwardsDescriptor d) : controller(std::move(d)) {
|
||||
}
|
||||
PeerListContentDelegateSimple delegate;
|
||||
PublicForwardsController controller;
|
||||
};
|
||||
const auto state = container->lifetime().make_state<State>(Descriptor{
|
||||
auto d = PublicForwardsDescriptor{
|
||||
firstSlice,
|
||||
std::move(showPeerHistory),
|
||||
peer,
|
||||
contextId,
|
||||
});
|
||||
};
|
||||
const auto state = container->lifetime().make_state<State>(std::move(d));
|
||||
|
||||
if (const auto total = firstSlice.total; total > 0) {
|
||||
AddSubtitle(
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Data {
|
|||
struct Boost;
|
||||
struct BoostsListSlice;
|
||||
struct PublicForwardsSlice;
|
||||
struct RecentPostId;
|
||||
struct SupergroupStatistics;
|
||||
} // namespace Data
|
||||
|
||||
|
@ -27,7 +28,7 @@ void AddPublicForwards(
|
|||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(FullMsgId)> showPeerHistory,
|
||||
not_null<PeerData*> peer,
|
||||
FullMsgId contextId);
|
||||
Data::RecentPostId contextId);
|
||||
|
||||
void AddMembersList(
|
||||
Data::SupergroupStatistics data,
|
||||
|
|
|
@ -349,7 +349,7 @@ void MessagePreview::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void MessagePreview::saveState(SavedState &state) const {
|
||||
if (!_lifetimeDownload) {
|
||||
const auto fullId = RecentPostId{ _messageId, _storyId };
|
||||
const auto fullId = Data::RecentPostId{ _messageId, _storyId };
|
||||
state.recentPostPreviews[fullId] = _preview;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue