mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 06:26:18 +00:00
Implement story album management.
This commit is contained in:
@@ -477,6 +477,19 @@ Story *Stories::parseAndApply(
|
||||
return nullptr;
|
||||
}
|
||||
const auto id = data.vid().v;
|
||||
auto albumInfo = (Albums*)nullptr;
|
||||
auto list = std::optional<base::flat_set<int>>();
|
||||
if (const auto albums = data.valbums()) {
|
||||
list.emplace();
|
||||
if (!albums->v.empty()) {
|
||||
albumInfo = &_albums[peer->id];
|
||||
list->reserve(albums->v.size());
|
||||
for (const auto &albumId : albums->v) {
|
||||
albumInfo->sets[albumId.v].albumKnownInArchive.emplace(id);
|
||||
list->emplace(albumId.v);
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto fullId = FullStoryId{ peer->id, id };
|
||||
auto &stories = _stories[peer->id];
|
||||
const auto i = stories.find(id);
|
||||
@@ -484,6 +497,21 @@ Story *Stories::parseAndApply(
|
||||
const auto result = i->second.get();
|
||||
const auto mediaChanged = (result->media() != *media);
|
||||
result->applyChanges(*media, data, now);
|
||||
if (list) {
|
||||
const auto &was = result->albumIds();
|
||||
if (*list != was) {
|
||||
if (!albumInfo && !was.empty()) {
|
||||
albumInfo = &_albums[peer->id];
|
||||
}
|
||||
for (const auto wasId : result->albumIds()) {
|
||||
if (!list->contains(wasId)) {
|
||||
albumInfo->sets[wasId].albumKnownInArchive.remove(id);
|
||||
}
|
||||
}
|
||||
result->setAlbumIds(*base::take(list));
|
||||
}
|
||||
}
|
||||
|
||||
const auto j = _pollingSettings.find(result);
|
||||
if (j != end(_pollingSettings)) {
|
||||
maybeSchedulePolling(result, j->second, now);
|
||||
@@ -508,6 +536,9 @@ Story *Stories::parseAndApply(
|
||||
data,
|
||||
now
|
||||
)).first->second.get();
|
||||
if (list) {
|
||||
result->setAlbumIds(*base::take(list));
|
||||
}
|
||||
|
||||
if (const auto archive = lookupArchive(peer)) {
|
||||
const auto added = archive->ids.list.emplace(id).second;
|
||||
@@ -827,6 +858,7 @@ void Stories::applyDeleted(not_null<PeerData*> peer, StoryId id) {
|
||||
removeDependencyStory(story.get());
|
||||
const auto removeFromAlbum = [&](int albumId) {
|
||||
if (const auto set = albumIdsSet(peerId, albumId, true)) {
|
||||
set->albumKnownInArchive.remove(id);
|
||||
if (set->ids.list.remove(id)) {
|
||||
if (set->total > 0) {
|
||||
--set->total;
|
||||
@@ -1669,9 +1701,18 @@ bool Stories::albumIdsLoaded(PeerId peerId, int albumId) const {
|
||||
}
|
||||
|
||||
void Stories::albumIdsLoadMore(PeerId peerId, int albumId) {
|
||||
albumIdsLoadMore(peerId, albumId, false);
|
||||
}
|
||||
|
||||
void Stories::albumIdsLoadMore(PeerId peerId, int albumId, bool reload) {
|
||||
Expects(!reload || albumId > 0);
|
||||
|
||||
const auto peer = _owner->peer(peerId);
|
||||
const auto set = albumIdsSet(peerId, albumId);
|
||||
if (!set || set->requestId || set->loaded) {
|
||||
if (set && reload) {
|
||||
_owner->session().api().request(base::take(set->requestId)).cancel();
|
||||
}
|
||||
if (!set || set->requestId || (!reload && set->loaded)) {
|
||||
return;
|
||||
}
|
||||
const auto api = &_owner->session().api();
|
||||
@@ -1681,6 +1722,11 @@ void Stories::albumIdsLoadMore(PeerId peerId, int albumId) {
|
||||
return;
|
||||
}
|
||||
set->requestId = 0;
|
||||
if (reload) {
|
||||
set->ids.list.clear();
|
||||
set->ids.pinnedToTop.clear();
|
||||
set->lastId = StoryId();
|
||||
}
|
||||
const auto &data = result.data();
|
||||
const auto now = base::unixtime::now();
|
||||
auto pinnedToTopIds = data.vpinned_to_top().value_or_empty();
|
||||
@@ -1734,11 +1780,28 @@ void Stories::albumIdsLoadMore(PeerId peerId, int albumId) {
|
||||
: api->request(MTPstories_GetAlbumStories(
|
||||
peer->input,
|
||||
MTP_int(albumId),
|
||||
MTP_int(set->lastId),
|
||||
MTP_int(set->lastId ? kSavedPerPage : kSavedFirstPerPage)
|
||||
MTP_int(reload ? 0 : set->ids.list.size()),
|
||||
MTP_int((reload || set->ids.list.empty())
|
||||
? kSavedFirstPerPage
|
||||
: kSavedPerPage)
|
||||
)).done(done).fail(fail).send();
|
||||
}
|
||||
|
||||
const base::flat_set<StoryId> &Stories::albumKnownInArchive(
|
||||
PeerId peerId,
|
||||
int albumId) const {
|
||||
static const auto empty = base::flat_set<StoryId>();
|
||||
|
||||
const auto i = _albums.find(peerId);
|
||||
if (i == end(_albums)) {
|
||||
return empty;
|
||||
}
|
||||
const auto j = i->second.sets.find(albumId);
|
||||
return (j != end(i->second.sets))
|
||||
? j->second.albumKnownInArchive
|
||||
: empty;
|
||||
}
|
||||
|
||||
auto Stories::albumsListValue(PeerId peerId)
|
||||
-> rpl::producer<std::vector<Data::StoryAlbum>> {
|
||||
auto &albums = _albums[peerId];
|
||||
@@ -1839,6 +1902,33 @@ void Stories::albumRename(
|
||||
}
|
||||
|
||||
void Stories::notifyAlbumUpdate(StoryAlbumUpdate &&update) {
|
||||
const auto peerId = update.peer->id;
|
||||
const auto i = _albums.find(peerId);
|
||||
if (i != end(_albums)) {
|
||||
const auto albumId = update.albumId;
|
||||
const auto j = i->second.sets.find(albumId);
|
||||
if (j != end(i->second.sets)) {
|
||||
for (const auto &id : update.added) {
|
||||
j->second.albumKnownInArchive.emplace(id);
|
||||
if (const auto story = lookup({ peerId, id })) {
|
||||
auto now = (*story)->albumIds();
|
||||
if (now.emplace(albumId).second) {
|
||||
(*story)->setAlbumIds(std::move(now));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto &id : update.removed) {
|
||||
j->second.albumKnownInArchive.remove(id);
|
||||
if (const auto story = lookup({ peerId, id })) {
|
||||
auto now = (*story)->albumIds();
|
||||
if (now.remove(albumId)) {
|
||||
(*story)->setAlbumIds(std::move(now));
|
||||
}
|
||||
}
|
||||
}
|
||||
albumIdsLoadMore(peerId, albumId, true);
|
||||
}
|
||||
}
|
||||
_albumUpdates.fire(std::move(update));
|
||||
}
|
||||
|
||||
|
@@ -213,10 +213,13 @@ public:
|
||||
PeerId peerId,
|
||||
int albumId) const;
|
||||
[[nodiscard]] rpl::producer<StoryAlbumIdsKey> albumIdsChanged() const;
|
||||
[[nodiscard]] int albumIdsCount(PeerId peerIdl, int albumId) const;
|
||||
[[nodiscard]] int albumIdsCount(PeerId peerId, 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]] const base::flat_set<StoryId> &albumKnownInArchive(
|
||||
PeerId peerId,
|
||||
int albumId) const;
|
||||
|
||||
[[nodiscard]] auto albumsListValue(PeerId peerId)
|
||||
-> rpl::producer<std::vector<Data::StoryAlbum>>;
|
||||
@@ -286,6 +289,7 @@ public:
|
||||
private:
|
||||
struct Set {
|
||||
StoriesIds ids;
|
||||
base::flat_set<StoryId> albumKnownInArchive;
|
||||
int total = -1;
|
||||
StoryId lastId = 0;
|
||||
bool loaded = false;
|
||||
@@ -307,6 +311,7 @@ private:
|
||||
DirectRequest,
|
||||
};
|
||||
|
||||
void albumIdsLoadMore(PeerId peerId, int albumId, bool reload);
|
||||
void parseAndApply(const MTPPeerStories &stories, ParseSource source);
|
||||
[[nodiscard]] Story *parseAndApply(
|
||||
not_null<PeerData*> peer,
|
||||
|
@@ -899,10 +899,14 @@ StoryId Story::repostSourceId() const {
|
||||
return _repostSourceId;
|
||||
}
|
||||
|
||||
const std::vector<int> &Story::albumIds() const {
|
||||
const base::flat_set<int> &Story::albumIds() const {
|
||||
return _albumIds;
|
||||
}
|
||||
|
||||
void Story::setAlbumIds(base::flat_set<int> ids) {
|
||||
_albumIds = std::move(ids);
|
||||
}
|
||||
|
||||
PeerData *Story::fromPeer() const {
|
||||
return _fromPeer;
|
||||
}
|
||||
|
@@ -237,7 +237,8 @@ public:
|
||||
[[nodiscard]] QString repostSourceName() const;
|
||||
[[nodiscard]] StoryId repostSourceId() const;
|
||||
|
||||
[[nodiscard]] const std::vector<int> &albumIds() const;
|
||||
[[nodiscard]] const base::flat_set<int> &albumIds() const;
|
||||
void setAlbumIds(base::flat_set<int> ids);
|
||||
|
||||
[[nodiscard]] PeerData *fromPeer() const;
|
||||
|
||||
@@ -267,7 +268,7 @@ private:
|
||||
PeerData * const _repostSourcePeer = nullptr;
|
||||
const QString _repostSourceName;
|
||||
const StoryId _repostSourceId = 0;
|
||||
std::vector<int> _albumIds;
|
||||
base::flat_set<int> _albumIds;
|
||||
PeerData * const _fromPeer = nullptr;
|
||||
Data::ReactionId _sentReactionId;
|
||||
StoryMedia _media;
|
||||
|
Reference in New Issue
Block a user