2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Support correct saved stories / archive loading.

This commit is contained in:
John Preston
2023-06-07 19:56:38 +04:00
parent 7f8a985067
commit 5e5b252f2f
15 changed files with 382 additions and 162 deletions

View File

@@ -33,8 +33,8 @@ constexpr auto kMaxResolveTogether = 100;
constexpr auto kIgnorePreloadAroundIfLoaded = 15;
constexpr auto kPreloadAroundCount = 30;
constexpr auto kMarkAsReadDelay = 3 * crl::time(1000);
constexpr auto kExpiredMineFirstPerPage = 30;
constexpr auto kExpiredMinePerPage = 100;
constexpr auto kArchiveFirstPerPage = 30;
constexpr auto kArchivePerPage = 100;
constexpr auto kSavedFirstPerPage = 30;
constexpr auto kSavedPerPage = 100;
@@ -333,6 +333,9 @@ void Stories::apply(const MTPDupdateStory &data) {
const auto wasInfo = i->second.info();
i->second.ids.emplace(idDates);
const auto nowInfo = i->second.info();
if (user->isSelf() && i->second.readTill < idDates.id) {
i->second.readTill = idDates.id;
}
if (wasInfo == nowInfo) {
return;
}
@@ -361,15 +364,44 @@ void Stories::apply(not_null<PeerData*> peer, const MTPUserStories *data) {
if (i != end(_stories)) {
auto stories = base::take(i->second);
_stories.erase(i);
auto archiveChanged = false;
auto savedChanged = false;
if (peer->isSelf()) {
for (const auto &[id, story] : stories) {
if (_archive.list.remove(id)) {
archiveChanged = true;
if (_archiveTotal > 0) {
--_archiveTotal;
}
}
}
}
const auto j = _saved.find(peer->id);
const auto saved = (j != end(_saved)) ? &j->second : nullptr;
for (const auto &[id, story] : stories) {
// Duplicated in Stories::applyDeleted.
_deleted.emplace(FullStoryId{ peer->id, id });
_expiring.remove(story->expires(), story->fullId());
if (story->pinned() && saved) {
if (saved->ids.list.remove(id)) {
savedChanged = true;
if (saved->total > 0) {
--saved->total;
}
}
}
session().changes().storyUpdated(
story.get(),
UpdateFlag::Destroyed);
removeDependencyStory(story.get());
}
if (archiveChanged) {
_archiveChanged.fire({});
}
if (savedChanged) {
_savedChanged.fire_copy(peer->id);
}
}
_sourceChanged.fire_copy(peer->id);
} else {
@@ -471,6 +503,8 @@ void Stories::parseAndApply(const MTPUserStories &stories) {
if (result.ids.empty()) {
applyDeletedFromSources(peerId, StorySourcesList::All);
return;
} else if (user->isSelf()) {
result.readTill = result.ids.back().id;
}
const auto info = result.info();
const auto i = _all.find(peerId);
@@ -526,15 +560,20 @@ Story *Stories::parseAndApply(
auto &stories = _stories[peer->id];
const auto i = stories.find(id);
if (i != end(stories)) {
if (i->second->applyChanges(*media, data)) {
const auto result = i->second.get();
const auto pinned = result->pinned();
if (result->applyChanges(*media, data)) {
if (result->pinned() != pinned) {
savedStateUpdated(result);
}
session().changes().storyUpdated(
i->second.get(),
result,
UpdateFlag::Edited);
if (const auto item = lookupItem(i->second.get())) {
item->applyChanges(i->second.get());
if (const auto item = lookupItem(result)) {
item->applyChanges(result);
}
}
return i->second.get();
return result;
}
const auto result = stories.emplace(id, std::make_unique<Story>(
id,
@@ -543,6 +582,19 @@ Story *Stories::parseAndApply(
data.vdate().v,
data.vexpire_date().v)).first->second.get();
result->applyChanges(*media, data);
if (result->pinned()) {
savedStateUpdated(result);
}
if (peer->isSelf()) {
const auto added = _archive.list.emplace(id).second;
if (added) {
if (_archiveTotal >= 0 && id > _archiveLastId) {
++_archiveTotal;
}
_archiveChanged.fire({});
}
}
if (expired) {
_expiring.remove(expires, result->fullId());
@@ -617,6 +669,30 @@ void Stories::unregisterDependentMessage(
}
}
void Stories::savedStateUpdated(not_null<Story*> story) {
const auto id = story->id();
const auto peer = story->peer()->id;
const auto pinned = story->pinned();
if (pinned) {
auto &saved = _saved[peer];
const auto added = saved.ids.list.emplace(id).second;
if (added) {
if (saved.total >= 0 && id > saved.lastId) {
++saved.total;
}
_savedChanged.fire_copy(peer);
}
} else if (const auto i = _saved.find(peer); i != end(_saved)) {
auto &saved = i->second;
if (saved.ids.list.remove(id)) {
if (saved.total > 0) {
--saved.total;
}
_savedChanged.fire_copy(peer);
}
}
}
void Stories::loadMore(StorySourcesList list) {
const auto index = static_cast<int>(list);
if (_loadMoreRequestId[index] || _sourcesLoaded[index]) {
@@ -744,20 +820,38 @@ void Stories::applyDeleted(FullStoryId id) {
applyRemovedFromActive(id);
_deleted.emplace(id);
const auto j = _stories.find(id.peer);
if (j != end(_stories)) {
const auto k = j->second.find(id.story);
if (k != end(j->second)) {
const auto i = _stories.find(id.peer);
if (i != end(_stories)) {
const auto j = i->second.find(id.story);
if (j != end(i->second)) {
// Duplicated in Stories::apply(peer, const MTPUserStories*).
auto story = std::move(k->second);
auto story = std::move(j->second);
_expiring.remove(story->expires(), story->fullId());
j->second.erase(k);
i->second.erase(j);
session().changes().storyUpdated(
story.get(),
UpdateFlag::Destroyed);
removeDependencyStory(story.get());
if (j->second.empty()) {
_stories.erase(j);
if (id.peer == session().userPeerId()
&& _archive.list.remove(id.story)) {
if (_archiveTotal > 0) {
--_archiveTotal;
}
_archiveChanged.fire({});
}
if (story->pinned()) {
if (const auto k = _saved.find(id.peer); k != end(_saved)) {
const auto saved = &k->second;
if (saved->ids.list.remove(id.story)) {
if (saved->total > 0) {
--saved->total;
}
_savedChanged.fire_copy(id.peer);
}
}
}
if (i->second.empty()) {
_stories.erase(i);
}
}
}
@@ -766,9 +860,7 @@ void Stories::applyDeleted(FullStoryId id) {
void Stories::applyExpired(FullStoryId id) {
if (const auto maybeStory = lookup(id)) {
const auto story = *maybeStory;
if (story->peer()->isSelf()) {
addToExpiredMine(story);
} else if (!story->pinned()) {
if (!story->peer()->isSelf() && !story->pinned()) {
applyDeleted(id);
return;
}
@@ -776,13 +868,6 @@ void Stories::applyExpired(FullStoryId id) {
applyRemovedFromActive(id);
}
void Stories::addToExpiredMine(not_null<Story*> story) {
const auto added = _expiredMine.list.emplace(story->id()).second;
if (added && _expiredMineTotal >= 0) {
++_expiredMineTotal;
}
}
void Stories::applyRemovedFromActive(FullStoryId id) {
const auto removeFromList = [&](StorySourcesList list) {
const auto index = static_cast<int>(list);
@@ -1172,24 +1257,24 @@ void Stories::loadViewsSlice(
}).send();
}
const StoriesIds &Stories::expiredMine() const {
return _expiredMine;
const StoriesIds &Stories::archive() const {
return _archive;
}
rpl::producer<> Stories::expiredMineChanged() const {
return _expiredMineChanged.events();
rpl::producer<> Stories::archiveChanged() const {
return _archiveChanged.events();
}
int Stories::expiredMineCount() const {
return std::max(_expiredMineTotal, 0);
int Stories::archiveCount() const {
return std::max(_archiveTotal, 0);
}
bool Stories::expiredMineCountKnown() const {
return _expiredMineTotal >= 0;
bool Stories::archiveCountKnown() const {
return _archiveTotal >= 0;
}
bool Stories::expiredMineLoaded() const {
return _expiredMineLoaded;
bool Stories::archiveLoaded() const {
return _archiveLoaded;
}
const StoriesIds *Stories::saved(PeerId peerId) const {
@@ -1216,46 +1301,43 @@ bool Stories::savedLoaded(PeerId peerId) const {
return (i != end(_saved)) && i->second.loaded;
}
void Stories::expiredMineLoadMore() {
if (_expiredMineRequestId) {
void Stories::archiveLoadMore() {
if (_archiveRequestId || _archiveLoaded) {
return;
}
const auto api = &_owner->session().api();
_expiredMineRequestId = api->request(MTPstories_GetExpiredStories(
MTP_int(_expiredMineLastId),
MTP_int(_expiredMineLastId
? kExpiredMinePerPage
: kExpiredMineFirstPerPage)
_archiveRequestId = api->request(MTPstories_GetStoriesArchive(
MTP_int(_archiveLastId),
MTP_int(_archiveLastId ? kArchivePerPage : kArchiveFirstPerPage)
)).done([=](const MTPstories_Stories &result) {
_expiredMineRequestId = 0;
_archiveRequestId = 0;
const auto &data = result.data();
const auto self = _owner->session().user();
const auto now = base::unixtime::now();
_expiredMineTotal = data.vcount().v;
_archiveTotal = data.vcount().v;
for (const auto &story : data.vstories().v) {
const auto id = story.match([&](const auto &id) {
return id.vid().v;
});
_expiredMine.list.emplace(id);
_expiredMineLastId = id;
_archive.list.emplace(id);
_archiveLastId = id;
if (!parseAndApply(self, story, now)) {
_expiredMine.list.remove(id);
if (_expiredMineTotal > 0) {
--_expiredMineTotal;
_archive.list.remove(id);
if (_archiveTotal > 0) {
--_archiveTotal;
}
}
}
_expiredMineTotal = std::max(
_expiredMineTotal,
int(_expiredMine.list.size()));
_expiredMineLoaded = data.vstories().v.empty();
_expiredMineChanged.fire({});
const auto ids = int(_archive.list.size());
_archiveLoaded = data.vstories().v.empty();
_archiveTotal = _archiveLoaded ? ids : std::max(_archiveTotal, ids);
_archiveChanged.fire({});
}).fail([=] {
_expiredMineRequestId = 0;
_expiredMineLoaded = true;
_expiredMineTotal = int(_expiredMine.list.size());
_expiredMineChanged.fire({});
_archiveRequestId = 0;
_archiveLoaded = true;
_archiveTotal = int(_archive.list.size());
_archiveChanged.fire({});
}).send();
}
@@ -1263,7 +1345,7 @@ void Stories::savedLoadMore(PeerId peerId) {
Expects(peerIsUser(peerId));
auto &saved = _saved[peerId];
if (saved.requestId) {
if (saved.requestId || saved.loaded) {
return;
}
const auto api = &_owner->session().api();
@@ -1292,8 +1374,9 @@ void Stories::savedLoadMore(PeerId peerId) {
}
}
}
saved.total = std::max(saved.total, int(saved.ids.list.size()));
const auto ids = int(saved.ids.list.size());
saved.loaded = data.vstories().v.empty();
saved.total = saved.loaded ? ids : std::max(saved.total, ids);
_savedChanged.fire_copy(peerId);
}).fail([=] {
auto &saved = _saved[peerId];