/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include #include "storage/storage_facade.h" namespace Storage { struct UserPhotosAddNew { UserPhotosAddNew(UserId userId, PhotoId photoId) : userId(userId), photoId(photoId) { } UserId userId = 0; PhotoId photoId = 0; }; struct UserPhotosAddSlice { UserPhotosAddSlice( UserId userId, std::vector &&photoIds, int count) : userId(userId) , photoIds(std::move(photoIds)) , count(count) { } UserId userId = 0; std::vector photoIds; int count = 0; }; struct UserPhotosRemoveOne { UserPhotosRemoveOne( UserId userId, PhotoId photoId) : userId(userId) , photoId(photoId) { } UserId userId = 0; PhotoId photoId = 0; }; struct UserPhotosRemoveAfter { UserPhotosRemoveAfter( UserId userId, PhotoId photoId) : userId(userId) , photoId(photoId) { } UserId userId = 0; PhotoId photoId = 0; }; struct UserPhotosKey { UserPhotosKey( UserId userId, PhotoId photoId) : userId(userId) , photoId(photoId) { } bool operator==(const UserPhotosKey &other) const { return (userId == other.userId) && (photoId == other.photoId); } bool operator!=(const UserPhotosKey &other) const { return !(*this == other); } UserId userId = 0; PhotoId photoId = 0; }; struct UserPhotosQuery { UserPhotosQuery( UserPhotosKey key, int limitBefore, int limitAfter) : key(key) , limitBefore(limitBefore) , limitAfter(limitAfter) { } UserPhotosKey key; int limitBefore = 0; int limitAfter = 0; }; struct UserPhotosResult { std::optional count; std::optional skippedBefore; int skippedAfter = 0; std::deque photoIds; }; struct UserPhotosSliceUpdate { UserPhotosSliceUpdate( UserId userId, const std::deque *photoIds, std::optional count) : userId(userId) , photoIds(photoIds) , count(count) { } UserId userId = 0; const std::deque *photoIds = nullptr; std::optional count; }; class UserPhotos { public: void add(UserPhotosAddNew &&query); void add(UserPhotosAddSlice &&query); void remove(UserPhotosRemoveOne &&query); void remove(UserPhotosRemoveAfter &&query); rpl::producer query(UserPhotosQuery &&query) const; rpl::producer sliceUpdated() const; private: class List { public: void addNew(PhotoId photoId); void addSlice( std::vector &&photoIds, int count); void removeOne(PhotoId photoId); void removeAfter(PhotoId photoId); rpl::producer query(UserPhotosQuery &&query) const; struct SliceUpdate { const std::deque *photoIds = nullptr; std::optional count; }; rpl::producer sliceUpdated() const; private: void sendUpdate(); std::optional _count; std::deque _photoIds; rpl::event_stream _sliceUpdated; }; using SliceUpdate = List::SliceUpdate; std::map::iterator enforceLists(UserId user); std::map _lists; rpl::event_stream _sliceUpdated; rpl::lifetime _lifetime; }; } // namespace Storage