mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Update API scheme. Show interactions in channel stories.
This commit is contained in:
parent
28d68acfe6
commit
1fb4a2f4ba
8 changed files with 198 additions and 15 deletions
|
@ -1353,6 +1353,96 @@ void Stories::loadViewsSlice(
|
|||
}
|
||||
}
|
||||
|
||||
void Stories::loadReactionsSlice(
|
||||
not_null<PeerData*> peer,
|
||||
StoryId id,
|
||||
QString offset,
|
||||
Fn<void(StoryViews)> done) {
|
||||
Expects(peer->isChannel());
|
||||
|
||||
if (_reactionsStoryPeer == peer
|
||||
&& _reactionsStoryId == id
|
||||
&& _reactionsOffset == offset) {
|
||||
if (_reactionsRequestId) {
|
||||
_reactionsDone = std::move(done);
|
||||
}
|
||||
return;
|
||||
}
|
||||
_reactionsStoryPeer = peer;
|
||||
_reactionsStoryId = id;
|
||||
_reactionsOffset = offset;
|
||||
_reactionsDone = std::move(done);
|
||||
|
||||
using Flag = MTPstories_GetStoryReactionsList::Flag;
|
||||
const auto api = &_owner->session().api();
|
||||
_owner->session().api().request(_reactionsRequestId).cancel();
|
||||
_reactionsRequestId = api->request(MTPstories_GetStoryReactionsList(
|
||||
MTP_flags(offset.isEmpty() ? Flag() : Flag::f_offset),
|
||||
_reactionsStoryPeer->input,
|
||||
MTP_int(_reactionsStoryId),
|
||||
MTPReaction(),
|
||||
MTP_string(_reactionsOffset),
|
||||
MTP_int(kViewsPerPage)
|
||||
)).done([=](const MTPstories_StoryReactionsList &result) {
|
||||
_reactionsRequestId = 0;
|
||||
|
||||
const auto &data = result.data();
|
||||
auto slice = StoryViews{
|
||||
.nextOffset = data.vnext_offset().value_or_empty(),
|
||||
.reactions = data.vcount().v,
|
||||
.total = data.vcount().v,
|
||||
};
|
||||
_owner->processUsers(data.vusers());
|
||||
_owner->processChats(data.vchats());
|
||||
slice.list.reserve(data.vreactions().v.size());
|
||||
for (const auto &reaction : data.vreactions().v) {
|
||||
reaction.match([&](const MTPDstoryReaction &data) {
|
||||
slice.list.push_back({
|
||||
.peer = _owner->peer(peerFromMTP(data.vpeer_id())),
|
||||
.reaction = ReactionFromMTP(data.vreaction()),
|
||||
.date = data.vdate().v,
|
||||
});
|
||||
}, [&](const MTPDstoryReactionPublicRepost &data) {
|
||||
const auto story = applySingle(
|
||||
peerFromMTP(data.vpeer_id()),
|
||||
data.vstory());
|
||||
if (story) {
|
||||
slice.list.push_back({
|
||||
.peer = story->peer(),
|
||||
.repostId = story->id(),
|
||||
});
|
||||
}
|
||||
}, [&](const MTPDstoryReactionPublicForward &data) {
|
||||
const auto item = _owner->addNewMessage(
|
||||
data.vmessage(),
|
||||
{},
|
||||
NewMessageType::Existing);
|
||||
if (item) {
|
||||
slice.list.push_back({
|
||||
.peer = item->history()->peer,
|
||||
.forwardId = item->id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const auto fullId = FullStoryId{
|
||||
.peer = _reactionsStoryPeer->id,
|
||||
.story = _reactionsStoryId,
|
||||
};
|
||||
if (const auto story = lookup(fullId)) {
|
||||
(*story)->applyChannelReactionsSlice(_reactionsOffset, slice);
|
||||
}
|
||||
if (const auto done = base::take(_reactionsDone)) {
|
||||
done(std::move(slice));
|
||||
}
|
||||
}).fail([=] {
|
||||
_reactionsRequestId = 0;
|
||||
if (const auto done = base::take(_reactionsDone)) {
|
||||
done({});
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
void Stories::sendViewsSliceRequest() {
|
||||
Expects(_viewsStoryPeer != nullptr);
|
||||
Expects(_viewsStoryPeer->isSelf());
|
||||
|
@ -1379,6 +1469,7 @@ void Stories::sendViewsSliceRequest() {
|
|||
.total = data.vcount().v,
|
||||
};
|
||||
_owner->processUsers(data.vusers());
|
||||
_owner->processChats(data.vchats());
|
||||
slice.list.reserve(data.vviews().v.size());
|
||||
for (const auto &view : data.vviews().v) {
|
||||
view.match([&](const MTPDstoryView &data) {
|
||||
|
|
|
@ -182,6 +182,11 @@ public:
|
|||
StoryId id,
|
||||
QString offset,
|
||||
Fn<void(StoryViews)> done);
|
||||
void loadReactionsSlice(
|
||||
not_null<PeerData*> peer,
|
||||
StoryId id,
|
||||
QString offset,
|
||||
Fn<void(StoryViews)> done);
|
||||
|
||||
[[nodiscard]] bool hasArchive(not_null<PeerData*> peer) const;
|
||||
|
||||
|
@ -379,6 +384,12 @@ private:
|
|||
Fn<void(StoryViews)> _viewsDone;
|
||||
mtpRequestId _viewsRequestId = 0;
|
||||
|
||||
PeerData *_reactionsStoryPeer = nullptr;
|
||||
StoryId _reactionsStoryId = 0;
|
||||
QString _reactionsOffset;
|
||||
Fn<void(StoryViews)> _reactionsDone;
|
||||
mtpRequestId _reactionsRequestId = 0;
|
||||
|
||||
base::flat_set<FullStoryId> _preloaded;
|
||||
std::vector<FullStoryId> _toPreloadSources[kStorySourcesListCount];
|
||||
std::vector<FullStoryId> _toPreloadViewer;
|
||||
|
|
|
@ -513,6 +513,10 @@ const StoryViews &Story::viewsList() const {
|
|||
return _views;
|
||||
}
|
||||
|
||||
const StoryViews &Story::channelReactionsList() const {
|
||||
return _channelReactions;
|
||||
}
|
||||
|
||||
int Story::interactions() const {
|
||||
return _views.total;
|
||||
}
|
||||
|
@ -543,6 +547,9 @@ void Story::applyViewsSlice(
|
|||
_views.known = true;
|
||||
if (offset.isEmpty()) {
|
||||
_views = slice;
|
||||
if (!_channelReactions.total) {
|
||||
_channelReactions.total = _views.reactions + _views.forwards;
|
||||
}
|
||||
} else if (_views.nextOffset == offset) {
|
||||
_views.list.insert(
|
||||
end(_views.list),
|
||||
|
@ -591,6 +598,33 @@ void Story::applyViewsSlice(
|
|||
}
|
||||
}
|
||||
|
||||
void Story::applyChannelReactionsSlice(
|
||||
const QString &offset,
|
||||
const StoryViews &slice) {
|
||||
const auto changed = (_channelReactions.reactions != slice.reactions)
|
||||
|| (_channelReactions.total != slice.total);
|
||||
_channelReactions.reactions = slice.reactions;
|
||||
_channelReactions.total = slice.total;
|
||||
_channelReactions.known = true;
|
||||
if (offset.isEmpty()) {
|
||||
_channelReactions = slice;
|
||||
} else if (_channelReactions.nextOffset == offset) {
|
||||
_channelReactions.list.insert(
|
||||
end(_channelReactions.list),
|
||||
begin(slice.list),
|
||||
end(slice.list));
|
||||
_channelReactions.nextOffset = slice.nextOffset;
|
||||
if (_channelReactions.nextOffset.isEmpty()) {
|
||||
_channelReactions.total = int(_channelReactions.list.size());
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
_peer->session().changes().storyUpdated(
|
||||
this,
|
||||
UpdateFlag::ViewsChanged);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<StoryLocation> &Story::locations() const {
|
||||
return _locations;
|
||||
}
|
||||
|
@ -793,6 +827,9 @@ void Story::updateViewsCounts(ViewsCounts &&counts, bool known, bool initial) {
|
|||
.total = total,
|
||||
.known = known,
|
||||
};
|
||||
if (!_channelReactions.total) {
|
||||
_channelReactions.total = _views.reactions + _views.forwards;
|
||||
}
|
||||
}
|
||||
if (viewsChanged) {
|
||||
_recentViewers = std::move(counts.viewers);
|
||||
|
|
|
@ -179,11 +179,15 @@ public:
|
|||
[[nodiscard]] auto recentViewers() const
|
||||
-> const std::vector<not_null<PeerData*>> &;
|
||||
[[nodiscard]] const StoryViews &viewsList() const;
|
||||
[[nodiscard]] const StoryViews &channelReactionsList() const;
|
||||
[[nodiscard]] int interactions() const;
|
||||
[[nodiscard]] int views() const;
|
||||
[[nodiscard]] int forwards() const;
|
||||
[[nodiscard]] int reactions() const;
|
||||
void applyViewsSlice(const QString &offset, const StoryViews &slice);
|
||||
void applyChannelReactionsSlice(
|
||||
const QString &offset,
|
||||
const StoryViews &slice);
|
||||
|
||||
[[nodiscard]] const std::vector<StoryLocation> &locations() const;
|
||||
[[nodiscard]] auto suggestedReactions() const
|
||||
|
@ -235,6 +239,7 @@ private:
|
|||
std::vector<StoryLocation> _locations;
|
||||
std::vector<SuggestedReaction> _suggestedReactions;
|
||||
StoryViews _views;
|
||||
StoryViews _channelReactions;
|
||||
const TimeId _date = 0;
|
||||
const TimeId _expires = 0;
|
||||
TimeId _lastUpdateTime = 0;
|
||||
|
|
|
@ -907,6 +907,7 @@ void Controller::show(
|
|||
.views = story->views(),
|
||||
.total = story->interactions(),
|
||||
.type = RecentViewsTypeFor(peer),
|
||||
.canViewReactions = CanViewReactionsFor(peer),
|
||||
}, _reactions->likedValue());
|
||||
if (const auto nowLikeButton = _recentViews->likeButton()) {
|
||||
if (wasLikeButton != nowLikeButton) {
|
||||
|
@ -998,13 +999,15 @@ void Controller::subscribeToSession() {
|
|||
show(update.story, _context);
|
||||
_delegate->storiesRedisplay(update.story);
|
||||
} else {
|
||||
const auto peer = update.story->peer();
|
||||
_recentViews->show({
|
||||
.list = update.story->recentViewers(),
|
||||
.reactions = update.story->reactions(),
|
||||
.forwards = update.story->forwards(),
|
||||
.views = update.story->views(),
|
||||
.total = update.story->interactions(),
|
||||
.type = RecentViewsTypeFor(update.story->peer()),
|
||||
.type = RecentViewsTypeFor(peer),
|
||||
.canViewReactions = CanViewReactionsFor(peer),
|
||||
});
|
||||
updateAreas(update.story);
|
||||
}
|
||||
|
@ -1414,11 +1417,19 @@ const Data::StoryViews &Controller::views(int limit, bool initial) {
|
|||
const auto done = viewsGotMoreCallback();
|
||||
const auto peer = shownPeer();
|
||||
auto &stories = peer->owner().stories();
|
||||
stories.loadViewsSlice(
|
||||
peer,
|
||||
_shown.story,
|
||||
_viewsSlice.nextOffset,
|
||||
done);
|
||||
if (peer->isChannel()) {
|
||||
stories.loadReactionsSlice(
|
||||
peer,
|
||||
_shown.story,
|
||||
_viewsSlice.nextOffset,
|
||||
done);
|
||||
} else {
|
||||
stories.loadViewsSlice(
|
||||
peer,
|
||||
_shown.story,
|
||||
_viewsSlice.nextOffset,
|
||||
done);
|
||||
}
|
||||
}
|
||||
return _viewsSlice;
|
||||
}
|
||||
|
@ -1433,7 +1444,11 @@ Fn<void(Data::StoryViews)> Controller::viewsGotMoreCallback() {
|
|||
const auto peer = shownPeer();
|
||||
auto &stories = peer->owner().stories();
|
||||
if (const auto maybeStory = stories.lookup(_shown)) {
|
||||
_viewsSlice = (*maybeStory)->viewsList();
|
||||
if (peer->isChannel()) {
|
||||
_viewsSlice = (*maybeStory)->channelReactionsList();
|
||||
} else {
|
||||
_viewsSlice = (*maybeStory)->viewsList();
|
||||
}
|
||||
} else {
|
||||
_viewsSlice = {};
|
||||
}
|
||||
|
@ -1596,8 +1611,12 @@ void Controller::refreshViewsFromData() {
|
|||
const auto peer = shownPeer();
|
||||
auto &stories = peer->owner().stories();
|
||||
const auto maybeStory = stories.lookup(_shown);
|
||||
if (!maybeStory || !peer->isSelf()) {
|
||||
const auto check = peer->isSelf()
|
||||
|| CanViewReactionsFor(peer);
|
||||
if (!maybeStory || !check) {
|
||||
_viewsSlice = {};
|
||||
} else if (peer->isChannel()) {
|
||||
_viewsSlice = (*maybeStory)->channelReactionsList();
|
||||
} else {
|
||||
_viewsSlice = (*maybeStory)->viewsList();
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_who_reacted.h" // FormatReadDate.
|
||||
#include "chat_helpers/compose/compose_show.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
|
@ -145,6 +146,13 @@ RecentViewsType RecentViewsTypeFor(not_null<PeerData*> peer) {
|
|||
: RecentViewsType::Other;
|
||||
}
|
||||
|
||||
bool CanViewReactionsFor(not_null<PeerData*> peer) {
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
return channel->amCreator() || channel->hasAdminRights();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RecentViews::RecentViews(not_null<Controller*> controller)
|
||||
: _controller(controller) {
|
||||
}
|
||||
|
@ -178,8 +186,10 @@ void RecentViews::show(
|
|||
|| (_data.forwards != data.forwards)
|
||||
|| (_data.reactions != data.reactions);
|
||||
const auto usersChanged = !_userpics || (_data.list != data.list);
|
||||
const auto canViewReactions = data.canViewReactions
|
||||
&& (data.reactions > 0 || data.forwards > 0);
|
||||
_data = data;
|
||||
if (_data.type != RecentViewsType::Self) {
|
||||
if (_data.type != RecentViewsType::Self && !canViewReactions) {
|
||||
_text = {};
|
||||
_clickHandlerLifetime.destroy();
|
||||
_userpicsLifetime.destroy();
|
||||
|
@ -229,7 +239,8 @@ Ui::RpWidget *RecentViews::likeIconWidget() const {
|
|||
}
|
||||
|
||||
void RecentViews::refreshClickHandler() {
|
||||
const auto nowEmpty = _data.list.empty();
|
||||
const auto nowEmpty = (_data.type != RecentViewsType::Channel)
|
||||
&& _data.list.empty();
|
||||
const auto wasEmpty = !_clickHandlerLifetime;
|
||||
const auto raw = _widget.get();
|
||||
if (wasEmpty == nowEmpty) {
|
||||
|
@ -389,13 +400,16 @@ void RecentViews::updateViewsReactionsGeometry() {
|
|||
void RecentViews::updatePartsGeometry() {
|
||||
const auto skip = st::storiesRecentViewsSkip;
|
||||
const auto full = _userpicsWidth + skip + _text.maxWidth();
|
||||
const auto add = (_data.type == RecentViewsType::Channel)
|
||||
? st::storiesViewsTextPosition.y()
|
||||
: 0;
|
||||
const auto use = std::min(full, _outer.width());
|
||||
const auto ux = _outer.x() + (_outer.width() - use) / 2;
|
||||
const auto uheight = st::storiesWhoViewed.userpics.size;
|
||||
const auto uy = _outer.y() + (_outer.height() - uheight) / 2;
|
||||
const auto uy = _outer.y() + (_outer.height() - uheight) / 2 + add;
|
||||
const auto tx = ux + _userpicsWidth + skip;
|
||||
const auto theight = st::normalFont->height;
|
||||
const auto ty = _outer.y() + (_outer.height() - theight) / 2;
|
||||
const auto ty = _outer.y() + (_outer.height() - theight) / 2 + add;
|
||||
const auto my = std::min(uy, ty);
|
||||
const auto mheight = std::max(uheight, theight);
|
||||
const auto padding = skip;
|
||||
|
@ -406,7 +420,9 @@ void RecentViews::updatePartsGeometry() {
|
|||
}
|
||||
|
||||
void RecentViews::updateText() {
|
||||
const auto text = _data.views
|
||||
const auto text = (_data.type == RecentViewsType::Channel)
|
||||
? u"View reactions"_q
|
||||
: _data.views
|
||||
? (tr::lng_stories_views(tr::now, lt_count, _data.views)
|
||||
+ (_data.reactions
|
||||
? (u" "_q + QChar(10084) + QString::number(_data.reactions))
|
||||
|
@ -417,7 +433,8 @@ void RecentViews::updateText() {
|
|||
}
|
||||
|
||||
void RecentViews::showMenu() {
|
||||
if (_menu || _data.list.empty()) {
|
||||
if (_menu
|
||||
|| (_data.type != RecentViewsType::Channel && _data.list.empty())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ struct RecentViewsData {
|
|||
int views = 0;
|
||||
int total = 0;
|
||||
RecentViewsType type = RecentViewsType::Other;
|
||||
bool canViewReactions = false;
|
||||
|
||||
friend inline auto operator<=>(
|
||||
const RecentViewsData &,
|
||||
|
@ -58,6 +59,7 @@ struct RecentViewsData {
|
|||
};
|
||||
|
||||
[[nodiscard]] RecentViewsType RecentViewsTypeFor(not_null<PeerData*> peer);
|
||||
[[nodiscard]] bool CanViewReactionsFor(not_null<PeerData*> peer);
|
||||
|
||||
class RecentViews final {
|
||||
public:
|
||||
|
|
|
@ -396,6 +396,7 @@ updateSentStoryReaction#7d627683 peer:Peer story_id:int reaction:Reaction = Upda
|
|||
updateBotChatBoost#904dd49c peer:Peer boost:Boost qts:int = Update;
|
||||
updateChannelViewForumAsMessages#7b68920 channel_id:long enabled:Bool = Update;
|
||||
updatePeerWallpaper#ae3f101d flags:# wallpaper_overridden:flags.1?true peer:Peer wallpaper:flags.0?WallPaper = Update;
|
||||
updateBotMessageReaction#ac21d3ce peer:Peer msg_id:int date:int actor:Peer old_reactions:Vector<Reaction> new_reactions:Vector<Reaction> qts:int = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
@ -1558,7 +1559,7 @@ storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?
|
|||
storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true message:Message = StoryView;
|
||||
storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
|
||||
|
||||
stories.storyViewsList#19a16886 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
|
||||
stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
|
||||
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue