mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Allow loading stories in different albums.
This commit is contained in:
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -133,6 +133,18 @@ struct StoryAlbumUpdate {
|
||||
|
||||
inline constexpr auto kStorySourcesListCount = 2;
|
||||
|
||||
struct StoryAlbumIdsKey {
|
||||
PeerId peerId;
|
||||
int albumId = 0;
|
||||
|
||||
friend inline auto operator<=>(
|
||||
StoryAlbumIdsKey,
|
||||
StoryAlbumIdsKey) = default;
|
||||
friend inline bool operator==(
|
||||
StoryAlbumIdsKey,
|
||||
StoryAlbumIdsKey) = default;
|
||||
};
|
||||
|
||||
class Stories final : public base::has_weak_ptr {
|
||||
public:
|
||||
explicit Stories(not_null<Session*> owner);
|
||||
@@ -197,19 +209,14 @@ public:
|
||||
|
||||
[[nodiscard]] bool hasArchive(not_null<PeerData*> peer) const;
|
||||
|
||||
[[nodiscard]] const StoriesIds &archive(PeerId peerId) const;
|
||||
[[nodiscard]] rpl::producer<PeerId> archiveChanged() const;
|
||||
[[nodiscard]] int archiveCount(PeerId peerId) const;
|
||||
[[nodiscard]] bool archiveCountKnown(PeerId peerId) const;
|
||||
[[nodiscard]] bool archiveLoaded(PeerId peerId) const;
|
||||
void archiveLoadMore(PeerId peerId);
|
||||
|
||||
[[nodiscard]] const StoriesIds &saved(PeerId peerId) const;
|
||||
[[nodiscard]] rpl::producer<PeerId> savedChanged() const;
|
||||
[[nodiscard]] int savedCount(PeerId peerId) const;
|
||||
[[nodiscard]] bool savedCountKnown(PeerId peerId) const;
|
||||
[[nodiscard]] bool savedLoaded(PeerId peerId) const;
|
||||
void savedLoadMore(PeerId peerId);
|
||||
[[nodiscard]] const StoriesIds &albumIds(
|
||||
PeerId peerId,
|
||||
int albumId) const;
|
||||
[[nodiscard]] rpl::producer<StoryAlbumIdsKey> albumIdsChanged() const;
|
||||
[[nodiscard]] int albumIdsCount(PeerId peerIdl, int albumId) const;
|
||||
[[nodiscard]] bool albumIdsCountKnown(PeerId peerId, int albumId) const;
|
||||
[[nodiscard]] bool albumIdsLoaded(PeerId peerId, int albumId) const;
|
||||
void albumIdsLoadMore(PeerId peerId, int albumId);
|
||||
|
||||
[[nodiscard]] auto albumsListValue(PeerId peerId)
|
||||
-> rpl::producer<std::vector<Data::StoryAlbum>>;
|
||||
@@ -319,6 +326,9 @@ private:
|
||||
[[nodiscard]] Set *lookupArchive(not_null<PeerData*> peer);
|
||||
void clearArchive(not_null<PeerData*> peer);
|
||||
|
||||
const Set *albumIdsSet(PeerId peerId, int albumId) const;
|
||||
Set *albumIdsSet(PeerId peerId, int albumId, bool lazy = false);
|
||||
|
||||
void applyDeleted(not_null<PeerData*> peer, StoryId id);
|
||||
void applyExpired(FullStoryId id);
|
||||
void applyRemovedFromActive(FullStoryId id);
|
||||
@@ -403,13 +413,10 @@ private:
|
||||
rpl::event_stream<PeerId> _itemsChanged;
|
||||
|
||||
std::unordered_map<PeerId, Set> _archive;
|
||||
rpl::event_stream<PeerId> _archiveChanged;
|
||||
|
||||
std::unordered_map<PeerId, Set> _saved;
|
||||
rpl::event_stream<PeerId> _savedChanged;
|
||||
|
||||
std::unordered_map<PeerId, Albums> _albums;
|
||||
rpl::event_stream<StoryAlbumUpdate> _albumUpdates;
|
||||
rpl::event_stream<StoryAlbumIdsKey> _albumIdsChanged;
|
||||
|
||||
base::flat_set<PeerId> _markReadPending;
|
||||
base::Timer _markReadTimer;
|
||||
|
||||
@@ -16,8 +16,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
namespace Data {
|
||||
|
||||
rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
||||
rpl::producer<StoriesIdsSlice> AlbumStoriesIds(
|
||||
not_null<PeerData*> peer,
|
||||
int albumId,
|
||||
StoryId aroundId,
|
||||
int limit) {
|
||||
return [=](auto consumer) {
|
||||
@@ -35,22 +36,21 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
||||
|
||||
const auto peerId = peer->id;
|
||||
const auto stories = &peer->owner().stories();
|
||||
if (!stories->savedCountKnown(peerId)) {
|
||||
if (!stories->albumIdsCountKnown(peerId, albumId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &saved = stories->saved(peerId);
|
||||
const auto sorted = RespectingPinned(saved);
|
||||
const auto count = stories->savedCount(peerId);
|
||||
const auto &loaded = stories->albumIds(peerId, albumId);
|
||||
const auto sorted = RespectingPinned(loaded);
|
||||
const auto count = stories->albumIdsCount(peerId, albumId);
|
||||
auto i = ranges::find(sorted, aroundId);
|
||||
if (i == end(sorted)) {
|
||||
const auto j = saved.list.lower_bound(aroundId);
|
||||
i = begin(sorted) + int(j - begin(saved.list));
|
||||
const auto j = loaded.list.lower_bound(aroundId);
|
||||
i = begin(sorted) + int(j - begin(loaded.list));
|
||||
}
|
||||
const auto hasBefore = int(i - begin(sorted));
|
||||
const auto hasAfter = int(end(sorted) - i);
|
||||
if (hasAfter < limit) {
|
||||
stories->savedLoadMore(peerId);
|
||||
stories->albumIdsLoadMore(peerId, albumId);
|
||||
}
|
||||
const auto takeBefore = std::min(hasBefore, limit);
|
||||
const auto takeAfter = std::min(hasAfter, limit);
|
||||
@@ -81,91 +81,13 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
||||
|
||||
const auto peerId = peer->id;
|
||||
const auto stories = &peer->owner().stories();
|
||||
stories->savedChanged(
|
||||
stories->albumIdsChanged(
|
||||
) | rpl::filter(
|
||||
rpl::mappers::_1 == peerId
|
||||
rpl::mappers::_1 == Data::StoryAlbumIdsKey{ peerId, albumId }
|
||||
) | rpl::start_with_next(schedule, lifetime);
|
||||
|
||||
if (!stories->savedCountKnown(peerId)) {
|
||||
stories->savedLoadMore(peerId);
|
||||
}
|
||||
|
||||
push();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
|
||||
not_null<PeerData*> peer,
|
||||
StoryId aroundId,
|
||||
int limit) {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
|
||||
struct State {
|
||||
StoriesIdsSlice slice;
|
||||
base::has_weak_ptr guard;
|
||||
bool scheduled = false;
|
||||
};
|
||||
const auto state = lifetime.make_state<State>();
|
||||
|
||||
const auto push = [=] {
|
||||
state->scheduled = false;
|
||||
|
||||
const auto peerId = peer->id;
|
||||
const auto stories = &peer->owner().stories();
|
||||
if (!stories->archiveCountKnown(peerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &archive = stories->archive(peerId);
|
||||
const auto sorted = RespectingPinned(archive);
|
||||
const auto count = stories->savedCount(peerId);
|
||||
auto i = ranges::find(sorted, aroundId);
|
||||
if (i == end(sorted)) {
|
||||
const auto j = archive.list.lower_bound(aroundId);
|
||||
i = begin(sorted) + int(j - begin(archive.list));
|
||||
}
|
||||
const auto hasBefore = int(i - begin(sorted));
|
||||
const auto hasAfter = int(end(sorted) - i);
|
||||
if (hasAfter < limit) {
|
||||
stories->archiveLoadMore(peerId);
|
||||
}
|
||||
const auto takeBefore = std::min(hasBefore, limit);
|
||||
const auto takeAfter = std::min(hasAfter, limit);
|
||||
auto ids = std::vector<StoryId>();
|
||||
ids.reserve(takeBefore + takeAfter);
|
||||
for (auto j = i - takeBefore; j != i + takeAfter; ++j) {
|
||||
ids.push_back(*j);
|
||||
}
|
||||
const auto added = int(ids.size());
|
||||
state->slice = StoriesIdsSlice(
|
||||
std::move(ids),
|
||||
count,
|
||||
(hasBefore - takeBefore),
|
||||
count - hasBefore - added);
|
||||
consumer.put_next_copy(state->slice);
|
||||
};
|
||||
const auto schedule = [=] {
|
||||
if (state->scheduled) {
|
||||
return;
|
||||
}
|
||||
state->scheduled = true;
|
||||
Ui::PostponeCall(&state->guard, [=] {
|
||||
if (state->scheduled) {
|
||||
push();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const auto peerId = peer->id;
|
||||
const auto stories = &peer->owner().stories();
|
||||
stories->archiveChanged(
|
||||
) | rpl::start_with_next(schedule, lifetime);
|
||||
|
||||
if (!stories->archiveCountKnown(peerId)) {
|
||||
stories->archiveLoadMore(peerId);
|
||||
if (!stories->albumIdsCountKnown(peerId, albumId)) {
|
||||
stories->albumIdsLoadMore(peerId, albumId);
|
||||
}
|
||||
|
||||
push();
|
||||
|
||||
@@ -19,13 +19,9 @@ namespace Data {
|
||||
|
||||
using StoriesIdsSlice = AbstractSparseIds<std::vector<StoryId>>;
|
||||
|
||||
[[nodiscard]] rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
||||
not_null<PeerData*> peer,
|
||||
StoryId aroundId,
|
||||
int limit);
|
||||
|
||||
[[nodiscard]] rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
|
||||
[[nodiscard]] rpl::producer<StoriesIdsSlice> AlbumStoriesIds(
|
||||
not_null<PeerData*> peer,
|
||||
int albumId,
|
||||
StoryId aroundId,
|
||||
int limit);
|
||||
|
||||
|
||||
@@ -824,9 +824,12 @@ void TopBarWidget::setActiveChat(
|
||||
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
if (channel->canEditStories()
|
||||
&& !channel->owner().stories().archiveCountKnown(
|
||||
channel->id)) {
|
||||
channel->owner().stories().archiveLoadMore(channel->id);
|
||||
&& !channel->owner().stories().albumIdsCountKnown(
|
||||
channel->id,
|
||||
Data::kStoriesAlbumIdArchive)) {
|
||||
channel->owner().stories().albumIdsLoadMore(
|
||||
channel->id,
|
||||
Data::kStoriesAlbumIdArchive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +299,10 @@ Controller::Controller(
|
||||
setupTopicViewer();
|
||||
}
|
||||
|
||||
void Controller::replaceKey(Key key) {
|
||||
_key = key;
|
||||
}
|
||||
|
||||
void Controller::setupMigrationViewer() {
|
||||
const auto peer = _key.peer();
|
||||
if (_key.topic()
|
||||
|
||||
@@ -293,6 +293,7 @@ public:
|
||||
return _section;
|
||||
}
|
||||
|
||||
void replaceKey(Key key);
|
||||
[[nodiscard]] bool validateMementoPeer(
|
||||
not_null<ContentMemento*> memento) const;
|
||||
|
||||
|
||||
@@ -246,8 +246,9 @@ not_null<Ui::SettingsButton*> AddStoriesButton(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer,
|
||||
Ui::MultiSlideTracker &tracker) {
|
||||
auto count = rpl::single(0) | rpl::then(Data::SavedStoriesIds(
|
||||
auto count = rpl::single(0) | rpl::then(Data::AlbumStoriesIds(
|
||||
peer,
|
||||
0, // = Data::kStoriesAlbumIdSaved
|
||||
ServerMaxStoryId - 1,
|
||||
0
|
||||
) | rpl::map([](const Data::StoriesIdsSlice &slice) {
|
||||
|
||||
@@ -105,22 +105,32 @@ void EmptyWidget::paintEvent(QPaintEvent *e) {
|
||||
|
||||
InnerWidget::InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller)
|
||||
not_null<Controller*> controller,
|
||||
rpl::producer<int> albumId,
|
||||
int addingToAlbumId)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller)
|
||||
, _peer(controller->key().storiesPeer())
|
||||
, _addingToAlbumId(0)
|
||||
, _albumId(controller->key().storiesAlbumId())
|
||||
, _addingToAlbumId(addingToAlbumId)
|
||||
, _albumId(std::move(albumId))
|
||||
, _albumChanges(Data::StoryAlbumUpdate{
|
||||
.peer = _peer,
|
||||
.albumId = _addingToAlbumId,
|
||||
})
|
||||
, _empty(this) {
|
||||
_empty->heightValue(
|
||||
) | rpl::start_with_next(
|
||||
[this] { refreshHeight(); },
|
||||
_empty->lifetime());
|
||||
_list = setupList();
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshHeight();
|
||||
}, _empty->lifetime());
|
||||
setupList();
|
||||
|
||||
_albumId.changes(
|
||||
) | rpl::start_with_next([=](int albumId) {
|
||||
_list.destroy();
|
||||
_controller->replaceKey(Key(Tag(_peer, albumId)));
|
||||
setupList();
|
||||
resizeToWidth(width());
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void InnerWidget::setupAlbums() {
|
||||
@@ -200,19 +210,20 @@ void InnerWidget::addArchiveButton(Ui::MultiSlideTracker &tracker) {
|
||||
|
||||
const auto stories = &_peer->owner().stories();
|
||||
|
||||
if (!stories->archiveCountKnown(_peer->id)) {
|
||||
stories->archiveLoadMore(_peer->id);
|
||||
constexpr auto kArchive = Data::kStoriesAlbumIdArchive;
|
||||
if (!stories->albumIdsCountKnown(_peer->id, kArchive)) {
|
||||
stories->albumIdsLoadMore(_peer->id, kArchive);
|
||||
}
|
||||
|
||||
auto count = rpl::single(
|
||||
rpl::empty
|
||||
) | rpl::then(
|
||||
stories->archiveChanged(
|
||||
stories->albumIdsChanged(
|
||||
) | rpl::filter(
|
||||
rpl::mappers::_1 == _peer->id
|
||||
rpl::mappers::_1 == Data::StoryAlbumIdsKey{ _peer->id, kArchive }
|
||||
) | rpl::to_empty
|
||||
) | rpl::map([=] {
|
||||
return stories->archiveCount(_peer->id);
|
||||
return stories->albumIdsCount(_peer->id, kArchive);
|
||||
}) | rpl::start_spawning(_top->lifetime());
|
||||
|
||||
const auto archiveWrap = _top->add(
|
||||
@@ -228,8 +239,7 @@ void InnerWidget::addArchiveButton(Ui::MultiSlideTracker &tracker) {
|
||||
|
||||
const auto archive = archiveWrap->entity();
|
||||
archive->addClickHandler([=] {
|
||||
_controller->showSection(
|
||||
Make(_peer, Data::kStoriesAlbumIdArchive));
|
||||
_controller->showSection(Make(_peer, kArchive));
|
||||
});
|
||||
auto label = rpl::duplicate(
|
||||
count
|
||||
@@ -401,27 +411,30 @@ bool InnerWidget::showInternal(not_null<Memento*> memento) {
|
||||
return false;
|
||||
}
|
||||
|
||||
object_ptr<Media::ListWidget> InnerWidget::setupList() {
|
||||
auto result = object_ptr<Media::ListWidget>(
|
||||
void InnerWidget::setupList() {
|
||||
Expects(!_list);
|
||||
|
||||
_list = object_ptr<Media::ListWidget>(
|
||||
this,
|
||||
_controller);
|
||||
result->heightValue(
|
||||
) | rpl::start_with_next(
|
||||
[this] { refreshHeight(); },
|
||||
result->lifetime());
|
||||
const auto raw = _list.data();
|
||||
|
||||
raw->heightValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshHeight();
|
||||
}, raw->lifetime());
|
||||
using namespace rpl::mappers;
|
||||
result->scrollToRequests(
|
||||
) | rpl::map([widget = result.data()](int to) {
|
||||
raw->scrollToRequests(
|
||||
) | rpl::map([=](int to) {
|
||||
return Ui::ScrollToRequest {
|
||||
widget->y() + to,
|
||||
raw->y() + to,
|
||||
-1
|
||||
};
|
||||
}) | rpl::start_to_stream(
|
||||
_scrollToRequests,
|
||||
result->lifetime());
|
||||
_selectedLists.fire(result->selectedListValue());
|
||||
_listTops.fire(result->topValue());
|
||||
return result;
|
||||
}) | rpl::start_to_stream(_scrollToRequests, raw->lifetime());
|
||||
_selectedLists.fire(raw->selectedListValue());
|
||||
_listTops.fire(raw->topValue());
|
||||
|
||||
raw->show();
|
||||
}
|
||||
|
||||
void InnerWidget::refreshAlbumsTabs() {
|
||||
@@ -435,6 +448,7 @@ void InnerWidget::refreshAlbumsTabs() {
|
||||
return;
|
||||
}
|
||||
auto tabs = std::vector<Ui::SubTabs::Tab>();
|
||||
auto selected = QString();
|
||||
if (!_albums.empty()) {
|
||||
tabs.push_back({
|
||||
.id = u"all"_q,
|
||||
@@ -449,6 +463,12 @@ void InnerWidget::refreshAlbumsTabs() {
|
||||
.id = QString::number(album.id),
|
||||
.text = std::move(title),
|
||||
});
|
||||
if (_albumId.current() == album.id) {
|
||||
selected = tabs.back().id;
|
||||
}
|
||||
}
|
||||
if (selected.isEmpty()) {
|
||||
selected = tabs.front().id;
|
||||
}
|
||||
}
|
||||
if (_peer->canEditStories()) {
|
||||
@@ -461,7 +481,7 @@ void InnerWidget::refreshAlbumsTabs() {
|
||||
_albumsTabs = std::make_unique<Ui::SubTabs>(
|
||||
_albumsWrap,
|
||||
Ui::SubTabs::Options{
|
||||
.selected = _albums.empty() ? QString() : u"all"_q,
|
||||
.selected = selected,
|
||||
.centered = true,
|
||||
},
|
||||
std::move(tabs));
|
||||
@@ -490,10 +510,7 @@ void InnerWidget::refreshAlbumsTabs() {
|
||||
added));
|
||||
} else {
|
||||
_albumsTabs->setActiveTab(id);
|
||||
|
||||
//auto now = _descriptor.current();
|
||||
//now.collectionId = (id == u"all"_q) ? 0 : id.toInt();
|
||||
//_descriptorChanges.fire(std::move(now));
|
||||
_albumIdChanges.fire((id == u"all"_q) ? 0 : id.toInt());
|
||||
}
|
||||
}, _albumsTabs->lifetime());
|
||||
|
||||
@@ -508,6 +525,9 @@ void InnerWidget::refreshAlbumsTabs() {
|
||||
}, _albumsTabs->lifetime());
|
||||
} else {
|
||||
_albumsTabs->setTabs(std::move(tabs));
|
||||
if (!selected.isEmpty()) {
|
||||
_albumsTabs->setActiveTab(selected);
|
||||
}
|
||||
}
|
||||
resizeToWidth(width());
|
||||
}
|
||||
@@ -533,6 +553,10 @@ void InnerWidget::showMenuForAlbum(int id) {
|
||||
_menu->popup(QCursor::pos());
|
||||
}
|
||||
|
||||
rpl::producer<int> InnerWidget::albumIdChanges() const {
|
||||
return _albumIdChanges.events();
|
||||
}
|
||||
|
||||
rpl::producer<Data::StoryAlbumUpdate> InnerWidget::changes() const {
|
||||
return _albumChanges.value();
|
||||
}
|
||||
@@ -562,7 +586,9 @@ void InnerWidget::editAlbumStories(int id) {
|
||||
const auto content = box->addRow(
|
||||
object_ptr<InnerWidget>(
|
||||
box,
|
||||
_controller/*,
|
||||
_controller,
|
||||
rpl::single(Data::kStoriesAlbumIdArchive),
|
||||
id/*,
|
||||
_peer,
|
||||
state->descriptor.value(),
|
||||
id,
|
||||
|
||||
@@ -45,7 +45,11 @@ class EmptyWidget;
|
||||
|
||||
class InnerWidget final : public Ui::RpWidget {
|
||||
public:
|
||||
InnerWidget(QWidget *parent, not_null<Controller*> controller);
|
||||
InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
rpl::producer<int> albumId,
|
||||
int addingToAlbumId = 0);
|
||||
~InnerWidget();
|
||||
|
||||
bool showInternal(not_null<Memento*> memento);
|
||||
@@ -69,6 +73,7 @@ public:
|
||||
void confirmDeleteAlbum(int id);
|
||||
void albumAdded(Data::StoryAlbum result);
|
||||
|
||||
[[nodiscard]] rpl::producer<int> albumIdChanges() const;
|
||||
[[nodiscard]] rpl::producer<Data::StoryAlbumUpdate> changes() const;
|
||||
|
||||
protected:
|
||||
@@ -82,6 +87,7 @@ private:
|
||||
void refreshHeight();
|
||||
|
||||
void setupTop();
|
||||
void setupList();
|
||||
void setupAlbums();
|
||||
void createButtons();
|
||||
void createProfileTop();
|
||||
@@ -93,8 +99,6 @@ private:
|
||||
void addGiftsButton(Ui::MultiSlideTracker &tracker);
|
||||
void finalizeTop();
|
||||
|
||||
[[nodiscard]] object_ptr<Media::ListWidget> setupList();
|
||||
|
||||
void refreshAlbumsTabs();
|
||||
void showMenuForAlbum(int id);
|
||||
|
||||
@@ -107,6 +111,7 @@ private:
|
||||
|
||||
std::vector<Data::StoryAlbum> _albums;
|
||||
rpl::variable<int> _albumId;
|
||||
rpl::event_stream<int> _albumIdChanges;
|
||||
Ui::RpWidget *_albumsWrap = nullptr;
|
||||
std::unique_ptr<Ui::SubTabs> _albumsTabs;
|
||||
rpl::variable<Data::StoryAlbumUpdate> _albumChanges;
|
||||
|
||||
@@ -179,10 +179,8 @@ void Provider::setSearchQuery(QString query) {
|
||||
|
||||
void Provider::refreshViewer() {
|
||||
_viewerLifetime.destroy();
|
||||
const auto idForViewer = _aroundId;
|
||||
auto ids = (_albumId == Data::kStoriesAlbumIdArchive)
|
||||
? Data::ArchiveStoriesIds(_peer, idForViewer, _idsLimit)
|
||||
: Data::SavedStoriesIds(_peer, idForViewer, _idsLimit); // #TODO stories
|
||||
const auto aroundId = _aroundId;
|
||||
auto ids = Data::AlbumStoriesIds(_peer, _albumId, aroundId, _idsLimit);
|
||||
std::move(
|
||||
ids
|
||||
) | rpl::start_with_next([=](Data::StoriesIdsSlice &&slice) {
|
||||
@@ -195,8 +193,8 @@ void Provider::refreshViewer() {
|
||||
auto nearestId = std::optional<StoryId>();
|
||||
for (auto i = 0; i != _slice.size(); ++i) {
|
||||
if (!nearestId
|
||||
|| std::abs(*nearestId - idForViewer)
|
||||
> std::abs(_slice[i] - idForViewer)) {
|
||||
|| std::abs(*nearestId - aroundId)
|
||||
> std::abs(_slice[i] - aroundId)) {
|
||||
nearestId = _slice[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,17 @@ object_ptr<ContentWidget> Memento::createWidget(
|
||||
Widget::Widget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller)
|
||||
: ContentWidget(parent, controller) {
|
||||
: ContentWidget(parent, controller)
|
||||
, _albumId(controller->key().storiesAlbumId()) {
|
||||
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
||||
this,
|
||||
controller));
|
||||
controller,
|
||||
_albumId.value()));
|
||||
_inner->albumIdChanges() | rpl::start_with_next([=](int id) {
|
||||
controller->showSection(
|
||||
Make(controller->storiesPeer(), id),
|
||||
Window::SectionShow::Way::Backward);
|
||||
}, _inner->lifetime());
|
||||
_inner->setScrollHeightValue(scrollHeightValue());
|
||||
_inner->scrollToRequests(
|
||||
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||
@@ -73,10 +80,15 @@ bool Widget::showInternal(not_null<ContentMemento*> memento) {
|
||||
return false;
|
||||
}
|
||||
if (auto storiesMemento = dynamic_cast<Memento*>(memento.get())) {
|
||||
const auto albumId = controller()->key().storiesAlbumId();
|
||||
if (storiesMemento->storiesAlbumId() == albumId) {
|
||||
const auto myId = controller()->key().storiesAlbumId();
|
||||
const auto hisId = storiesMemento->storiesAlbumId();
|
||||
constexpr auto kArchive = Data::kStoriesAlbumIdArchive;
|
||||
if (myId == hisId) {
|
||||
restoreState(storiesMemento);
|
||||
return true;
|
||||
} else if (myId != kArchive && hisId != kArchive) {
|
||||
_albumId = hisId;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -64,6 +64,7 @@ private:
|
||||
|
||||
std::shared_ptr<ContentMemento> doCreateMemento() override;
|
||||
|
||||
rpl::variable<int> _albumId;
|
||||
InnerWidget *_inner = nullptr;
|
||||
|
||||
};
|
||||
|
||||
@@ -705,22 +705,15 @@ void Controller::rebuildFromContext(
|
||||
source = stories.source(peerId);
|
||||
hideSiblings();
|
||||
}, [&](StoriesContextAlbum album) {
|
||||
const auto archive = (album.id == Data::kStoriesAlbumIdArchive);
|
||||
const auto known = archive
|
||||
? stories.archiveCountKnown(peerId)
|
||||
: stories.savedCountKnown(peerId);
|
||||
const auto known = stories.albumIdsCountKnown(peerId, album.id);
|
||||
if (known) {
|
||||
const auto &ids = archive
|
||||
? stories.archive(peerId)
|
||||
: stories.saved(peerId);
|
||||
const auto &ids = stories.albumIds(peerId, album.id);
|
||||
auto sorted = RespectingPinned(ids);
|
||||
const auto i = ranges::find(sorted, id);
|
||||
const auto tillEnd = int(end(sorted) - i);
|
||||
if (tillEnd > 0) {
|
||||
_index = int(i - begin(sorted));
|
||||
const auto total = archive
|
||||
? stories.archiveCount(peerId)
|
||||
: stories.savedCount(peerId);
|
||||
const auto total = stories.albumIdsCount(peerId, album.id);
|
||||
list = StoriesList{
|
||||
.peer = peer,
|
||||
.ids = ids,
|
||||
@@ -729,11 +722,7 @@ void Controller::rebuildFromContext(
|
||||
};
|
||||
if (ids.list.size() < list->total
|
||||
&& tillEnd < kPreloadStoriesCount) {
|
||||
if (archive) {
|
||||
stories.archiveLoadMore(peerId);
|
||||
} else {
|
||||
stories.savedLoadMore(peerId);
|
||||
}
|
||||
stories.albumIdsLoadMore(peerId, album.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -854,20 +843,13 @@ void Controller::show(
|
||||
}, [&](Data::StoriesContextPeer) {
|
||||
subscribeToSource();
|
||||
}, [&](Data::StoriesContextAlbum album) {
|
||||
if (album.id == Data::kStoriesAlbumIdArchive) {
|
||||
stories.archiveChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
rebuildFromContext(peer, storyId);
|
||||
checkMoveByDelta();
|
||||
}, _contextLifetime);
|
||||
} else {
|
||||
stories.savedChanged() | rpl::filter(
|
||||
rpl::mappers::_1 == storyId.peer
|
||||
) | rpl::start_with_next([=] {
|
||||
rebuildFromContext(peer, storyId);
|
||||
checkMoveByDelta();
|
||||
}, _contextLifetime);
|
||||
}
|
||||
const auto key = Data::StoryAlbumIdsKey{ storyId.peer, album.id };
|
||||
stories.albumIdsChanged() | rpl::filter(
|
||||
rpl::mappers::_1 == key
|
||||
) | rpl::start_with_next([=] {
|
||||
rebuildFromContext(peer, storyId);
|
||||
checkMoveByDelta();
|
||||
}, _contextLifetime);
|
||||
}, [&](Data::StorySourcesList) {
|
||||
subscribeToSource();
|
||||
});
|
||||
@@ -1597,11 +1579,7 @@ void Controller::loadMoreToList() {
|
||||
const auto peerId = _shown.peer;
|
||||
auto &stories = peer->owner().stories();
|
||||
v::match(_context.data, [&](StoriesContextAlbum album) {
|
||||
if (album.id == Data::kStoriesAlbumIdArchive) {
|
||||
stories.archiveLoadMore(peerId);
|
||||
} else {
|
||||
stories.savedLoadMore(peerId); // #TODO stories
|
||||
}
|
||||
stories.albumIdsLoadMore(peerId, album.id);
|
||||
}, [](const auto &) {
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user