From 54d6673d0bc8be2892439ce106e59abf5f63ebec Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 28 Dec 2017 13:11:50 +0300 Subject: [PATCH] Display photos and videos together in MediaView. --- .../data/data_search_controller.cpp | 20 +++-- .../history/history_media_types.cpp | 12 ++- Telegram/SourceFiles/mediaview.cpp | 81 +++++++++++++------ Telegram/SourceFiles/mediaview.h | 2 + .../storage/storage_shared_media.h | 23 +++--- 5 files changed, 90 insertions(+), 48 deletions(-) diff --git a/Telegram/SourceFiles/data/data_search_controller.cpp b/Telegram/SourceFiles/data/data_search_controller.cpp index 0bbe1f21a..828050a06 100644 --- a/Telegram/SourceFiles/data/data_search_controller.cpp +++ b/Telegram/SourceFiles/data/data_search_controller.cpp @@ -36,13 +36,15 @@ MTPmessages_Search PrepareSearchRequest( const QString &query, MsgId messageId, SparseIdsLoadDirection direction) { - auto filter = [&] { + const auto filter = [&] { using Type = Storage::SharedMediaType; switch (type) { case Type::Photo: return MTP_inputMessagesFilterPhotos(); case Type::Video: return MTP_inputMessagesFilterVideo(); + case Type::PhotoVideo: + return MTP_inputMessagesFilterPhotoVideo(); case Type::MusicFile: return MTP_inputMessagesFilterMusic(); case Type::File: @@ -63,10 +65,10 @@ MTPmessages_Search PrepareSearchRequest( return MTP_inputMessagesFilterEmpty(); }(); - auto minId = 0; - auto maxId = 0; - auto limit = messageId ? kSharedMediaLimit : 0; - auto offsetId = [&] { + const auto minId = 0; + const auto maxId = 0; + const auto limit = messageId ? kSharedMediaLimit : 0; + const auto offsetId = [&] { switch (direction) { case SparseIdsLoadDirection::Before: case SparseIdsLoadDirection::Around: return messageId; @@ -74,7 +76,7 @@ MTPmessages_Search PrepareSearchRequest( } Unexpected("Direction in PrepareSearchRequest"); }(); - auto addOffset = [&] { + const auto addOffset = [&] { switch (direction) { case SparseIdsLoadDirection::Before: return 0; case SparseIdsLoadDirection::Around: return -limit / 2; @@ -130,7 +132,8 @@ SearchResult ParseSearchResult( if (auto channel = peer->asChannel()) { channel->ptsReceived(d.vpts.v); } else { - LOG(("API Error: received messages.channelMessages when no channel was passed! (ParseSearchResult)")); + LOG(("API Error: received messages.channelMessages when " + "no channel was passed! (ParseSearchResult)")); } App::feedUsers(d.vusers); App::feedChats(d.vchats); @@ -139,7 +142,8 @@ SearchResult ParseSearchResult( } break; case mtpc_messages_messagesNotModified: { - LOG(("API Error: received messages.messagesNotModified! (ParseSearchResult)")); + LOG(("API Error: received messages.messagesNotModified! " + "(ParseSearchResult)")); return (const QVector*)nullptr; } break; } diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 1cb438856..4abb7b76f 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -839,10 +839,13 @@ bool HistoryPhoto::needsBubble() const { } Storage::SharedMediaTypesMask HistoryPhoto::sharedMediaTypes() const { + using Type = Storage::SharedMediaType; if (_parent->toHistoryMessage()) { - return Storage::SharedMediaType::Photo; + return Storage::SharedMediaTypesMask{} + .added(Type::Photo) + .added(Type::PhotoVideo); } - return Storage::SharedMediaType::ChatPhoto; + return Type::ChatPhoto; } ImagePtr HistoryPhoto::replyPreview() { @@ -1305,7 +1308,10 @@ bool HistoryVideo::needsBubble() const { } Storage::SharedMediaTypesMask HistoryVideo::sharedMediaTypes() const { - return Storage::SharedMediaType::Video; + using Type = Storage::SharedMediaType; + return Storage::SharedMediaTypesMask{} + .added(Type::Video) + .added(Type::PhotoVideo); } void HistoryVideo::updateStatusText() const { diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 95e65b1b7..e37821055 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -211,12 +211,22 @@ bool MediaView::fileBubbleShown() const { bool MediaView::gifShown() const { if (_gif && _gif->ready()) { if (!_gif->started()) { - if (_doc && (_doc->isVideoFile() || _doc->isVideoMessage()) && _autoplayVideoDocument != _doc && !_gif->videoPaused()) { - _gif->pauseResumeVideo(); - const_cast(this)->_videoPaused = _gif->videoPaused(); + const auto streamVideo = _doc + && (_doc->isVideoFile() || _doc->isVideoMessage()); + const auto pauseOnStart = (_autoplayVideoDocument != _doc); + if (streamVideo && pauseOnStart && !_gif->videoPaused()) { + const_cast(this)->toggleVideoPaused(); } - auto rounding = (_doc && _doc->isVideoMessage()) ? ImageRoundRadius::Ellipse : ImageRoundRadius::None; - _gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, RectPart::AllCorners); + const auto rounding = (_doc && _doc->isVideoMessage()) + ? ImageRoundRadius::Ellipse + : ImageRoundRadius::None; + _gif->start( + _gif->width() / cIntRetinaFactor(), + _gif->height() / cIntRetinaFactor(), + _gif->width() / cIntRetinaFactor(), + _gif->height() / cIntRetinaFactor(), + rounding, + RectPart::AllCorners); const_cast(this)->_current = QPixmap(); updateMixerVideoVolume(); Global::RefVideoVolumeChanged().notify(); @@ -413,13 +423,27 @@ void MediaView::updateActions() { } _actions.push_back({ lang(lng_mediaview_save_as), SLOT(onSaveAs()) }); - if (auto overviewType = - sharedMediaType() - | SharedMediaOverviewType) { + if (const auto overviewType = computeOverviewType()) { _actions.push_back({ lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all), SLOT(onOverview()) }); } } +auto MediaView::computeOverviewType() const +-> base::optional { + if (const auto mediaType = sharedMediaType()) { + if (const auto overviewType = SharedMediaOverviewType(*mediaType)) { + return overviewType; + } else if (mediaType == SharedMediaType::PhotoVideo) { + if (_photo) { + return SharedMediaOverviewType(SharedMediaType::Photo); + } else if (_doc) { + return SharedMediaOverviewType(SharedMediaType::Video); + } + } + } + return base::none; +} + void MediaView::step_state(TimeMs ms, bool timer) { bool result = false; for (Showing::iterator i = _animations.begin(); i != _animations.end();) { @@ -512,21 +536,26 @@ void MediaView::step_radial(TimeMs ms, bool timer) { _radial.stop(); return; } - auto wasAnimating = _radial.animating(); + const auto wasAnimating = _radial.animating(); _radial.update(radialProgress(), !radialLoading(), ms + radialTimeShift()); if (timer && (wasAnimating || _radial.animating())) { update(radialRect()); } - if (_doc && _doc->loaded() && _doc->size < App::kImageSizeLimit && (!_radial.animating() || _doc->isAnimation() || _doc->isVideoFile())) { + const auto ready = _doc && _doc->loaded(); + const auto streamVideo = _doc->isAnimation() || _doc->isVideoFile(); + const auto tryOpenImage = (_doc->size < App::kImageSizeLimit); + if (ready && ((tryOpenImage && !_radial.animating()) || streamVideo)) { if (_doc->isVideoFile() || _doc->isVideoMessage()) { _autoplayVideoDocument = _doc; } - if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideoFile())) { + if (!_doc->data().isEmpty() && streamVideo) { displayDocument(_doc, App::histItemById(_msgid)); } else { auto &location = _doc->location(true); if (location.accessEnable()) { - if (_doc->isAnimation() || _doc->isVideoFile() || _doc->isTheme() || QImageReader(location.name()).canRead()) { + if (streamVideo + || _doc->isTheme() + || QImageReader(location.name()).canRead()) { displayDocument(_doc, App::histItemById(_msgid)); } location.accessDisable(); @@ -963,9 +992,7 @@ void MediaView::onDelete() { void MediaView::onOverview() { if (_menu) _menu->hideMenu(true); update(); - if (auto overviewType = - sharedMediaType() - | SharedMediaOverviewType) { + if (const auto overviewType = computeOverviewType()) { close(); SharedMediaShowOverview(*overviewType, _history); } @@ -991,14 +1018,14 @@ base::optional MediaView::sharedMediaType() const { if (auto item = App::histItemById(_msgid)) { if (_photo) { if (item->toHistoryMessage()) { - return Type::Photo; + return Type::PhotoVideo; } return Type::ChatPhoto; } else if (_doc) { if (_doc->isGifv()) { return Type::GIF; } else if (_doc->isVideoFile()) { - return Type::Video; + return Type::PhotoVideo; } return Type::File; } @@ -1254,7 +1281,7 @@ void MediaView::showDocument(not_null document, HistoryItem *cont void MediaView::displayPhoto(not_null photo, HistoryItem *item) { stopGif(); destroyThemePreview(); - _doc = nullptr; + _doc = _autoplayVideoDocument = nullptr; _fullScreenVideo = false; _photo = photo; _radial.stop(); @@ -1646,11 +1673,7 @@ void MediaView::onVideoPauseResume() { } else if (_gif->state() == Media::Clip::State::Finished) { restartVideoAtSeekPosition(0); } else { - _gif->pauseResumeVideo(); - _videoPaused = _gif->videoPaused(); - if (_videoIsSilent) { - updateSilentVideoPlaybackState(); - } + toggleVideoPaused(); } } else { stopGif(); @@ -1659,6 +1682,14 @@ void MediaView::onVideoPauseResume() { } } +void MediaView::toggleVideoPaused() { + _gif->pauseResumeVideo(); + _videoPaused = _gif->videoPaused(); + if (_videoIsSilent) { + updateSilentVideoPlaybackState(); + } +} + void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) { _autoplayVideoDocument = _doc; @@ -2857,9 +2888,7 @@ void MediaView::updateHeader() { _headerText = lang(lng_mediaview_single_photo); } } - _headerHasLink = ( - sharedMediaType() - | SharedMediaOverviewType) != base::none; + _headerHasLink = computeOverviewType() != base::none; auto hwidth = st::mediaviewThickFont->width(_headerText); if (hwidth > width() / 3) { hwidth = width() / 3; diff --git a/Telegram/SourceFiles/mediaview.h b/Telegram/SourceFiles/mediaview.h index fc78146f2..6ee48aaf9 100644 --- a/Telegram/SourceFiles/mediaview.h +++ b/Telegram/SourceFiles/mediaview.h @@ -171,6 +171,7 @@ private: using SharedMediaKey = SharedMediaWithLastSlice::Key; base::optional sharedMediaType() const; base::optional sharedMediaKey() const; + base::optional computeOverviewType() const; bool validSharedMedia() const; void validateSharedMedia(); void handleSharedMediaUpdate(SharedMediaWithLastSlice &&update); @@ -201,6 +202,7 @@ private: void updateVideoPlaybackState(const Media::Player::TrackState &state); void updateSilentVideoPlaybackState(); void restartVideoAtSeekPosition(TimeMs positionMs); + void toggleVideoPaused(); void createClipController(); void setClipControllerGeometry(); diff --git a/Telegram/SourceFiles/storage/storage_shared_media.h b/Telegram/SourceFiles/storage/storage_shared_media.h index c3802126d..b77c47da5 100644 --- a/Telegram/SourceFiles/storage/storage_shared_media.h +++ b/Telegram/SourceFiles/storage/storage_shared_media.h @@ -28,18 +28,19 @@ namespace Storage { // Allow forward declarations. enum class SharedMediaType : char { - Photo = 0, - Video = 1, - MusicFile = 2, - File = 3, - VoiceFile = 4, - Link = 5, - ChatPhoto = 6, - RoundVoiceFile = 7, - GIF = 8, - RoundFile = 9, + Photo, + Video, + PhotoVideo, + MusicFile, + File, + VoiceFile, + Link, + ChatPhoto, + RoundVoiceFile, + GIF, + RoundFile, - kCount = 10, + kCount, }; constexpr auto kSharedMediaTypeCount = static_cast(SharedMediaType::kCount); constexpr bool IsValidSharedMediaType(SharedMediaType type) {