Display photos and videos together in MediaView.

This commit is contained in:
John Preston 2017-12-28 13:11:50 +03:00
parent e07a7a4b4c
commit 54d6673d0b
5 changed files with 90 additions and 48 deletions

View file

@ -36,13 +36,15 @@ MTPmessages_Search PrepareSearchRequest(
const QString &query, const QString &query,
MsgId messageId, MsgId messageId,
SparseIdsLoadDirection direction) { SparseIdsLoadDirection direction) {
auto filter = [&] { const auto filter = [&] {
using Type = Storage::SharedMediaType; using Type = Storage::SharedMediaType;
switch (type) { switch (type) {
case Type::Photo: case Type::Photo:
return MTP_inputMessagesFilterPhotos(); return MTP_inputMessagesFilterPhotos();
case Type::Video: case Type::Video:
return MTP_inputMessagesFilterVideo(); return MTP_inputMessagesFilterVideo();
case Type::PhotoVideo:
return MTP_inputMessagesFilterPhotoVideo();
case Type::MusicFile: case Type::MusicFile:
return MTP_inputMessagesFilterMusic(); return MTP_inputMessagesFilterMusic();
case Type::File: case Type::File:
@ -63,10 +65,10 @@ MTPmessages_Search PrepareSearchRequest(
return MTP_inputMessagesFilterEmpty(); return MTP_inputMessagesFilterEmpty();
}(); }();
auto minId = 0; const auto minId = 0;
auto maxId = 0; const auto maxId = 0;
auto limit = messageId ? kSharedMediaLimit : 0; const auto limit = messageId ? kSharedMediaLimit : 0;
auto offsetId = [&] { const auto offsetId = [&] {
switch (direction) { switch (direction) {
case SparseIdsLoadDirection::Before: case SparseIdsLoadDirection::Before:
case SparseIdsLoadDirection::Around: return messageId; case SparseIdsLoadDirection::Around: return messageId;
@ -74,7 +76,7 @@ MTPmessages_Search PrepareSearchRequest(
} }
Unexpected("Direction in PrepareSearchRequest"); Unexpected("Direction in PrepareSearchRequest");
}(); }();
auto addOffset = [&] { const auto addOffset = [&] {
switch (direction) { switch (direction) {
case SparseIdsLoadDirection::Before: return 0; case SparseIdsLoadDirection::Before: return 0;
case SparseIdsLoadDirection::Around: return -limit / 2; case SparseIdsLoadDirection::Around: return -limit / 2;
@ -130,7 +132,8 @@ SearchResult ParseSearchResult(
if (auto channel = peer->asChannel()) { if (auto channel = peer->asChannel()) {
channel->ptsReceived(d.vpts.v); channel->ptsReceived(d.vpts.v);
} else { } 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::feedUsers(d.vusers);
App::feedChats(d.vchats); App::feedChats(d.vchats);
@ -139,7 +142,8 @@ SearchResult ParseSearchResult(
} break; } break;
case mtpc_messages_messagesNotModified: { case mtpc_messages_messagesNotModified: {
LOG(("API Error: received messages.messagesNotModified! (ParseSearchResult)")); LOG(("API Error: received messages.messagesNotModified! "
"(ParseSearchResult)"));
return (const QVector<MTPMessage>*)nullptr; return (const QVector<MTPMessage>*)nullptr;
} break; } break;
} }

View file

@ -839,10 +839,13 @@ bool HistoryPhoto::needsBubble() const {
} }
Storage::SharedMediaTypesMask HistoryPhoto::sharedMediaTypes() const { Storage::SharedMediaTypesMask HistoryPhoto::sharedMediaTypes() const {
using Type = Storage::SharedMediaType;
if (_parent->toHistoryMessage()) { 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() { ImagePtr HistoryPhoto::replyPreview() {
@ -1305,7 +1308,10 @@ bool HistoryVideo::needsBubble() const {
} }
Storage::SharedMediaTypesMask HistoryVideo::sharedMediaTypes() 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 { void HistoryVideo::updateStatusText() const {

View file

@ -211,12 +211,22 @@ bool MediaView::fileBubbleShown() const {
bool MediaView::gifShown() const { bool MediaView::gifShown() const {
if (_gif && _gif->ready()) { if (_gif && _gif->ready()) {
if (!_gif->started()) { if (!_gif->started()) {
if (_doc && (_doc->isVideoFile() || _doc->isVideoMessage()) && _autoplayVideoDocument != _doc && !_gif->videoPaused()) { const auto streamVideo = _doc
_gif->pauseResumeVideo(); && (_doc->isVideoFile() || _doc->isVideoMessage());
const_cast<MediaView*>(this)->_videoPaused = _gif->videoPaused(); const auto pauseOnStart = (_autoplayVideoDocument != _doc);
if (streamVideo && pauseOnStart && !_gif->videoPaused()) {
const_cast<MediaView*>(this)->toggleVideoPaused();
} }
auto rounding = (_doc && _doc->isVideoMessage()) ? ImageRoundRadius::Ellipse : ImageRoundRadius::None; const auto rounding = (_doc && _doc->isVideoMessage())
_gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, RectPart::AllCorners); ? ImageRoundRadius::Ellipse
: ImageRoundRadius::None;
_gif->start(
_gif->width() / cIntRetinaFactor(),
_gif->height() / cIntRetinaFactor(),
_gif->width() / cIntRetinaFactor(),
_gif->height() / cIntRetinaFactor(),
rounding,
RectPart::AllCorners);
const_cast<MediaView*>(this)->_current = QPixmap(); const_cast<MediaView*>(this)->_current = QPixmap();
updateMixerVideoVolume(); updateMixerVideoVolume();
Global::RefVideoVolumeChanged().notify(); Global::RefVideoVolumeChanged().notify();
@ -413,13 +423,27 @@ void MediaView::updateActions() {
} }
_actions.push_back({ lang(lng_mediaview_save_as), SLOT(onSaveAs()) }); _actions.push_back({ lang(lng_mediaview_save_as), SLOT(onSaveAs()) });
if (auto overviewType = if (const auto overviewType = computeOverviewType()) {
sharedMediaType()
| SharedMediaOverviewType) {
_actions.push_back({ lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all), SLOT(onOverview()) }); _actions.push_back({ lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all), SLOT(onOverview()) });
} }
} }
auto MediaView::computeOverviewType() const
-> base::optional<SharedMediaType> {
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) { void MediaView::step_state(TimeMs ms, bool timer) {
bool result = false; bool result = false;
for (Showing::iterator i = _animations.begin(); i != _animations.end();) { for (Showing::iterator i = _animations.begin(); i != _animations.end();) {
@ -512,21 +536,26 @@ void MediaView::step_radial(TimeMs ms, bool timer) {
_radial.stop(); _radial.stop();
return; return;
} }
auto wasAnimating = _radial.animating(); const auto wasAnimating = _radial.animating();
_radial.update(radialProgress(), !radialLoading(), ms + radialTimeShift()); _radial.update(radialProgress(), !radialLoading(), ms + radialTimeShift());
if (timer && (wasAnimating || _radial.animating())) { if (timer && (wasAnimating || _radial.animating())) {
update(radialRect()); 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()) { if (_doc->isVideoFile() || _doc->isVideoMessage()) {
_autoplayVideoDocument = _doc; _autoplayVideoDocument = _doc;
} }
if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideoFile())) { if (!_doc->data().isEmpty() && streamVideo) {
displayDocument(_doc, App::histItemById(_msgid)); displayDocument(_doc, App::histItemById(_msgid));
} else { } else {
auto &location = _doc->location(true); auto &location = _doc->location(true);
if (location.accessEnable()) { 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)); displayDocument(_doc, App::histItemById(_msgid));
} }
location.accessDisable(); location.accessDisable();
@ -963,9 +992,7 @@ void MediaView::onDelete() {
void MediaView::onOverview() { void MediaView::onOverview() {
if (_menu) _menu->hideMenu(true); if (_menu) _menu->hideMenu(true);
update(); update();
if (auto overviewType = if (const auto overviewType = computeOverviewType()) {
sharedMediaType()
| SharedMediaOverviewType) {
close(); close();
SharedMediaShowOverview(*overviewType, _history); SharedMediaShowOverview(*overviewType, _history);
} }
@ -991,14 +1018,14 @@ base::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const {
if (auto item = App::histItemById(_msgid)) { if (auto item = App::histItemById(_msgid)) {
if (_photo) { if (_photo) {
if (item->toHistoryMessage()) { if (item->toHistoryMessage()) {
return Type::Photo; return Type::PhotoVideo;
} }
return Type::ChatPhoto; return Type::ChatPhoto;
} else if (_doc) { } else if (_doc) {
if (_doc->isGifv()) { if (_doc->isGifv()) {
return Type::GIF; return Type::GIF;
} else if (_doc->isVideoFile()) { } else if (_doc->isVideoFile()) {
return Type::Video; return Type::PhotoVideo;
} }
return Type::File; return Type::File;
} }
@ -1254,7 +1281,7 @@ void MediaView::showDocument(not_null<DocumentData*> document, HistoryItem *cont
void MediaView::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item) { void MediaView::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item) {
stopGif(); stopGif();
destroyThemePreview(); destroyThemePreview();
_doc = nullptr; _doc = _autoplayVideoDocument = nullptr;
_fullScreenVideo = false; _fullScreenVideo = false;
_photo = photo; _photo = photo;
_radial.stop(); _radial.stop();
@ -1646,11 +1673,7 @@ void MediaView::onVideoPauseResume() {
} else if (_gif->state() == Media::Clip::State::Finished) { } else if (_gif->state() == Media::Clip::State::Finished) {
restartVideoAtSeekPosition(0); restartVideoAtSeekPosition(0);
} else { } else {
_gif->pauseResumeVideo(); toggleVideoPaused();
_videoPaused = _gif->videoPaused();
if (_videoIsSilent) {
updateSilentVideoPlaybackState();
}
} }
} else { } else {
stopGif(); stopGif();
@ -1659,6 +1682,14 @@ void MediaView::onVideoPauseResume() {
} }
} }
void MediaView::toggleVideoPaused() {
_gif->pauseResumeVideo();
_videoPaused = _gif->videoPaused();
if (_videoIsSilent) {
updateSilentVideoPlaybackState();
}
}
void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) { void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) {
_autoplayVideoDocument = _doc; _autoplayVideoDocument = _doc;
@ -2857,9 +2888,7 @@ void MediaView::updateHeader() {
_headerText = lang(lng_mediaview_single_photo); _headerText = lang(lng_mediaview_single_photo);
} }
} }
_headerHasLink = ( _headerHasLink = computeOverviewType() != base::none;
sharedMediaType()
| SharedMediaOverviewType) != base::none;
auto hwidth = st::mediaviewThickFont->width(_headerText); auto hwidth = st::mediaviewThickFont->width(_headerText);
if (hwidth > width() / 3) { if (hwidth > width() / 3) {
hwidth = width() / 3; hwidth = width() / 3;

View file

@ -171,6 +171,7 @@ private:
using SharedMediaKey = SharedMediaWithLastSlice::Key; using SharedMediaKey = SharedMediaWithLastSlice::Key;
base::optional<SharedMediaType> sharedMediaType() const; base::optional<SharedMediaType> sharedMediaType() const;
base::optional<SharedMediaKey> sharedMediaKey() const; base::optional<SharedMediaKey> sharedMediaKey() const;
base::optional<SharedMediaType> computeOverviewType() const;
bool validSharedMedia() const; bool validSharedMedia() const;
void validateSharedMedia(); void validateSharedMedia();
void handleSharedMediaUpdate(SharedMediaWithLastSlice &&update); void handleSharedMediaUpdate(SharedMediaWithLastSlice &&update);
@ -201,6 +202,7 @@ private:
void updateVideoPlaybackState(const Media::Player::TrackState &state); void updateVideoPlaybackState(const Media::Player::TrackState &state);
void updateSilentVideoPlaybackState(); void updateSilentVideoPlaybackState();
void restartVideoAtSeekPosition(TimeMs positionMs); void restartVideoAtSeekPosition(TimeMs positionMs);
void toggleVideoPaused();
void createClipController(); void createClipController();
void setClipControllerGeometry(); void setClipControllerGeometry();

View file

@ -28,18 +28,19 @@ namespace Storage {
// Allow forward declarations. // Allow forward declarations.
enum class SharedMediaType : char { enum class SharedMediaType : char {
Photo = 0, Photo,
Video = 1, Video,
MusicFile = 2, PhotoVideo,
File = 3, MusicFile,
VoiceFile = 4, File,
Link = 5, VoiceFile,
ChatPhoto = 6, Link,
RoundVoiceFile = 7, ChatPhoto,
GIF = 8, RoundVoiceFile,
RoundFile = 9, GIF,
RoundFile,
kCount = 10, kCount,
}; };
constexpr auto kSharedMediaTypeCount = static_cast<int>(SharedMediaType::kCount); constexpr auto kSharedMediaTypeCount = static_cast<int>(SharedMediaType::kCount);
constexpr bool IsValidSharedMediaType(SharedMediaType type) { constexpr bool IsValidSharedMediaType(SharedMediaType type) {