| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- 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
- */
- #include "storage/storage_user_photos.h"
- namespace Storage {
- void UserPhotos::List::setBack(PhotoId photoId) {
- if (_backPhotoId != photoId) {
- detachBack();
- _backPhotoId = photoId;
- attachBack();
- sendUpdate();
- }
- }
- void UserPhotos::List::detachBack() {
- if (_backPhotoId) {
- removeOne(_backPhotoId);
- }
- }
- void UserPhotos::List::attachBack() {
- if (_backPhotoId) {
- _photoIds.push_front(_backPhotoId);
- if (_count) {
- ++*_count;
- }
- }
- }
- void UserPhotos::List::addNew(PhotoId photoId) {
- if (!base::contains(_photoIds, photoId)) {
- detachBack();
- _photoIds.push_back(photoId);
- if (_count) {
- ++*_count;
- }
- attachBack();
- sendUpdate();
- }
- }
- void UserPhotos::List::addSlice(
- std::vector<PhotoId> &&photoIds,
- int count) {
- detachBack();
- for (auto photoId : photoIds) {
- if (!base::contains(_photoIds, photoId)) {
- _photoIds.push_front(photoId);
- }
- }
- _count = count;
- if ((_count && *_count < _photoIds.size()) || photoIds.empty()) {
- _count = _photoIds.size();
- }
- attachBack();
- sendUpdate();
- }
- void UserPhotos::List::removeOne(PhotoId photoId) {
- auto position = ranges::find(_photoIds, photoId);
- if (position == _photoIds.end()) {
- _count = std::nullopt;
- } else {
- if (_count) {
- --*_count;
- }
- _photoIds.erase(position);
- }
- sendUpdate();
- }
- void UserPhotos::List::removeAfter(PhotoId photoId) {
- auto position = ranges::find(_photoIds, photoId);
- if (position == _photoIds.end()) {
- _count = std::nullopt;
- _photoIds.clear();
- } else {
- if (_count) {
- *_count -= (_photoIds.end() - position);
- }
- _photoIds.erase(position, _photoIds.end());
- }
- sendUpdate();
- }
- void UserPhotos::List::sendUpdate() {
- auto update = SliceUpdate();
- update.photoIds = &_photoIds;
- update.count = _count;
- _sliceUpdated.fire(std::move(update));
- }
- rpl::producer<UserPhotosResult> UserPhotos::List::query(
- UserPhotosQuery &&query) const {
- return [this, query = std::move(query)](auto consumer) {
- auto result = UserPhotosResult();
- result.count = _count;
- auto position = ranges::find(_photoIds, query.key.photoId);
- if (position != _photoIds.end()) {
- auto haveBefore = int(position - _photoIds.begin());
- auto haveEqualOrAfter = int(_photoIds.end() - position);
- auto before = qMin(haveBefore, query.limitBefore);
- auto equalOrAfter = qMin(haveEqualOrAfter, query.limitAfter + 1);
- result.photoIds = std::deque<PhotoId>(
- position - before,
- position + equalOrAfter);
- auto skippedInIds = (haveBefore - before);
- result.skippedBefore = _count
- | func::add(-int(_photoIds.size()) + skippedInIds);
- result.skippedBefore = haveBefore - before;
- result.skippedAfter = (haveEqualOrAfter - equalOrAfter);
- consumer.put_next(std::move(result));
- } else if (query.key.back && _backPhotoId) {
- result.photoIds.push_front(_backPhotoId);
- result.count = 1;
- consumer.put_next(std::move(result));
- } else if (_count) {
- consumer.put_next(std::move(result));
- }
- consumer.put_done();
- return rpl::lifetime();
- };
- }
- auto UserPhotos::List::sliceUpdated() const -> rpl::producer<SliceUpdate> {
- return _sliceUpdated.events();
- }
- rpl::producer<UserPhotosSliceUpdate> UserPhotos::sliceUpdated() const {
- return _sliceUpdated.events();
- }
- std::map<UserId, UserPhotos::List>::iterator UserPhotos::enforceLists(
- UserId user) {
- auto result = _lists.find(user);
- if (result != _lists.end()) {
- return result;
- }
- result = _lists.emplace(user, List {}).first;
- result->second.sliceUpdated(
- ) | rpl::start_with_next([this, user](
- const SliceUpdate &update) {
- _sliceUpdated.fire(UserPhotosSliceUpdate(
- user,
- update.photoIds,
- update.count));
- }, _lifetime);
- return result;
- }
- void UserPhotos::add(UserPhotosSetBack &&query) {
- auto userIt = enforceLists(query.userId);
- userIt->second.setBack(query.photoId);
- }
- void UserPhotos::add(UserPhotosAddNew &&query) {
- auto userIt = enforceLists(query.userId);
- userIt->second.addNew(query.photoId);
- }
- void UserPhotos::add(UserPhotosAddSlice &&query) {
- auto userIt = enforceLists(query.userId);
- userIt->second.addSlice(
- std::move(query.photoIds),
- query.count);
- }
- void UserPhotos::remove(UserPhotosRemoveOne &&query) {
- auto userIt = _lists.find(query.userId);
- if (userIt != _lists.end()) {
- userIt->second.removeOne(query.photoId);
- }
- }
- void UserPhotos::remove(UserPhotosRemoveAfter &&query) {
- auto userIt = _lists.find(query.userId);
- if (userIt != _lists.end()) {
- userIt->second.removeAfter(query.photoId);
- }
- }
- rpl::producer<UserPhotosResult> UserPhotos::query(
- UserPhotosQuery &&query) const {
- auto userIt = _lists.find(query.key.userId);
- if (userIt != _lists.end()) {
- return userIt->second.query(std::move(query));
- }
- return [](auto consumer) {
- consumer.put_done();
- return rpl::lifetime();
- };
- }
- } // namespace Storage
|