2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-31 22:46:10 +00:00

Allow loading stories in different albums.

This commit is contained in:
John Preston
2025-07-28 11:36:58 +04:00
parent c8015898ff
commit 1c251a308a
14 changed files with 283 additions and 352 deletions

View File

@@ -353,15 +353,7 @@ void Stories::processExpired() {
}
Stories::Set *Stories::lookupArchive(not_null<PeerData*> peer) {
const auto peerId = peer->id;
if (hasArchive(peer)) {
const auto i = _archive.find(peerId);
return (i != end(_archive))
? &i->second
: &_archive.emplace(peerId, Set()).first->second;
}
clearArchive(peer);
return nullptr;
return albumIdsSet(peer->id, kStoriesAlbumIdArchive);
}
void Stories::clearArchive(not_null<PeerData*> peer) {
@@ -379,7 +371,7 @@ void Stories::clearArchive(not_null<PeerData*> peer) {
}
}
}
_archiveChanged.fire_copy(peerId);
_albumIdsChanged.fire({ peerId, kStoriesAlbumIdArchive });
}
void Stories::parseAndApply(
@@ -523,7 +515,7 @@ Story *Stories::parseAndApply(
if (archive->total >= 0 && id > archive->lastId) {
++archive->total;
}
_archiveChanged.fire_copy(peer->id);
_albumIdsChanged.fire({ peer->id, kStoriesAlbumIdArchive });
}
}
@@ -615,7 +607,7 @@ void Stories::savedStateChanged(not_null<Story*> story) {
if (saved.total >= 0 && id > saved.lastId) {
++saved.total;
}
_savedChanged.fire_copy(peer);
_albumIdsChanged.fire({ peer, kStoriesAlbumIdSaved });
}
} else if (const auto i = _saved.find(peer); i != end(_saved)) {
auto &saved = i->second;
@@ -623,7 +615,7 @@ void Stories::savedStateChanged(not_null<Story*> story) {
if (saved.total > 0) {
--saved.total;
}
_savedChanged.fire_copy(peer);
_albumIdsChanged.fire({ peer, kStoriesAlbumIdSaved });
}
}
}
@@ -678,6 +670,8 @@ void Stories::preloadListsMore() {
const auto index = static_cast<int>(list);
return _sourcesLoaded[index] || !_sourcesStates[index].isEmpty();
};
const auto selfId = _owner->session().userPeerId();
constexpr auto archive = kStoriesAlbumIdArchive;
if (loading(StorySourcesList::NotHidden)
|| loading(StorySourcesList::Hidden)) {
return;
@@ -685,8 +679,8 @@ void Stories::preloadListsMore() {
loadMore(StorySourcesList::NotHidden);
} else if (!countLoaded(StorySourcesList::Hidden)) {
loadMore(StorySourcesList::Hidden);
} else if (!archiveCountKnown(_owner->session().userPeerId())) {
archiveLoadMore(_owner->session().userPeerId());
} else if (!albumIdsCountKnown(selfId, archive)) {
albumIdsLoadMore(selfId, archive);
}
}
@@ -831,28 +825,24 @@ void Stories::applyDeleted(not_null<PeerData*> peer, StoryId id) {
story.get(),
UpdateFlag::Destroyed);
removeDependencyStory(story.get());
if (hasArchive(story->peer())) {
if (const auto k = _archive.find(peerId)
; k != end(_archive)) {
const auto archive = &k->second;
if (archive->ids.list.remove(id)) {
if (archive->total > 0) {
--archive->total;
const auto removeFromAlbum = [&](int albumId) {
if (const auto set = albumIdsSet(peerId, albumId, true)) {
if (set->ids.list.remove(id)) {
if (set->total > 0) {
--set->total;
}
_archiveChanged.fire_copy(peerId);
_albumIdsChanged.fire({ peerId, albumId });
}
}
};
if (hasArchive(story->peer())) {
removeFromAlbum(kStoriesAlbumIdArchive);
}
if (story->inProfile()) {
if (const auto k = _saved.find(peerId); k != end(_saved)) {
const auto saved = &k->second;
if (saved->ids.list.remove(id)) {
if (saved->total > 0) {
--saved->total;
}
_savedChanged.fire_copy(peerId);
}
}
removeFromAlbum(kStoriesAlbumIdSaved);
}
for (const auto id : story->albumIds()) {
removeFromAlbum(id);
}
if (_preloading && _preloading->id() == fullId) {
_preloading = nullptr;
@@ -1465,7 +1455,7 @@ void Stories::loadReactionsSlice(
slice.list.push_back({
.peer = story->peer(),
.repostId = story->id(),
});
});
}
}, [&](const MTPDstoryReactionPublicForward &data) {
const auto item = _owner->addNewMessage(
@@ -1613,153 +1603,140 @@ bool Stories::hasArchive(not_null<PeerData*> peer) const {
return false;
}
const StoriesIds &Stories::archive(PeerId peerId) const {
const Stories::Set *Stories::albumIdsSet(PeerId peerId, int albumId) const {
return const_cast<Stories*>(this)->albumIdsSet(peerId, albumId, true);
}
Stories::Set *Stories::albumIdsSet(PeerId peerId, int albumId, bool lazy) {
if (albumId == kStoriesAlbumIdArchive) {
const auto peer = _owner->peer(peerId);
if (!hasArchive(peer)) {
clearArchive(peer);
return nullptr;
}
const auto i = _archive.find(peerId);
return (i != end(_archive))
? &i->second
: lazy
? nullptr
: &_archive.emplace(peerId, Set()).first->second;
} else if (albumId == kStoriesAlbumIdSaved) {
const auto i = _saved.find(peerId);
return (i != end(_saved))
? &i->second
: lazy
? nullptr
: &_saved.emplace(peerId, Set()).first->second;
}
auto i = _albums.find(peerId);
if (i == end(_albums)) {
if (lazy) {
return nullptr;
}
i = _albums.emplace(peerId, Albums()).first;
}
const auto j = i->second.sets.find(albumId);
return (j != end(i->second.sets))
? &j->second
: lazy
? nullptr
: &i->second.sets.emplace(albumId).first->second;
}
const StoriesIds &Stories::albumIds(PeerId peerId, int albumId) const {
static const auto empty = StoriesIds();
const auto i = _archive.find(peerId);
return (i != end(_archive)) ? i->second.ids : empty;
const auto set = albumIdsSet(peerId, albumId);
return set ? set->ids : empty;
}
rpl::producer<PeerId> Stories::archiveChanged() const {
return _archiveChanged.events();
rpl::producer<StoryAlbumIdsKey> Stories::albumIdsChanged() const {
return _albumIdsChanged.events();
}
int Stories::archiveCount(PeerId peerId) const {
const auto i = _archive.find(peerId);
return (i != end(_archive)) ? i->second.total : 0;
int Stories::albumIdsCount(PeerId peerId, int albumId) const {
const auto set = albumIdsSet(peerId, albumId);
return set ? set->total : 0;
}
bool Stories::archiveCountKnown(PeerId peerId) const {
const auto i = _archive.find(peerId);
return (i != end(_archive)) && (i->second.total >= 0);
bool Stories::albumIdsCountKnown(PeerId peerId, int albumId) const {
const auto set = albumIdsSet(peerId, albumId);
return set && (set->total >= 0);
}
bool Stories::archiveLoaded(PeerId peerId) const {
const auto i = _archive.find(peerId);
return (i != end(_archive)) && i->second.loaded;
bool Stories::albumIdsLoaded(PeerId peerId, int albumId) const {
const auto set = albumIdsSet(peerId, albumId);
return set && set->loaded;
}
const StoriesIds &Stories::saved(PeerId peerId) const {
static const auto empty = StoriesIds();
const auto i = _saved.find(peerId);
return (i != end(_saved)) ? i->second.ids : empty;
}
rpl::producer<PeerId> Stories::savedChanged() const {
return _savedChanged.events();
}
int Stories::savedCount(PeerId peerId) const {
const auto i = _saved.find(peerId);
return (i != end(_saved)) ? i->second.total : 0;
}
bool Stories::savedCountKnown(PeerId peerId) const {
const auto i = _saved.find(peerId);
return (i != end(_saved)) && (i->second.total >= 0);
}
bool Stories::savedLoaded(PeerId peerId) const {
const auto i = _saved.find(peerId);
return (i != end(_saved)) && i->second.loaded;
}
void Stories::archiveLoadMore(PeerId peerId) {
void Stories::albumIdsLoadMore(PeerId peerId, int albumId) {
const auto peer = _owner->peer(peerId);
const auto archive = lookupArchive(peer);
if (!archive || archive->requestId || archive->loaded) {
const auto set = albumIdsSet(peerId, albumId);
if (!set || set->requestId || set->loaded) {
return;
}
const auto api = &_owner->session().api();
archive->requestId = api->request(MTPstories_GetStoriesArchive(
peer->input,
MTP_int(archive->lastId),
MTP_int(archive->lastId ? kArchivePerPage : kArchiveFirstPerPage)
)).done([=](const MTPstories_Stories &result) {
const auto archive = lookupArchive(peer);
if (!archive) {
const auto done = [=](const MTPstories_Stories &result) {
const auto set = albumIdsSet(peerId, albumId);
if (!set) {
return;
}
archive->requestId = 0;
const auto &data = result.data();
const auto now = base::unixtime::now();
archive->total = data.vcount().v;
for (const auto &story : data.vstories().v) {
const auto id = story.match([&](const auto &id) {
return id.vid().v;
});
archive->ids.list.emplace(id);
archive->lastId = id;
if (!parseAndApply(peer, story, now)) {
archive->ids.list.remove(id);
if (archive->total > 0) {
--archive->total;
}
}
}
const auto ids = int(archive->ids.list.size());
archive->loaded = data.vstories().v.empty();
archive->total = archive->loaded ? ids : std::max(archive->total, ids);
_archiveChanged.fire_copy(peerId);
}).fail([=] {
const auto archive = lookupArchive(peer);
if (!archive) {
return;
}
archive->requestId = 0;
archive->loaded = true;
archive->total = int(archive->ids.list.size());
_archiveChanged.fire_copy(peerId);
}).send();
}
void Stories::savedLoadMore(PeerId peerId) {
auto &saved = _saved[peerId];
if (saved.requestId || saved.loaded) {
return;
}
const auto api = &_owner->session().api();
const auto peer = _owner->peer(peerId);
saved.requestId = api->request(MTPstories_GetPinnedStories(
peer->input,
MTP_int(saved.lastId),
MTP_int(saved.lastId ? kSavedPerPage : kSavedFirstPerPage)
)).done([=](const MTPstories_Stories &result) {
auto &saved = _saved[peerId];
saved.requestId = 0;
set->requestId = 0;
const auto &data = result.data();
const auto now = base::unixtime::now();
auto pinnedToTopIds = data.vpinned_to_top().value_or_empty();
auto pinnedToTop = pinnedToTopIds
| ranges::views::transform(&MTPint::v)
| ranges::to_vector;
saved.total = data.vcount().v;
set->total = data.vcount().v;
for (const auto &story : data.vstories().v) {
const auto id = story.match([&](const auto &id) {
return id.vid().v;
});
saved.ids.list.emplace(id);
saved.lastId = id;
set->ids.list.emplace(id);
set->lastId = id;
if (!parseAndApply(peer, story, now)) {
saved.ids.list.remove(id);
if (saved.total > 0) {
--saved.total;
set->ids.list.remove(id);
if (set->total > 0) {
--set->total;
}
}
}
const auto ids = int(saved.ids.list.size());
saved.loaded = data.vstories().v.empty();
saved.total = saved.loaded ? ids : std::max(saved.total, ids);
setPinnedToTop(peerId, std::move(pinnedToTop));
_savedChanged.fire_copy(peerId);
}).fail([=] {
auto &saved = _saved[peerId];
saved.requestId = 0;
saved.loaded = true;
saved.total = int(saved.ids.list.size());
_savedChanged.fire_copy(peerId);
}).send();
const auto count = int(set->ids.list.size());
set->loaded = data.vstories().v.empty();
set->total = set->loaded ? count : std::max(set->total, count);
if (albumId == kStoriesAlbumIdSaved) {
setPinnedToTop(peerId, std::move(pinnedToTop));
}
_albumIdsChanged.fire({ peerId, albumId });
};
const auto fail = [=] {
const auto set = albumIdsSet(peerId, albumId);
if (!set) {
return;
}
set->requestId = 0;
set->loaded = true;
set->total = int(set->ids.list.size());
_albumIdsChanged.fire({ peerId, albumId });
};
set->requestId = (albumId == kStoriesAlbumIdArchive)
? api->request(MTPstories_GetStoriesArchive(
peer->input,
MTP_int(set->lastId),
MTP_int(set->lastId ? kArchivePerPage : kArchiveFirstPerPage)
)).done(done).fail(fail).send()
: (albumId == kStoriesAlbumIdSaved)
? api->request(MTPstories_GetPinnedStories(
peer->input,
MTP_int(set->lastId),
MTP_int(set->lastId ? kSavedPerPage : kSavedFirstPerPage)
)).done(done).fail(fail).send()
: api->request(MTPstories_GetAlbumStories(
peer->input,
MTP_int(albumId),
MTP_int(set->lastId),
MTP_int(set->lastId ? kSavedPerPage : kSavedFirstPerPage)
)).done(done).fail(fail).send();
}
auto Stories::albumsListValue(PeerId peerId)
@@ -1976,9 +1953,9 @@ void Stories::toggleInProfileList(
}
}
if (dirty) {
savedLoadMore(peerId);
albumIdsLoadMore(peerId, kStoriesAlbumIdSaved);
} else {
_savedChanged.fire_copy(peerId);
_albumIdsChanged.fire({ peerId, kStoriesAlbumIdSaved });
}
}).send();
}
@@ -2047,7 +2024,7 @@ void Stories::togglePinnedList(
setPinnedToTop(peerId, list
| ranges::views::transform(&MTPint::v)
| ranges::to_vector);
_savedChanged.fire_copy(peerId);
_albumIdsChanged.fire({ peerId, kStoriesAlbumIdSaved });
}).send();
}