2017-08-29 19:52:52 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
2018-01-03 10:23:14 +00:00
|
|
|
the official desktop application for the Telegram messaging service.
|
2017-08-29 19:52:52 +00:00
|
|
|
|
2018-01-03 10:23:14 +00:00
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
2017-08-29 19:52:52 +00:00
|
|
|
*/
|
|
|
|
#include "storage/storage_user_photos.h"
|
|
|
|
|
|
|
|
namespace Storage {
|
|
|
|
|
2022-12-19 10:01:32 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-29 19:52:52 +00:00
|
|
|
void UserPhotos::List::addNew(PhotoId photoId) {
|
|
|
|
if (!base::contains(_photoIds, photoId)) {
|
2022-12-19 10:01:32 +00:00
|
|
|
detachBack();
|
2017-08-29 19:52:52 +00:00
|
|
|
_photoIds.push_back(photoId);
|
|
|
|
if (_count) {
|
|
|
|
++*_count;
|
|
|
|
}
|
2022-12-19 10:01:32 +00:00
|
|
|
attachBack();
|
2017-08-29 19:52:52 +00:00
|
|
|
sendUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPhotos::List::addSlice(
|
|
|
|
std::vector<PhotoId> &&photoIds,
|
|
|
|
int count) {
|
2022-12-19 10:01:32 +00:00
|
|
|
detachBack();
|
2017-08-29 19:52:52 +00:00
|
|
|
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();
|
|
|
|
}
|
2022-12-19 10:01:32 +00:00
|
|
|
attachBack();
|
2017-08-29 19:52:52 +00:00
|
|
|
sendUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPhotos::List::removeOne(PhotoId photoId) {
|
2017-11-20 12:23:20 +00:00
|
|
|
auto position = ranges::find(_photoIds, photoId);
|
2017-08-29 19:52:52 +00:00
|
|
|
if (position == _photoIds.end()) {
|
2018-09-21 16:28:46 +00:00
|
|
|
_count = std::nullopt;
|
2017-08-29 19:52:52 +00:00
|
|
|
} else {
|
|
|
|
if (_count) {
|
|
|
|
--*_count;
|
|
|
|
}
|
|
|
|
_photoIds.erase(position);
|
|
|
|
}
|
|
|
|
sendUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPhotos::List::removeAfter(PhotoId photoId) {
|
2017-11-20 12:23:20 +00:00
|
|
|
auto position = ranges::find(_photoIds, photoId);
|
2017-08-29 19:52:52 +00:00
|
|
|
if (position == _photoIds.end()) {
|
2018-09-21 16:28:46 +00:00
|
|
|
_count = std::nullopt;
|
2017-08-29 19:52:52 +00:00
|
|
|
_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;
|
2017-09-06 14:50:11 +00:00
|
|
|
_sliceUpdated.fire(std::move(update));
|
2017-08-29 19:52:52 +00:00
|
|
|
}
|
|
|
|
|
2017-09-06 14:50:11 +00:00
|
|
|
rpl::producer<UserPhotosResult> UserPhotos::List::query(
|
|
|
|
UserPhotosQuery &&query) const {
|
|
|
|
return [this, query = std::move(query)](auto consumer) {
|
2022-12-19 10:01:32 +00:00
|
|
|
auto result = UserPhotosResult();
|
2017-09-06 14:50:11 +00:00
|
|
|
result.count = _count;
|
|
|
|
|
2017-11-20 12:23:20 +00:00
|
|
|
auto position = ranges::find(_photoIds, query.key.photoId);
|
2017-09-06 14:50:11 +00:00
|
|
|
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));
|
2022-12-19 10:01:32 +00:00
|
|
|
} else if (query.key.back && _backPhotoId) {
|
|
|
|
result.photoIds.push_front(_backPhotoId);
|
|
|
|
result.count = 1;
|
|
|
|
consumer.put_next(std::move(result));
|
2017-09-06 14:50:11 +00:00
|
|
|
} else if (_count) {
|
|
|
|
consumer.put_next(std::move(result));
|
|
|
|
}
|
|
|
|
consumer.put_done();
|
|
|
|
return rpl::lifetime();
|
|
|
|
};
|
2017-08-29 19:52:52 +00:00
|
|
|
}
|
|
|
|
|
2017-11-21 09:20:56 +00:00
|
|
|
auto UserPhotos::List::sliceUpdated() const -> rpl::producer<SliceUpdate> {
|
|
|
|
return _sliceUpdated.events();
|
|
|
|
}
|
|
|
|
|
|
|
|
rpl::producer<UserPhotosSliceUpdate> UserPhotos::sliceUpdated() const {
|
|
|
|
return _sliceUpdated.events();
|
|
|
|
}
|
|
|
|
|
2022-12-19 10:01:32 +00:00
|
|
|
std::map<UserId, UserPhotos::List>::iterator UserPhotos::enforceLists(
|
|
|
|
UserId user) {
|
2017-08-29 19:52:52 +00:00
|
|
|
auto result = _lists.find(user);
|
|
|
|
if (result != _lists.end()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = _lists.emplace(user, List {}).first;
|
2017-09-06 14:50:11 +00:00
|
|
|
result->second.sliceUpdated(
|
2017-09-27 08:43:35 +00:00
|
|
|
) | rpl::start_with_next([this, user](
|
|
|
|
const SliceUpdate &update) {
|
2017-09-06 14:50:11 +00:00
|
|
|
_sliceUpdated.fire(UserPhotosSliceUpdate(
|
2017-08-29 19:52:52 +00:00
|
|
|
user,
|
|
|
|
update.photoIds,
|
2017-09-06 14:50:11 +00:00
|
|
|
update.count));
|
2017-09-18 17:04:45 +00:00
|
|
|
}, _lifetime);
|
2017-08-29 19:52:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-12-19 10:01:32 +00:00
|
|
|
void UserPhotos::add(UserPhotosSetBack &&query) {
|
|
|
|
auto userIt = enforceLists(query.userId);
|
|
|
|
userIt->second.setBack(query.photoId);
|
|
|
|
}
|
|
|
|
|
2017-08-29 19:52:52 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 10:01:32 +00:00
|
|
|
rpl::producer<UserPhotosResult> UserPhotos::query(
|
|
|
|
UserPhotosQuery &&query) const {
|
2017-08-29 19:52:52 +00:00
|
|
|
auto userIt = _lists.find(query.key.userId);
|
|
|
|
if (userIt != _lists.end()) {
|
2017-09-06 14:50:11 +00:00
|
|
|
return userIt->second.query(std::move(query));
|
2017-08-29 19:52:52 +00:00
|
|
|
}
|
2017-09-06 14:50:11 +00:00
|
|
|
return [](auto consumer) {
|
|
|
|
consumer.put_done();
|
|
|
|
return rpl::lifetime();
|
|
|
|
};
|
2017-08-29 19:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Storage
|