Update API scheme on layer 161.

This commit is contained in:
John Preston 2023-08-04 16:49:58 +02:00
parent 6be1a05876
commit 318d75cc63
8 changed files with 100 additions and 146 deletions

View File

@ -862,7 +862,8 @@ void Stories::activateStealthMode(Fn<void()> done) {
using Flag = MTPstories_ActivateStealthMode::Flag;
api->request(MTPstories_ActivateStealthMode(
MTP_flags(Flag::f_past | Flag::f_future)
)).done([=](const MTPBool &result) {
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
if (done) done();
}).fail([=] {
if (done) done();
@ -1233,11 +1234,11 @@ void Stories::sendIncrementViewsRequests() {
void Stories::loadViewsSlice(
StoryId id,
std::optional<StoryView> offset,
Fn<void(std::vector<StoryView>)> done) {
QString offset,
Fn<void(StoryViews)> done) {
if (_viewsStoryId == id
&& _viewsOffset == offset
&& (offset || _viewsRequestId)) {
&& (!offset.isEmpty() || _viewsRequestId)) {
if (_viewsRequestId) {
_viewsDone = std::move(done);
}
@ -1251,21 +1252,27 @@ void Stories::loadViewsSlice(
const auto perPage = _viewsDone ? kViewsPerPage : kPollingViewsPerPage;
api->request(_viewsRequestId).cancel();
_viewsRequestId = api->request(MTPstories_GetStoryViewsList(
MTP_flags(0),
MTPstring(), // q
MTP_int(id),
MTP_int(offset ? offset->date : 0),
MTP_long(offset ? peerToUser(offset->peer->id).bare : 0),
MTP_string(offset),
MTP_int(perPage)
)).done([=](const MTPstories_StoryViewsList &result) {
_viewsRequestId = 0;
auto slice = std::vector<StoryView>();
const auto &data = result.data();
auto slice = StoryViews{
.nextOffset = data.vnext_offset().value_or_empty(),
.total = data.vcount().v,
};
_owner->processUsers(data.vusers());
slice.reserve(data.vviews().v.size());
slice.list.reserve(data.vviews().v.size());
for (const auto &view : data.vviews().v) {
slice.push_back({
slice.list.push_back({
.peer = _owner->peer(peerFromUser(view.data().vuser_id())),
.reaction = (view.data().vreaction()
? ReactionFromMTP(*view.data().vreaction())
: Data::ReactionId()),
.date = view.data().vdate().v,
});
}
@ -1274,7 +1281,7 @@ void Stories::loadViewsSlice(
.story = _viewsStoryId,
};
if (const auto story = lookup(fullId)) {
(*story)->applyViewsSlice(_viewsOffset, slice, data.vcount().v);
(*story)->applyViewsSlice(_viewsOffset, slice);
}
if (const auto done = base::take(_viewsDone)) {
done(std::move(slice));
@ -1713,7 +1720,7 @@ void Stories::sendPollingViewsRequests() {
return;
} else if (!_viewsRequestId) {
Assert(_viewsDone == nullptr);
loadViewsSlice(_pollingViews.front()->id(), std::nullopt, nullptr);
loadViewsSlice(_pollingViews.front()->id(), QString(), nullptr);
}
_pollingViewsTimer.callOnce(kPollViewsInterval);
}

View File

@ -179,8 +179,8 @@ public:
static constexpr auto kViewsPerPage = 50;
void loadViewsSlice(
StoryId id,
std::optional<StoryView> offset,
Fn<void(std::vector<StoryView>)> done);
QString offset,
Fn<void(StoryViews)> done);
[[nodiscard]] const StoriesIds &archive() const;
[[nodiscard]] rpl::producer<> archiveChanged() const;
@ -366,8 +366,8 @@ private:
base::flat_set<PeerId> _incrementViewsRequests;
StoryId _viewsStoryId = 0;
std::optional<StoryView> _viewsOffset;
Fn<void(std::vector<StoryView>)> _viewsDone;
QString _viewsOffset;
Fn<void(StoryViews)> _viewsDone;
mtpRequestId _viewsRequestId = 0;
base::flat_set<FullStoryId> _preloaded;

View File

@ -339,51 +339,35 @@ const std::vector<not_null<PeerData*>> &Story::recentViewers() const {
return _recentViewers;
}
const std::vector<StoryView> &Story::viewsList() const {
return _viewsList;
}
int Story::views() const {
const StoryViews &Story::viewsList() const {
return _views;
}
int Story::views() const {
return _views.total;
}
void Story::applyViewsSlice(
const std::optional<StoryView> &offset,
const std::vector<StoryView> &slice,
int total) {
const auto changed = (_views != total);
_views = total;
if (!offset) {
const auto i = _viewsList.empty()
? end(slice)
: ranges::find(slice, _viewsList.front());
const auto merge = (i != end(slice))
&& !ranges::contains(slice, _viewsList.back());
if (merge) {
_viewsList.insert(begin(_viewsList), begin(slice), i);
} else {
_viewsList = slice;
}
} else if (!slice.empty()) {
const auto i = ranges::find(_viewsList, *offset);
const auto merge = (i != end(_viewsList))
&& !ranges::contains(_viewsList, slice.back());
if (merge) {
const auto after = i + 1;
if (after == end(_viewsList)) {
_viewsList.insert(after, begin(slice), end(slice));
} else {
const auto j = ranges::find(slice, _viewsList.back());
if (j != end(slice)) {
_viewsList.insert(end(_viewsList), j + 1, end(slice));
}
}
const QString &offset,
const StoryViews &slice) {
const auto changed = (_views.total != slice.total);
_views.total = slice.total;
if (offset.isEmpty()) {
_views = slice;
} else if (_views.nextOffset == offset) {
_views.list.insert(
end(_views.list),
begin(slice.list),
end(slice.list));
_views.nextOffset = slice.nextOffset;
if (_views.nextOffset.isEmpty()) {
_views.total = int(_views.list.size());
}
}
const auto known = int(_viewsList.size());
const auto known = int(_views.list.size());
if (known >= _recentViewers.size()) {
const auto take = std::min(known, kRecentViewersMax);
auto viewers = _viewsList
auto viewers = _views.list
| ranges::views::take(take)
| ranges::views::transform(&StoryView::peer)
| ranges::to_vector;
@ -436,7 +420,7 @@ void Story::applyFields(
&owner().session(),
data.ventities().value_or_empty()),
};
auto views = _views;
auto views = _views.total;
auto viewers = std::vector<not_null<PeerData*>>();
if (!data.is_min()) {
if (const auto info = data.vviews()) {
@ -457,7 +441,7 @@ void Story::applyFields(
const auto editedChanged = (_edited != edited);
const auto mediaChanged = (_media != media);
const auto captionChanged = (_caption != caption);
const auto viewsChanged = (_views != views)
const auto viewsChanged = (_views.total != views)
|| (_recentViewers != viewers);
_privacyPublic = (privacy == StoryPrivacy::Public);
@ -468,8 +452,10 @@ void Story::applyFields(
_edited = edited;
_pinned = pinned;
_noForwards = noForwards;
if (_views.total != views) {
_views = StoryViews{ .total = views };
}
if (viewsChanged) {
_views = views;
_recentViewers = std::move(viewers);
}
if (mediaChanged) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/weak_ptr.h"
#include "data/data_message_reaction_id.h"
class Image;
class PhotoData;
@ -58,11 +59,18 @@ struct StoryMedia {
struct StoryView {
not_null<PeerData*> peer;
Data::ReactionId reaction;
TimeId date = 0;
friend inline bool operator==(StoryView, StoryView) = default;
};
struct StoryViews {
std::vector<StoryView> list;
QString nextOffset;
int total = 0;
};
class Story final {
public:
Story(
@ -115,12 +123,9 @@ public:
[[nodiscard]] auto recentViewers() const
-> const std::vector<not_null<PeerData*>> &;
[[nodiscard]] const std::vector<StoryView> &viewsList() const;
[[nodiscard]] const StoryViews &viewsList() const;
[[nodiscard]] int views() const;
void applyViewsSlice(
const std::optional<StoryView> &offset,
const std::vector<StoryView> &slice,
int total);
void applyViewsSlice(const QString &offset, const StoryViews &slice);
void applyChanges(
StoryMedia media,
@ -140,8 +145,7 @@ private:
StoryMedia _media;
TextWithEntities _caption;
std::vector<not_null<PeerData*>> _recentViewers;
std::vector<StoryView> _viewsList;
int _views = 0;
StoryViews _views;
const TimeId _date = 0;
const TimeId _expires = 0;
TimeId _lastUpdateTime = 0;

View File

@ -1254,12 +1254,17 @@ SiblingView Controller::sibling(SiblingType type) const {
return {};
}
ViewsSlice Controller::views(PeerId offset) {
const Data::StoryViews &Controller::views(int limit, bool initial) {
invalidate_weak_ptrs(&_viewsLoadGuard);
if (!offset) {
if (initial) {
refreshViewsFromData();
} else if (!sliceViewsTo(offset)) {
return { .left = _viewsSlice.left };
}
if (_viewsSlice.total > _viewsSlice.list.size()
&& _viewsSlice.list.size() < limit) {
const auto done = viewsGotMoreCallback();
const auto user = shownUser();
auto &stories = user->owner().stories();
stories.loadViewsSlice(_shown.story, _viewsSlice.nextOffset, done);
}
return _viewsSlice;
}
@ -1268,27 +1273,25 @@ rpl::producer<> Controller::moreViewsLoaded() const {
return _moreViewsLoaded.events();
}
Fn<void(std::vector<Data::StoryView>)> Controller::viewsGotMoreCallback() {
return crl::guard(&_viewsLoadGuard, [=](
const std::vector<Data::StoryView> &result) {
Fn<void(Data::StoryViews)> Controller::viewsGotMoreCallback() {
return crl::guard(&_viewsLoadGuard, [=](Data::StoryViews result) {
if (_viewsSlice.list.empty()) {
const auto user = shownUser();
auto &stories = user->owner().stories();
if (const auto maybeStory = stories.lookup(_shown)) {
_viewsSlice = {
.list = result,
.left = (*maybeStory)->views() - int(result.size()),
};
_viewsSlice = (*maybeStory)->viewsList();
} else {
_viewsSlice = {};
}
} else {
_viewsSlice.list.insert(
end(_viewsSlice.list),
begin(result),
end(result));
_viewsSlice.left
= std::max(_viewsSlice.left - int(result.size()), 0);
begin(result.list),
end(result.list));
_viewsSlice.total = result.nextOffset.isEmpty()
? int(_viewsSlice.list.size())
: std::max(result.total, int(_viewsSlice.list.size()));
_viewsSlice.nextOffset = result.nextOffset;
}
_moreViewsLoaded.fire({});
});
@ -1439,46 +1442,9 @@ void Controller::refreshViewsFromData() {
return;
}
const auto story = *maybeStory;
const auto &list = story->viewsList();
const auto &views = story->viewsList();
const auto total = story->views();
_viewsSlice.list = list
| ranges::views::take(Data::Stories::kViewsPerPage)
| ranges::to_vector;
_viewsSlice.left = total - int(_viewsSlice.list.size());
if (_viewsSlice.list.empty() && _viewsSlice.left > 0) {
const auto done = viewsGotMoreCallback();
stories.loadViewsSlice(_shown.story, std::nullopt, done);
}
}
bool Controller::sliceViewsTo(PeerId offset) {
Expects(shown());
const auto user = shownUser();
auto &stories = user->owner().stories();
const auto maybeStory = stories.lookup(_shown);
if (!maybeStory || !user->isSelf()) {
_viewsSlice = {};
return true;
}
const auto story = *maybeStory;
const auto &list = story->viewsList();
const auto proj = [&](const Data::StoryView &single) {
return single.peer->id;
};
const auto i = ranges::find(list, _viewsSlice.list.back());
const auto add = (i != end(list)) ? int(end(list) - i - 1) : 0;
const auto j = ranges::find(_viewsSlice.list, offset, proj);
Assert(j != end(_viewsSlice.list));
if (!add && (j + 1) == end(_viewsSlice.list)) {
const auto done = viewsGotMoreCallback();
stories.loadViewsSlice(_shown.story, _viewsSlice.list.back(), done);
return false;
}
_viewsSlice.list.erase(begin(_viewsSlice.list), j + 1);
_viewsSlice.list.insert(end(_viewsSlice.list), i + 1, end(list));
_viewsSlice.left -= add;
return true;
_viewsSlice = story->viewsList();
}
void Controller::unfocusReply() {

View File

@ -104,11 +104,6 @@ struct Layout {
friend inline bool operator==(Layout, Layout) = default;
};
struct ViewsSlice {
std::vector<Data::StoryView> list;
int left = 0;
};
class Controller final : public base::has_weak_ptr {
public:
explicit Controller(not_null<Delegate*> delegate);
@ -158,7 +153,7 @@ public:
void repaintSibling(not_null<Sibling*> sibling);
[[nodiscard]] SiblingView sibling(SiblingType type) const;
[[nodiscard]] ViewsSlice views(PeerId offset);
[[nodiscard]] const Data::StoryViews &views(int limit, bool initial);
[[nodiscard]] rpl::producer<> moreViewsLoaded() const;
void unfocusReply();
@ -221,9 +216,8 @@ private:
void moveFromShown();
void refreshViewsFromData();
bool sliceViewsTo(PeerId offset);
[[nodiscard]] auto viewsGotMoreCallback()
-> Fn<void(std::vector<Data::StoryView>)>;
-> Fn<void(Data::StoryViews)>;
[[nodiscard]] bool shown() const;
[[nodiscard]] UserData *shownUser() const;
@ -285,7 +279,7 @@ private:
int _cachedSourceIndex = -1;
bool _showingUnreadSources = false;
ViewsSlice _viewsSlice;
Data::StoryViews _viewsSlice;
rpl::event_stream<> _moreViewsLoaded;
base::has_weak_ptr _viewsLoadGuard;

View File

@ -264,8 +264,8 @@ void RecentViews::showMenu() {
return;
}
const auto views = _controller->views(PeerId());
if (views.list.empty() && !views.left) {
const auto views = _controller->views(kAddPerPage * 2, true);
if (views.list.empty() && !views.total) {
return;
}
@ -276,7 +276,7 @@ void RecentViews::showMenu() {
st::storiesViewsMenu);
auto count = 0;
const auto added = std::min(int(views.list.size()), kAddPerPage);
const auto add = std::min(added + views.left, kAddPerPage);
const auto add = std::min(views.total, kAddPerPage);
const auto now = QDateTime::currentDateTime();
for (const auto &entry : views.list) {
addMenuRow(entry, now);
@ -393,23 +393,18 @@ void RecentViews::addMenuRowPlaceholder() {
}
void RecentViews::rebuildMenuTail() {
const auto offset = (_menuPlaceholderCount < _menuEntries.size())
? (end(_menuEntries) - _menuPlaceholderCount - 1)->peer->id
: PeerId();
const auto views = _controller->views(offset);
if (views.list.empty()) {
const auto elements = _menuEntries.size() - _menuPlaceholderCount;
const auto views = _controller->views(elements + kAddPerPage, false);
if (views.list.size() <= elements) {
return;
}
const auto now = QDateTime::currentDateTime();
const auto added = std::min(
_menuPlaceholderCount + kAddPerPage,
int(views.list.size()));
auto add = added;
for (const auto &entry : views.list) {
int(views.list.size() - elements));
for (auto i = elements, till = i + added; i != till; ++i) {
const auto &entry = views.list[i];
addMenuRow(entry, now);
if (!--add) {
break;
}
}
_menuEntriesCount = _menuEntriesCount.current() + added;
}

View File

@ -386,6 +386,7 @@ updateStory#205a4133 user_id:long story:StoryItem = Update;
updateReadStories#feb5345a user_id:long max_id:int = Update;
updateStoryID#1bf335b9 id:int random_id:long = Update;
updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = Update;
updateSentStoryReaction#e3a73d20 user_id:long story_id:int reaction:Reaction = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -1527,11 +1528,11 @@ messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector<bytes> date:int = Mess
sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage;
storyViews#d36760cf flags:# views_count:int recent_viewers:flags.0?Vector<long> = StoryViews;
storyViews#c64c0b97 flags:# views_count:int reactions_count:int recent_viewers:flags.0?Vector<long> = StoryViews;
storyItemDeleted#51e6ee4f id:int = StoryItem;
storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem;
storyItem#945953ba flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews = StoryItem;
storyItem#44c457ce flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories;
@ -1542,9 +1543,9 @@ stories.stories#4fe57df1 count:int stories:Vector<StoryItem> users:Vector<User>
stories.userStories#37a6ff5f stories:UserStories users:Vector<User> = stories.UserStories;
storyView#d0b0a7de flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int = StoryView;
storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
stories.storyViewsList#fb3f77ac count:int views:Vector<StoryView> users:Vector<User> = stories.StoryViewsList;
stories.storyViewsList#46e9b9ec flags:# count:int reactions_count:int views:Vector<StoryView> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
@ -2111,8 +2112,9 @@ stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
stories.getAllReadUserStories#729c562c = Updates;
stories.readStories#edc5105b user_id:InputUser max_id:int = Vector<int>;
stories.incrementStoryViews#22126127 user_id:InputUser id:Vector<int> = Bool;
stories.getStoryViewsList#4b3b5e97 id:int offset_date:int offset_id:long limit:int = stories.StoryViewsList;
stories.getStoryViewsList#f95f61a4 flags:# just_contacts:flags.0?true q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList;
stories.getStoriesViews#9a75d6a6 id:Vector<int> = stories.StoryViews;
stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink;
stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool;
stories.activateStealthMode#11d7ddae flags:# past:flags.0?true future:flags.1?true = Bool;
stories.activateStealthMode#57bbd166 flags:# past:flags.0?true future:flags.1?true = Updates;
stories.sendReaction#49aaa9b3 flags:# add_to_recent:flags.0?true user_id:InputUser story_id:int reaction:Reaction = Updates;