mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-30 03:34:17 +00:00
Implement UserPhotosViewer using rpl.
This commit is contained in:
parent
2690618da2
commit
696478843e
@ -25,14 +25,25 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "storage/storage_facade.h"
|
||||
#include "storage/storage_user_photos.h"
|
||||
|
||||
UserPhotosSlice::UserPhotosSlice(Key key) : UserPhotosSlice(key, base::none) {
|
||||
UserPhotosSlice::UserPhotosSlice(Key key) : UserPhotosSlice(
|
||||
key,
|
||||
{},
|
||||
base::none,
|
||||
base::none,
|
||||
0) {
|
||||
}
|
||||
|
||||
UserPhotosSlice::UserPhotosSlice(
|
||||
Key key,
|
||||
base::optional<int> fullCount)
|
||||
const std::deque<PhotoId> &ids,
|
||||
base::optional<int> fullCount,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter)
|
||||
: _key(key)
|
||||
, _fullCount(fullCount) {
|
||||
, _ids(ids)
|
||||
, _fullCount(fullCount)
|
||||
, _skippedBefore(skippedBefore)
|
||||
, _skippedAfter(skippedAfter) {
|
||||
}
|
||||
|
||||
base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const {
|
||||
@ -79,82 +90,62 @@ QString UserPhotosSlice::debug() const {
|
||||
return before + middle + after;
|
||||
}
|
||||
|
||||
UserPhotosViewer::UserPhotosViewer(
|
||||
class UserPhotosSliceBuilder {
|
||||
public:
|
||||
using Key = UserPhotosSlice::Key;
|
||||
|
||||
UserPhotosSliceBuilder(Key key, int limitBefore, int limitAfter);
|
||||
|
||||
bool applyUpdate(const Storage::UserPhotosResult &update);
|
||||
bool applyUpdate(const Storage::UserPhotosSliceUpdate &update);
|
||||
void checkInsufficientPhotos();
|
||||
rpl::producer<PhotoId> insufficientPhotosAround() const {
|
||||
return _insufficientPhotosAround.events();
|
||||
}
|
||||
|
||||
UserPhotosSlice snapshot() const;
|
||||
|
||||
private:
|
||||
void mergeSliceData(
|
||||
base::optional<int> count,
|
||||
const std::deque<PhotoId> &photoIds,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter);
|
||||
void sliceToLimits();
|
||||
|
||||
Key _key;
|
||||
std::deque<PhotoId> _ids;
|
||||
base::optional<int> _fullCount;
|
||||
base::optional<int> _skippedBefore;
|
||||
int _skippedAfter = 0;
|
||||
int _limitBefore = 0;
|
||||
int _limitAfter = 0;
|
||||
|
||||
rpl::event_stream<PhotoId> _insufficientPhotosAround;
|
||||
|
||||
};
|
||||
|
||||
UserPhotosSliceBuilder::UserPhotosSliceBuilder(
|
||||
Key key,
|
||||
int limitBefore,
|
||||
int limitAfter)
|
||||
: _key(key)
|
||||
, _limitBefore(limitBefore)
|
||||
, _limitAfter(limitAfter)
|
||||
, _data(_key) {
|
||||
, _limitAfter(limitAfter) {
|
||||
}
|
||||
|
||||
void UserPhotosViewer::start() {
|
||||
auto applyUpdateCallback = [this](auto &update) {
|
||||
this->applyUpdate(update);
|
||||
};
|
||||
subscribe(Auth().storage().userPhotosSliceUpdated(), applyUpdateCallback);
|
||||
|
||||
loadInitial();
|
||||
}
|
||||
|
||||
void UserPhotosViewer::loadInitial() {
|
||||
auto weak = base::make_weak_unique(this);
|
||||
Auth().storage().query(Storage::UserPhotosQuery(
|
||||
_key,
|
||||
_limitBefore,
|
||||
_limitAfter), [weak](Storage::UserPhotosResult &&result) {
|
||||
if (weak) {
|
||||
weak->applyStoredResult(std::move(result));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UserPhotosViewer::applyStoredResult(Storage::UserPhotosResult &&result) {
|
||||
bool UserPhotosSliceBuilder::applyUpdate(const Storage::UserPhotosResult &update) {
|
||||
mergeSliceData(
|
||||
result.count,
|
||||
result.photoIds,
|
||||
result.skippedBefore,
|
||||
result.skippedAfter);
|
||||
update.count,
|
||||
update.photoIds,
|
||||
update.skippedBefore,
|
||||
update.skippedAfter);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UserPhotosViewer::mergeSliceData(
|
||||
base::optional<int> count,
|
||||
const std::deque<PhotoId> &photoIds,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter) {
|
||||
if (photoIds.empty()) {
|
||||
if (_data._fullCount != count) {
|
||||
_data._fullCount = count;
|
||||
if (_data._fullCount && *_data._fullCount <= _data.size()) {
|
||||
_data._fullCount = _data.size();
|
||||
_data._skippedBefore = _data._skippedAfter = 0;
|
||||
}
|
||||
updated.notify(_data);
|
||||
}
|
||||
sliceToLimits();
|
||||
return;
|
||||
}
|
||||
if (count) {
|
||||
_data._fullCount = count;
|
||||
}
|
||||
_data._skippedAfter = skippedAfter;
|
||||
_data._ids = photoIds;
|
||||
|
||||
if (_data._fullCount) {
|
||||
_data._skippedBefore = *_data._fullCount
|
||||
- _data._skippedAfter
|
||||
- int(_data._ids.size());
|
||||
}
|
||||
|
||||
sliceToLimits();
|
||||
|
||||
updated.notify(_data);
|
||||
}
|
||||
|
||||
void UserPhotosViewer::applyUpdate(const SliceUpdate &update) {
|
||||
bool UserPhotosSliceBuilder::applyUpdate(const Storage::UserPhotosSliceUpdate &update) {
|
||||
if (update.userId != _key.userId) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
auto idsCount = update.photoIds ? int(update.photoIds->size()) : 0;
|
||||
mergeSliceData(
|
||||
@ -162,28 +153,99 @@ void UserPhotosViewer::applyUpdate(const SliceUpdate &update) {
|
||||
update.photoIds ? *update.photoIds : std::deque<PhotoId> {},
|
||||
update.count | func::add(-idsCount),
|
||||
0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UserPhotosViewer::sliceToLimits() {
|
||||
auto aroundIt = base::find(_data._ids, _key.photoId);
|
||||
auto removeFromBegin = (aroundIt - _data._ids.begin() - _limitBefore);
|
||||
auto removeFromEnd = (_data._ids.end() - aroundIt - _limitAfter - 1);
|
||||
void UserPhotosSliceBuilder::checkInsufficientPhotos() {
|
||||
sliceToLimits();
|
||||
}
|
||||
|
||||
void UserPhotosSliceBuilder::mergeSliceData(
|
||||
base::optional<int> count,
|
||||
const std::deque<PhotoId> &photoIds,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter) {
|
||||
if (photoIds.empty()) {
|
||||
if (_fullCount != count) {
|
||||
_fullCount = count;
|
||||
if (_fullCount && *_fullCount <= _ids.size()) {
|
||||
_fullCount = _ids.size();
|
||||
_skippedBefore = _skippedAfter = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (count) {
|
||||
_fullCount = count;
|
||||
}
|
||||
_skippedAfter = skippedAfter;
|
||||
_ids = photoIds;
|
||||
|
||||
if (_fullCount) {
|
||||
_skippedBefore = *_fullCount
|
||||
- _skippedAfter
|
||||
- int(_ids.size());
|
||||
}
|
||||
}
|
||||
sliceToLimits();
|
||||
}
|
||||
|
||||
void UserPhotosSliceBuilder::sliceToLimits() {
|
||||
auto aroundIt = base::find(_ids, _key.photoId);
|
||||
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
||||
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
||||
if (removeFromEnd > 0) {
|
||||
_data._ids.erase(_data._ids.end() - removeFromEnd, _data._ids.end());
|
||||
_data._skippedAfter += removeFromEnd;
|
||||
_ids.erase(_ids.end() - removeFromEnd, _ids.end());
|
||||
_skippedAfter += removeFromEnd;
|
||||
}
|
||||
if (removeFromBegin > 0) {
|
||||
_data._ids.erase(_data._ids.begin(), _data._ids.begin() + removeFromBegin);
|
||||
if (_data._skippedBefore) {
|
||||
*_data._skippedBefore += removeFromBegin;
|
||||
_ids.erase(_ids.begin(), _ids.begin() + removeFromBegin);
|
||||
if (_skippedBefore) {
|
||||
*_skippedBefore += removeFromBegin;
|
||||
}
|
||||
} else if (removeFromBegin < 0 && (!_data._skippedBefore || *_data._skippedBefore > 0)) {
|
||||
requestPhotos();
|
||||
} else if (removeFromBegin < 0 && (!_skippedBefore || *_skippedBefore > 0)) {
|
||||
_insufficientPhotosAround.fire(_ids.empty() ? 0 : _ids.front());
|
||||
}
|
||||
}
|
||||
|
||||
void UserPhotosViewer::requestPhotos() {
|
||||
Auth().api().requestUserPhotos(
|
||||
App::user(_key.userId),
|
||||
_data._ids.empty() ? 0 : _data._ids.front());
|
||||
UserPhotosSlice UserPhotosSliceBuilder::snapshot() const {
|
||||
return UserPhotosSlice(_key, _ids, _fullCount, _skippedBefore, _skippedAfter);
|
||||
}
|
||||
|
||||
rpl::producer<UserPhotosSlice> UserPhotosViewer(
|
||||
UserPhotosSlice::Key key,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
return [key, limitBefore, limitAfter](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
auto builder = lifetime.make_state<UserPhotosSliceBuilder>(
|
||||
key,
|
||||
limitBefore,
|
||||
limitAfter);
|
||||
auto applyUpdate = [=](auto &&update) {
|
||||
if (builder->applyUpdate(std::move(update))) {
|
||||
consumer.put_next(builder->snapshot());
|
||||
}
|
||||
};
|
||||
auto requestPhotosAround = [user = App::user(key.userId)](PhotoId photoId) {
|
||||
Auth().api().requestUserPhotos(user, photoId);
|
||||
};
|
||||
builder->insufficientPhotosAround()
|
||||
| rpl::on_next(requestPhotosAround)
|
||||
| rpl::start(lifetime);
|
||||
|
||||
Auth().storage().userPhotosSliceUpdated()
|
||||
| rpl::on_next(applyUpdate)
|
||||
| rpl::start(lifetime);
|
||||
|
||||
Auth().storage().query(Storage::UserPhotosQuery(
|
||||
key,
|
||||
limitBefore,
|
||||
limitAfter
|
||||
))
|
||||
| rpl::on_next(applyUpdate)
|
||||
| rpl::on_done([=] { builder->checkInsufficientPhotos(); })
|
||||
| rpl::start(lifetime);
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
@ -23,13 +23,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "storage/storage_user_photos.h"
|
||||
#include "base/weak_unique_ptr.h"
|
||||
|
||||
class UserPhotosViewer;
|
||||
class UserPhotosSlice {
|
||||
public:
|
||||
using Key = Storage::UserPhotosKey;
|
||||
|
||||
UserPhotosSlice(Key key);
|
||||
UserPhotosSlice(Key key, base::optional<int> fullCount);
|
||||
UserPhotosSlice(
|
||||
Key key,
|
||||
const std::deque<PhotoId> &ids,
|
||||
base::optional<int> fullCount,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter);
|
||||
|
||||
const Key &key() const { return _key; }
|
||||
|
||||
@ -50,41 +54,11 @@ private:
|
||||
base::optional<int> _skippedBefore;
|
||||
int _skippedAfter = 0;
|
||||
|
||||
friend class UserPhotosViewer;
|
||||
friend class UserPhotosSliceBuilder;
|
||||
|
||||
};
|
||||
|
||||
class UserPhotosViewer :
|
||||
private base::Subscriber,
|
||||
public base::enable_weak_from_this {
|
||||
public:
|
||||
using Key = Storage::UserPhotosKey;
|
||||
|
||||
UserPhotosViewer(Key key, int limitBefore, int limitAfter);
|
||||
|
||||
void start();
|
||||
|
||||
base::Observable<UserPhotosSlice> updated;
|
||||
|
||||
private:
|
||||
using InitialResult = Storage::UserPhotosResult;
|
||||
using SliceUpdate = Storage::UserPhotosSliceUpdate;
|
||||
|
||||
void loadInitial();
|
||||
void requestPhotos();
|
||||
void applyStoredResult(InitialResult &&result);
|
||||
void applyUpdate(const SliceUpdate &update);
|
||||
void sliceToLimits();
|
||||
|
||||
void mergeSliceData(
|
||||
base::optional<int> count,
|
||||
const std::deque<PhotoId> &photoIds,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter);
|
||||
|
||||
Key _key;
|
||||
int _limitBefore = 0;
|
||||
int _limitAfter = 0;
|
||||
UserPhotosSlice _data;
|
||||
|
||||
};
|
||||
rpl::producer<UserPhotosSlice> UserPhotosViewer(
|
||||
UserPhotosSlice::Key key,
|
||||
int limitBefore,
|
||||
int limitAfter);
|
||||
|
@ -78,13 +78,12 @@ struct MediaView::SharedMedia {
|
||||
};
|
||||
|
||||
struct MediaView::UserPhotos {
|
||||
UserPhotos(UserPhotosViewer::Key key)
|
||||
: key(key)
|
||||
, slice(key, kIdsLimit, kIdsLimit) {
|
||||
UserPhotos(UserPhotosSlice::Key key)
|
||||
: key(key) {
|
||||
}
|
||||
|
||||
UserPhotosViewer::Key key;
|
||||
UserPhotosViewer slice;
|
||||
UserPhotosSlice::Key key;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
MediaView::MediaView() : TWidget(nullptr)
|
||||
@ -1075,7 +1074,7 @@ void MediaView::validateSharedMedia() {
|
||||
}
|
||||
|
||||
void MediaView::handleSharedMediaUpdate(const SharedMediaSliceWithLast &update) {
|
||||
if (isHidden() || (!_photo && !_doc) || !_sharedMedia) {
|
||||
if ((!_photo && !_doc) || !_sharedMedia) {
|
||||
_sharedMediaData = base::none;
|
||||
} else {
|
||||
_sharedMediaData = update;
|
||||
@ -1120,21 +1119,24 @@ bool MediaView::validUserPhotos() const {
|
||||
void MediaView::validateUserPhotos() {
|
||||
if (auto key = userPhotosKey()) {
|
||||
_userPhotos = std::make_unique<UserPhotos>(*key);
|
||||
subscribe(_userPhotos->slice.updated, [this](const UserPhotosSlice &data) {
|
||||
handleUserPhotosUpdate(data);
|
||||
});
|
||||
_userPhotos->slice.start();
|
||||
UserPhotosViewer(
|
||||
*key,
|
||||
kIdsLimit,
|
||||
kIdsLimit
|
||||
) | rpl::on_next([this](UserPhotosSlice &&update) {
|
||||
handleUserPhotosUpdate(std::move(update));
|
||||
}) | rpl::start(_userPhotos->lifetime);
|
||||
} else {
|
||||
_userPhotos = nullptr;
|
||||
_userPhotosData = base::none;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaView::handleUserPhotosUpdate(const UserPhotosSlice &update) {
|
||||
if (isHidden() || !_photo || !_userPhotos) {
|
||||
void MediaView::handleUserPhotosUpdate(UserPhotosSlice &&update) {
|
||||
if (!_photo || !_userPhotos) {
|
||||
_userPhotosData = base::none;
|
||||
} else {
|
||||
_userPhotosData = update;
|
||||
_userPhotosData = std::move(update);
|
||||
}
|
||||
findCurrent();
|
||||
updateControls();
|
||||
|
@ -178,11 +178,11 @@ private:
|
||||
void handleSharedMediaUpdate(const SharedMediaSliceWithLast &update);
|
||||
|
||||
struct UserPhotos;
|
||||
using UserPhotosKey = UserPhotosViewer::Key;
|
||||
using UserPhotosKey = UserPhotosSlice::Key;
|
||||
base::optional<UserPhotosKey> userPhotosKey() const;
|
||||
bool validUserPhotos() const;
|
||||
void validateUserPhotos();
|
||||
void handleUserPhotosUpdate(const UserPhotosSlice &update);
|
||||
void handleUserPhotosUpdate(UserPhotosSlice &&update);
|
||||
|
||||
void refreshMediaViewer();
|
||||
void refreshNavVisibility();
|
||||
|
@ -44,11 +44,9 @@ public:
|
||||
void add(UserPhotosAddSlice &&query);
|
||||
void remove(UserPhotosRemoveOne &&query);
|
||||
void remove(UserPhotosRemoveAfter &&query);
|
||||
void query(
|
||||
UserPhotosQuery &&query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback);
|
||||
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
||||
|
||||
base::Observable<UserPhotosSliceUpdate> &userPhotosSliceUpdated();
|
||||
rpl::producer<UserPhotosSliceUpdate> userPhotosSliceUpdated() const;
|
||||
|
||||
private:
|
||||
SharedMedia _sharedMedia;
|
||||
@ -110,14 +108,12 @@ void Facade::Impl::remove(UserPhotosRemoveAfter &&query) {
|
||||
return _userPhotos.remove(std::move(query));
|
||||
}
|
||||
|
||||
void Facade::Impl::query(
|
||||
UserPhotosQuery &&query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback) {
|
||||
return _userPhotos.query(std::move(query), std::move(callback));
|
||||
rpl::producer<UserPhotosResult> Facade::Impl::query(UserPhotosQuery &&query) const {
|
||||
return _userPhotos.query(std::move(query));
|
||||
}
|
||||
|
||||
base::Observable<UserPhotosSliceUpdate> &Facade::Impl::userPhotosSliceUpdated() {
|
||||
return _userPhotos.sliceUpdated;
|
||||
rpl::producer<UserPhotosSliceUpdate> Facade::Impl::userPhotosSliceUpdated() const {
|
||||
return _userPhotos.sliceUpdated();
|
||||
}
|
||||
|
||||
Facade::Facade() : _impl(std::make_unique<Impl>()) {
|
||||
@ -177,13 +173,11 @@ void Facade::remove(UserPhotosRemoveAfter &&query) {
|
||||
return _impl->remove(std::move(query));
|
||||
}
|
||||
|
||||
void Facade::query(
|
||||
UserPhotosQuery &&query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback) {
|
||||
return _impl->query(std::move(query), std::move(callback));
|
||||
rpl::producer<UserPhotosResult> Facade::query(UserPhotosQuery &&query) const {
|
||||
return _impl->query(std::move(query));
|
||||
}
|
||||
|
||||
base::Observable<UserPhotosSliceUpdate> &Facade::userPhotosSliceUpdated() {
|
||||
rpl::producer<UserPhotosSliceUpdate> Facade::userPhotosSliceUpdated() const {
|
||||
return _impl->userPhotosSliceUpdated();
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "base/enum_mask.h"
|
||||
#include "rpl/producer.h"
|
||||
|
||||
namespace Storage {
|
||||
|
||||
@ -62,11 +63,9 @@ public:
|
||||
void add(UserPhotosAddSlice &&query);
|
||||
void remove(UserPhotosRemoveOne &&query);
|
||||
void remove(UserPhotosRemoveAfter &&query);
|
||||
void query(
|
||||
UserPhotosQuery &&query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback);
|
||||
|
||||
base::Observable<UserPhotosSliceUpdate> &userPhotosSliceUpdated();
|
||||
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
||||
rpl::producer<UserPhotosSliceUpdate> userPhotosSliceUpdated() const;
|
||||
|
||||
~Facade();
|
||||
|
||||
|
@ -81,38 +81,37 @@ void UserPhotos::List::sendUpdate() {
|
||||
auto update = SliceUpdate();
|
||||
update.photoIds = &_photoIds;
|
||||
update.count = _count;
|
||||
sliceUpdated.notify(update, true);
|
||||
_sliceUpdated.fire(std::move(update));
|
||||
}
|
||||
|
||||
void UserPhotos::List::query(
|
||||
const UserPhotosQuery &query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback) {
|
||||
auto result = UserPhotosResult {};
|
||||
result.count = _count;
|
||||
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 = base::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 position = base::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);
|
||||
}
|
||||
base::TaskQueue::Main().Put(
|
||||
[
|
||||
callback = std::move(callback),
|
||||
result = std::move(result)
|
||||
]() mutable {
|
||||
callback(std::move(result));
|
||||
});
|
||||
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 (_count) {
|
||||
consumer.put_next(std::move(result));
|
||||
}
|
||||
consumer.put_done();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
std::map<UserId, UserPhotos::List>::iterator
|
||||
@ -122,12 +121,13 @@ UserPhotos::enforceLists(UserId user) {
|
||||
return result;
|
||||
}
|
||||
result = _lists.emplace(user, List {}).first;
|
||||
subscribe(result->second.sliceUpdated, [this, user](const SliceUpdate &update) {
|
||||
sliceUpdated.notify(UserPhotosSliceUpdate(
|
||||
result->second.sliceUpdated(
|
||||
) | rpl::on_next([this, user](SliceUpdate &&update) {
|
||||
_sliceUpdated.fire(UserPhotosSliceUpdate(
|
||||
user,
|
||||
update.photoIds,
|
||||
update.count), true);
|
||||
});
|
||||
update.count));
|
||||
}) | rpl::start(_lifetime);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -157,20 +157,15 @@ void UserPhotos::remove(UserPhotosRemoveAfter &&query) {
|
||||
}
|
||||
}
|
||||
|
||||
void UserPhotos::query(
|
||||
const UserPhotosQuery &query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback) {
|
||||
rpl::producer<UserPhotosResult> UserPhotos::query(UserPhotosQuery &&query) const {
|
||||
auto userIt = _lists.find(query.key.userId);
|
||||
if (userIt != _lists.end()) {
|
||||
userIt->second.query(query, std::move(callback));
|
||||
} else {
|
||||
base::TaskQueue::Main().Put(
|
||||
[
|
||||
callback = std::move(callback)
|
||||
]() mutable {
|
||||
callback(UserPhotosResult());
|
||||
});
|
||||
return userIt->second.query(std::move(query));
|
||||
}
|
||||
return [](auto consumer) {
|
||||
consumer.put_done();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Storage
|
||||
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "storage/storage_facade.h"
|
||||
#include "rpl/event_stream.h"
|
||||
|
||||
namespace Storage {
|
||||
|
||||
@ -135,17 +136,18 @@ struct UserPhotosSliceUpdate {
|
||||
base::optional<int> count;
|
||||
};
|
||||
|
||||
class UserPhotos : private base::Subscriber {
|
||||
class UserPhotos {
|
||||
public:
|
||||
void add(UserPhotosAddNew &&query);
|
||||
void add(UserPhotosAddSlice &&query);
|
||||
void remove(UserPhotosRemoveOne &&query);
|
||||
void remove(UserPhotosRemoveAfter &&query);
|
||||
void query(
|
||||
const UserPhotosQuery &query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback);
|
||||
|
||||
base::Observable<UserPhotosSliceUpdate> sliceUpdated;
|
||||
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
||||
|
||||
rpl::producer<UserPhotosSliceUpdate> sliceUpdated() const {
|
||||
return _sliceUpdated.events();
|
||||
}
|
||||
|
||||
private:
|
||||
class List {
|
||||
@ -156,15 +158,15 @@ private:
|
||||
int count);
|
||||
void removeOne(PhotoId photoId);
|
||||
void removeAfter(PhotoId photoId);
|
||||
void query(
|
||||
const UserPhotosQuery &query,
|
||||
base::lambda_once<void(UserPhotosResult&&)> &&callback);
|
||||
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
||||
|
||||
struct SliceUpdate {
|
||||
const std::deque<PhotoId> *photoIds = nullptr;
|
||||
base::optional<int> count;
|
||||
};
|
||||
base::Observable<SliceUpdate> sliceUpdated;
|
||||
rpl::producer<SliceUpdate> sliceUpdated() const {
|
||||
return _sliceUpdated.events();
|
||||
}
|
||||
|
||||
private:
|
||||
void sendUpdate();
|
||||
@ -172,6 +174,8 @@ private:
|
||||
base::optional<int> _count;
|
||||
std::deque<PhotoId> _photoIds;
|
||||
|
||||
rpl::event_stream<SliceUpdate> _sliceUpdated;
|
||||
|
||||
};
|
||||
using SliceUpdate = List::SliceUpdate;
|
||||
|
||||
@ -179,6 +183,9 @@ private:
|
||||
|
||||
std::map<UserId, List> _lists;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
rpl::event_stream<UserPhotosSliceUpdate> _sliceUpdated;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Storage
|
||||
|
Loading…
Reference in New Issue
Block a user