From b135a09e0057ed2123d20f800d3a194df6e355d2 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 19 Dec 2022 13:01:32 +0300 Subject: [PATCH] Added initial support of fallback user photo to storage module. --- Telegram/SourceFiles/data/data_user.cpp | 9 ++++ .../SourceFiles/data/data_user_photos.cpp | 18 ++++++++ Telegram/SourceFiles/data/data_user_photos.h | 5 +++ .../SourceFiles/storage/storage_facade.cpp | 9 ++++ Telegram/SourceFiles/storage/storage_facade.h | 2 + .../storage/storage_user_photos.cpp | 45 +++++++++++++++++-- .../SourceFiles/storage/storage_user_photos.h | 22 ++++++++- 7 files changed, 106 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 1d2defe70..733babee4 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -8,10 +8,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "storage/localstorage.h" +#include "storage/storage_user_photos.h" #include "main/main_session.h" #include "data/data_session.h" #include "data/data_changes.h" #include "data/data_peer_bot_command.h" +#include "data/data_photo.h" #include "data/data_emoji_statuses.h" #include "data/data_user_names.h" #include "data/notify/data_notify_settings.h" @@ -380,6 +382,13 @@ void ApplyUserUpdate(not_null user, const MTPDuserFull &update) { } else { user->session().api().peerPhoto().unregisterNonPersonalPhoto(user); } + if (const auto photo = update.vfallback_photo()) { + const auto data = user->owner().processPhoto(*photo); + user->session().storage().add(Storage::UserPhotosSetBack( + peerToUser(user->id), + data->id + )); + } user->setSettings(update.vsettings()); user->owner().notifySettings().apply(user, update.vnotify_settings()); diff --git a/Telegram/SourceFiles/data/data_user_photos.cpp b/Telegram/SourceFiles/data/data_user_photos.cpp index ccd27c51f..6271f9b4c 100644 --- a/Telegram/SourceFiles/data/data_user_photos.cpp +++ b/Telegram/SourceFiles/data/data_user_photos.cpp @@ -237,3 +237,21 @@ rpl::producer UserPhotosReversedViewer( return std::move(slice); }); } + +std::optional SyncUserFallbackPhotoViewer(not_null user) { + auto syncLifetime = rpl::lifetime(); + auto result = std::optional(std::nullopt); + + constexpr auto kFallbackCount = 1; + user->session().storage().query(Storage::UserPhotosQuery( + Storage::UserPhotosKey(peerToUser(user->id), true), + kFallbackCount, + kFallbackCount + )) | rpl::start_with_next([&](Storage::UserPhotosResult &&slice) { + if (slice.photoIds.empty()) { + return; + } + result = slice.photoIds.front(); + }, syncLifetime); + return result; +} diff --git a/Telegram/SourceFiles/data/data_user_photos.h b/Telegram/SourceFiles/data/data_user_photos.h index 42af886dd..dcfac59f4 100644 --- a/Telegram/SourceFiles/data/data_user_photos.h +++ b/Telegram/SourceFiles/data/data_user_photos.h @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_user_photos.h" #include "base/weak_ptr.h" +class UserData; + namespace Main { class Session; } // namespace Main @@ -48,3 +50,6 @@ rpl::producer UserPhotosReversedViewer( UserPhotosSlice::Key key, int limitBefore, int limitAfter); + +[[nodiscard]] std::optional SyncUserFallbackPhotoViewer( + not_null user); diff --git a/Telegram/SourceFiles/storage/storage_facade.cpp b/Telegram/SourceFiles/storage/storage_facade.cpp index 5ddb39781..dfd44294f 100644 --- a/Telegram/SourceFiles/storage/storage_facade.cpp +++ b/Telegram/SourceFiles/storage/storage_facade.cpp @@ -29,6 +29,7 @@ public: rpl::producer sharedMediaAllRemoved() const; rpl::producer sharedMediaBottomInvalidated() const; + void add(UserPhotosSetBack &&query); void add(UserPhotosAddNew &&query); void add(UserPhotosAddSlice &&query); void remove(UserPhotosRemoveOne &&query); @@ -98,6 +99,10 @@ rpl::producer Facade::Impl::sharedMediaBottomInvali return _sharedMedia.bottomInvalidated(); } +void Facade::Impl::add(UserPhotosSetBack &&query) { + return _userPhotos.add(std::move(query)); +} + void Facade::Impl::add(UserPhotosAddNew &&query) { return _userPhotos.add(std::move(query)); } @@ -181,6 +186,10 @@ rpl::producer Facade::sharedMediaBottomInvalidated( return _impl->sharedMediaBottomInvalidated(); } +void Facade::add(UserPhotosSetBack &&query) { + return _impl->add(std::move(query)); +} + void Facade::add(UserPhotosAddNew &&query) { return _impl->add(std::move(query)); } diff --git a/Telegram/SourceFiles/storage/storage_facade.h b/Telegram/SourceFiles/storage/storage_facade.h index 68cfdde27..05e9604e0 100644 --- a/Telegram/SourceFiles/storage/storage_facade.h +++ b/Telegram/SourceFiles/storage/storage_facade.h @@ -30,6 +30,7 @@ struct SharedMediaKey; using SharedMediaResult = SparseIdsListResult; struct SharedMediaSliceUpdate; +struct UserPhotosSetBack; struct UserPhotosAddNew; struct UserPhotosAddSlice; struct UserPhotosRemoveOne; @@ -58,6 +59,7 @@ public: rpl::producer sharedMediaAllRemoved() const; rpl::producer sharedMediaBottomInvalidated() const; + void add(UserPhotosSetBack &&query); void add(UserPhotosAddNew &&query); void add(UserPhotosAddSlice &&query); void remove(UserPhotosRemoveOne &&query); diff --git a/Telegram/SourceFiles/storage/storage_user_photos.cpp b/Telegram/SourceFiles/storage/storage_user_photos.cpp index 3f58608eb..5ecb6bcee 100644 --- a/Telegram/SourceFiles/storage/storage_user_photos.cpp +++ b/Telegram/SourceFiles/storage/storage_user_photos.cpp @@ -9,12 +9,38 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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(); } } @@ -22,6 +48,7 @@ void UserPhotos::List::addNew(PhotoId photoId) { void UserPhotos::List::addSlice( std::vector &&photoIds, int count) { + detachBack(); for (auto photoId : photoIds) { if (!base::contains(_photoIds, photoId)) { _photoIds.push_front(photoId); @@ -32,6 +59,7 @@ void UserPhotos::List::addSlice( if ((_count && *_count < _photoIds.size()) || photoIds.empty()) { _count = _photoIds.size(); } + attachBack(); sendUpdate(); } @@ -72,7 +100,7 @@ void UserPhotos::List::sendUpdate() { rpl::producer UserPhotos::List::query( UserPhotosQuery &&query) const { return [this, query = std::move(query)](auto consumer) { - auto result = UserPhotosResult {}; + auto result = UserPhotosResult(); result.count = _count; auto position = ranges::find(_photoIds, query.key.photoId); @@ -91,6 +119,10 @@ rpl::producer UserPhotos::List::query( 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)); } @@ -107,7 +139,8 @@ rpl::producer UserPhotos::sliceUpdated() const { return _sliceUpdated.events(); } -std::map::iterator UserPhotos::enforceLists(UserId user) { +std::map::iterator UserPhotos::enforceLists( + UserId user) { auto result = _lists.find(user); if (result != _lists.end()) { return result; @@ -124,6 +157,11 @@ std::map::iterator UserPhotos::enforceLists(UserId use 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); @@ -150,7 +188,8 @@ void UserPhotos::remove(UserPhotosRemoveAfter &&query) { } } -rpl::producer UserPhotos::query(UserPhotosQuery &&query) const { +rpl::producer UserPhotos::query( + UserPhotosQuery &&query) const { auto userIt = _lists.find(query.key.userId); if (userIt != _lists.end()) { return userIt->second.query(std::move(query)); diff --git a/Telegram/SourceFiles/storage/storage_user_photos.h b/Telegram/SourceFiles/storage/storage_user_photos.h index df37989c9..323d818c2 100644 --- a/Telegram/SourceFiles/storage/storage_user_photos.h +++ b/Telegram/SourceFiles/storage/storage_user_photos.h @@ -12,6 +12,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Storage { +struct UserPhotosSetBack { + UserPhotosSetBack(UserId userId, PhotoId photoId) + : userId(userId), photoId(photoId) { + } + + UserId userId = 0; + PhotoId photoId = 0; + +}; + struct UserPhotosAddNew { UserPhotosAddNew(UserId userId, PhotoId photoId) : userId(userId), photoId(photoId) { @@ -71,10 +81,13 @@ struct UserPhotosKey { : userId(userId) , photoId(photoId) { } + UserPhotosKey(UserId userId, bool back) : userId(userId), back(back) { + } bool operator==(const UserPhotosKey &other) const { return (userId == other.userId) - && (photoId == other.photoId); + && (photoId == other.photoId) + && (back == other.back); } bool operator!=(const UserPhotosKey &other) const { return !(*this == other); @@ -82,6 +95,7 @@ struct UserPhotosKey { UserId userId = 0; PhotoId photoId = 0; + bool back = false; }; @@ -125,6 +139,7 @@ struct UserPhotosSliceUpdate { class UserPhotos { public: + void add(UserPhotosSetBack &&query); void add(UserPhotosAddNew &&query); void add(UserPhotosAddSlice &&query); void remove(UserPhotosRemoveOne &&query); @@ -136,6 +151,7 @@ public: private: class List { public: + void setBack(PhotoId photoId); void addNew(PhotoId photoId); void addSlice( std::vector &&photoIds, @@ -152,10 +168,14 @@ private: private: void sendUpdate(); + void detachBack(); + void attachBack(); std::optional _count; std::deque _photoIds; + PhotoId _backPhotoId = PhotoId(0); + rpl::event_stream _sliceUpdated; };