From 67d4eb688a55f6d57b437111fd07a622fc88e8c3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 23 Nov 2017 13:58:12 +0400 Subject: [PATCH] Reverse user and chat profile photos. --- Telegram/SourceFiles/base/algorithm.h | 5 ++ Telegram/SourceFiles/base/functors.h | 24 ++++++-- Telegram/SourceFiles/base/qthelp_url.cpp | 26 ++++----- .../data/data_search_controller.cpp | 6 +- .../SourceFiles/data/data_shared_media.cpp | 39 ++++++++++++- Telegram/SourceFiles/data/data_shared_media.h | 12 ++++ .../SourceFiles/data/data_user_photos.cpp | 55 ++++++++++--------- Telegram/SourceFiles/data/data_user_photos.h | 17 ++++-- Telegram/SourceFiles/mediaview.cpp | 8 ++- .../storage/storage_sparse_ids_list.cpp | 3 - 10 files changed, 134 insertions(+), 61 deletions(-) diff --git a/Telegram/SourceFiles/base/algorithm.h b/Telegram/SourceFiles/base/algorithm.h index 0c5b2f1c3..6ef4129c5 100644 --- a/Telegram/SourceFiles/base/algorithm.h +++ b/Telegram/SourceFiles/base/algorithm.h @@ -27,6 +27,11 @@ inline Type take(Type &value) { return std::exchange(value, Type {}); } +template +inline Type duplicate(const Type &value) { + return value; +} + template inline constexpr size_t array_size(const Type(&)[Size]) { return Size; diff --git a/Telegram/SourceFiles/base/functors.h b/Telegram/SourceFiles/base/functors.h index bdf905e1e..5465e9481 100644 --- a/Telegram/SourceFiles/base/functors.h +++ b/Telegram/SourceFiles/base/functors.h @@ -24,19 +24,31 @@ namespace base { namespace functors { struct abs_helper { - template ()), typename = decltype(-std::declval())> - constexpr Type operator()(Type value) const { + constexpr Type operator()(Type value) const { return (0 < value) ? value : (-value); } }; -constexpr auto abs = abs_helper {}; +constexpr auto abs = abs_helper{}; -template -inline auto add(Type a) { - return [a](auto b) { return a + b; }; +constexpr auto add = [](auto value) { + return [value](auto other) { + return value + other; + }; }; +struct negate_helper { + template < + typename Type, + typename = decltype(-std::declval())> + constexpr Type operator()(Type value) const { + return -value; + } +}; +constexpr auto negate = negate_helper{}; + } // namespace functors } // namespace base diff --git a/Telegram/SourceFiles/base/qthelp_url.cpp b/Telegram/SourceFiles/base/qthelp_url.cpp index d3c4d9b1c..c38648014 100644 --- a/Telegram/SourceFiles/base/qthelp_url.cpp +++ b/Telegram/SourceFiles/base/qthelp_url.cpp @@ -22,27 +22,27 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace qthelp { -QMap url_parse_params(const QString ¶ms, UrlParamNameTransform transform) { - QMap result; +QMap url_parse_params( + const QString ¶ms, + UrlParamNameTransform transform) { + auto result = QMap(); - auto transformParamName = [transform](const QString &name) { + const auto transformParamName = [transform](const QString &name) { if (transform == UrlParamNameTransform::ToLower) { return name.toLower(); } return name; }; - - auto paramsList = params.split('&'); - for_const (auto ¶m, paramsList) { + for (const auto ¶m : params.split('&')) { // Skip params without a name (starting with '='). if (auto separatorPosition = param.indexOf('=')) { - auto paramName = param; - auto paramValue = QString(); - if (separatorPosition > 0) { - paramName = param.mid(0, separatorPosition); - paramValue = url_decode(param.mid(separatorPosition + 1)); - } - paramName = transformParamName(paramName); + const auto paramName = transformParamName( + (separatorPosition > 0) + ? param.mid(0, separatorPosition) + : param); + const auto paramValue = (separatorPosition > 0) + ? url_decode(param.mid(separatorPosition + 1)) + : QString(); if (!result.contains(paramName)) { result.insert(paramName, paramValue); } diff --git a/Telegram/SourceFiles/data/data_search_controller.cpp b/Telegram/SourceFiles/data/data_search_controller.cpp index 61e7eabe1..27f8f44ea 100644 --- a/Telegram/SourceFiles/data/data_search_controller.cpp +++ b/Telegram/SourceFiles/data/data_search_controller.cpp @@ -154,13 +154,13 @@ SearchResult ParseSearchResult( result.messageIds.reserve(messages->size()); for (auto &message : *messages) { if (auto item = App::histories().addNewMessage(message, addType)) { + auto itemId = item->id; if ((type == Storage::SharedMediaType::kCount) || item->sharedMediaTypes().test(type)) { - auto itemId = item->id; result.messageIds.push_back(itemId); - accumulate_min(result.noSkipRange.from, itemId); - accumulate_max(result.noSkipRange.till, itemId); } + accumulate_min(result.noSkipRange.from, itemId); + accumulate_max(result.noSkipRange.till, itemId); } } if (messageId && result.messageIds.empty()) { diff --git a/Telegram/SourceFiles/data/data_shared_media.cpp b/Telegram/SourceFiles/data/data_shared_media.cpp index 36ef3d5d3..49f59d59d 100644 --- a/Telegram/SourceFiles/data/data_shared_media.cpp +++ b/Telegram/SourceFiles/data/data_shared_media.cpp @@ -207,11 +207,15 @@ base::optional SharedMediaWithLastSlice::fullCount() const { _isolatedLastPhoto | [](bool isolated) { return isolated ? 1 : 0; }); } -base::optional SharedMediaWithLastSlice::skippedBefore() const { +base::optional SharedMediaWithLastSlice::skippedBeforeImpl() const { return _slice.skippedBefore(); } -base::optional SharedMediaWithLastSlice::skippedAfter() const { +base::optional SharedMediaWithLastSlice::skippedBefore() const { + return _reversed ? skippedAfterImpl() : skippedBeforeImpl(); +} + +base::optional SharedMediaWithLastSlice::skippedAfterImpl() const { return isolatedInSlice() ? Add( _slice.skippedAfter(), @@ -219,7 +223,11 @@ base::optional SharedMediaWithLastSlice::skippedAfter() const { : (lastPhotoSkip() | [](int) { return 0; }); } -base::optional SharedMediaWithLastSlice::indexOf(Value value) const { +base::optional SharedMediaWithLastSlice::skippedAfter() const { + return _reversed ? skippedBeforeImpl() : skippedAfterImpl(); +} + +base::optional SharedMediaWithLastSlice::indexOfImpl(Value value) const { return base::get_if(&value) ? _slice.indexOf(*base::get_if(&value)) : (isolatedInSlice() @@ -228,6 +236,13 @@ base::optional SharedMediaWithLastSlice::indexOf(Value value) const { : Add(_slice.size() - 1, lastPhotoSkip()); } +base::optional SharedMediaWithLastSlice::indexOf(Value value) const { + auto result = indexOfImpl(value); + return _reversed + ? (result | func::negate | func::add(size() - 1)) + : result; +} + int SharedMediaWithLastSlice::size() const { return _slice.size() + ((!isolatedInSlice() && lastPhotoSkip() == 1) ? 1 : 0); @@ -236,6 +251,9 @@ int SharedMediaWithLastSlice::size() const { SharedMediaWithLastSlice::Value SharedMediaWithLastSlice::operator[](int index) const { Expects(index >= 0 && index < size()); + if (_reversed) { + index = size() - index - 1; + } return (index < _slice.size()) ? Value(_slice[index]) : Value(App::photo(_lastPhotoId)); @@ -252,6 +270,10 @@ base::optional SharedMediaWithLastSlice::distance( return base::none; } +void SharedMediaWithLastSlice::reverse() { + _reversed = !_reversed; +} + PhotoId SharedMediaWithLastSlice::LastPeerPhotoId(PeerId peerId) { if (auto peer = App::peerLoaded(peerId)) { return peer->photoId; @@ -332,3 +354,14 @@ rpl::producer SharedMediaWithLastViewer( }); }; } + +rpl::producer SharedMediaWithLastReversedViewer( + SharedMediaWithLastSlice::Key key, + int limitBefore, + int limitAfter) { + return SharedMediaWithLastViewer(key, limitBefore, limitAfter) + | rpl::map([](SharedMediaWithLastSlice &&slice) { + slice.reverse(); + return std::move(slice); + }); +} diff --git a/Telegram/SourceFiles/data/data_shared_media.h b/Telegram/SourceFiles/data/data_shared_media.h index 7a59ade30..74fe0f0e3 100644 --- a/Telegram/SourceFiles/data/data_shared_media.h +++ b/Telegram/SourceFiles/data/data_shared_media.h @@ -116,6 +116,8 @@ public: Value operator[](int index) const; base::optional distance(const Key &a, const Key &b) const; + void reverse(); + static SparseIdsMergedSlice::Key ViewerKey(const Key &key) { return { key.peerId, @@ -174,11 +176,16 @@ private: | [](bool isolated) { return isolated ? 1 : 0; }; } + base::optional skippedBeforeImpl() const; + base::optional skippedAfterImpl() const; + base::optional indexOfImpl(Value fullId) const; + Key _key; SparseIdsMergedSlice _slice; base::optional _ending; PhotoId _lastPhotoId = 0; base::optional _isolatedLastPhoto; + bool _reversed = false; }; @@ -186,3 +193,8 @@ rpl::producer SharedMediaWithLastViewer( SharedMediaWithLastSlice::Key key, int limitBefore, int limitAfter); + +rpl::producer SharedMediaWithLastReversedViewer( + SharedMediaWithLastSlice::Key key, + int limitBefore, + int limitAfter); diff --git a/Telegram/SourceFiles/data/data_user_photos.cpp b/Telegram/SourceFiles/data/data_user_photos.cpp index c4110a9a2..9e8478adf 100644 --- a/Telegram/SourceFiles/data/data_user_photos.cpp +++ b/Telegram/SourceFiles/data/data_user_photos.cpp @@ -66,22 +66,27 @@ UserPhotosSlice::UserPhotosSlice(Key key) {}, base::none, base::none, - 0) { + base::none) { } UserPhotosSlice::UserPhotosSlice( Key key, - const std::deque &ids, + std::deque &&ids, base::optional fullCount, base::optional skippedBefore, - int skippedAfter) + base::optional skippedAfter) : _key(key) -, _ids(ids) +, _ids(std::move(ids)) , _fullCount(fullCount) , _skippedBefore(skippedBefore) , _skippedAfter(skippedAfter) { } +void UserPhotosSlice::reverse() { + ranges::reverse(_ids); + std::swap(_skippedBefore, _skippedAfter); +} + base::optional UserPhotosSlice::indexOf(PhotoId photoId) const { auto it = ranges::find(_ids, photoId); if (it != _ids.end()) { @@ -109,30 +114,13 @@ base::optional UserPhotosSlice::distance(const Key &a, const Key &b) const return base::none; } -QString UserPhotosSlice::debug() const { - auto before = _skippedBefore - ? (*_skippedBefore - ? ('(' + QString::number(*_skippedBefore) + ").. ") - : QString()) - : QString(".. "); - auto after = _skippedAfter - ? (" ..(" + QString::number(_skippedAfter) + ')') - : QString(" .."); - auto middle = (size() > 2) - ? QString::number((*this)[0]) + " .. " + QString::number((*this)[size() - 1]) - : (size() > 1) - ? QString::number((*this)[0]) + ' ' + QString::number((*this)[1]) - : ((size() > 0) ? QString::number((*this)[0]) : QString()); - return before + middle + after; -} - UserPhotosSliceBuilder::UserPhotosSliceBuilder( Key key, int limitBefore, int limitAfter) - : _key(key) - , _limitBefore(limitBefore) - , _limitAfter(limitAfter) { +: _key(key) +, _limitBefore(limitBefore) +, _limitAfter(limitAfter) { } bool UserPhotosSliceBuilder::applyUpdate(const Storage::UserPhotosResult &update) { @@ -209,7 +197,12 @@ void UserPhotosSliceBuilder::sliceToLimits() { } UserPhotosSlice UserPhotosSliceBuilder::snapshot() const { - return UserPhotosSlice(_key, _ids, _fullCount, _skippedBefore, _skippedAfter); + return UserPhotosSlice( + _key, + base::duplicate(_ids), + _fullCount, + _skippedBefore, + _skippedAfter); } rpl::producer UserPhotosViewer( @@ -249,3 +242,15 @@ rpl::producer UserPhotosViewer( return lifetime; }; } + + +rpl::producer UserPhotosReversedViewer( + UserPhotosSlice::Key key, + int limitBefore, + int limitAfter) { + return UserPhotosViewer(key, limitBefore, limitAfter) + | rpl::map([](UserPhotosSlice &&slice) { + slice.reverse(); + return std::move(slice); + }); +} \ No newline at end of file diff --git a/Telegram/SourceFiles/data/data_user_photos.h b/Telegram/SourceFiles/data/data_user_photos.h index 8cc651119..a38a17743 100644 --- a/Telegram/SourceFiles/data/data_user_photos.h +++ b/Telegram/SourceFiles/data/data_user_photos.h @@ -30,29 +30,29 @@ public: UserPhotosSlice(Key key); UserPhotosSlice( Key key, - const std::deque &ids, + std::deque &&ids, base::optional fullCount, base::optional skippedBefore, - int skippedAfter); + base::optional skippedAfter); + + void reverse(); const Key &key() const { return _key; } base::optional fullCount() const { return _fullCount; } base::optional skippedBefore() const { return _skippedBefore; } - int skippedAfter() const { return _skippedAfter; } + base::optional skippedAfter() const { return _skippedAfter; } base::optional indexOf(PhotoId msgId) const; int size() const { return _ids.size(); } PhotoId operator[](int index) const; base::optional distance(const Key &a, const Key &b) const; - QString debug() const; - private: Key _key; std::deque _ids; base::optional _fullCount; base::optional _skippedBefore; - int _skippedAfter = 0; + base::optional _skippedAfter; friend class UserPhotosSliceBuilder; @@ -62,3 +62,8 @@ rpl::producer UserPhotosViewer( UserPhotosSlice::Key key, int limitBefore, int limitAfter); + +rpl::producer UserPhotosReversedViewer( + UserPhotosSlice::Key key, + int limitBefore, + int limitAfter); diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 68a4cca9c..53cb0aa30 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -1071,7 +1071,10 @@ bool MediaView::validSharedMedia() const { void MediaView::validateSharedMedia() { if (auto key = sharedMediaKey()) { _sharedMedia = std::make_unique(*key); - SharedMediaWithLastViewer( + auto viewer = (key->type == SharedMediaType::ChatPhoto) + ? SharedMediaWithLastReversedViewer + : SharedMediaWithLastViewer; + viewer( *key, kIdsLimit, kIdsLimit @@ -1134,7 +1137,7 @@ bool MediaView::validUserPhotos() const { void MediaView::validateUserPhotos() { if (auto key = userPhotosKey()) { _userPhotos = std::make_unique(*key); - UserPhotosViewer( + UserPhotosReversedViewer( *key, kIdsLimit, kIdsLimit @@ -2811,6 +2814,7 @@ void MediaView::updateImage() { } void MediaView::findCurrent() { + using namespace rpl::mappers; if (_sharedMediaData) { _index = _msgid ? _sharedMediaData->indexOf(_msgid) diff --git a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp index ec558c2b3..b40d791c4 100644 --- a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp +++ b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp @@ -76,9 +76,6 @@ int SparseIdsList::addRangeItemsAndCountNew( const Range &messages, MsgRange noSkipRange) { Expects(noSkipRange.from <= noSkipRange.till); - if (messages.begin() == messages.end()) { - return 0; - } auto uniteFrom = ranges::lower_bound( _slices,