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,
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<MTPMessage>*)nullptr;
} break;
}

View File

@ -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 {

View File

@ -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<MediaView*>(this)->_videoPaused = _gif->videoPaused();
const auto streamVideo = _doc
&& (_doc->isVideoFile() || _doc->isVideoMessage());
const auto pauseOnStart = (_autoplayVideoDocument != _doc);
if (streamVideo && pauseOnStart && !_gif->videoPaused()) {
const_cast<MediaView*>(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<MediaView*>(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<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) {
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> 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<DocumentData*> document, HistoryItem *cont
void MediaView::displayPhoto(not_null<PhotoData*> 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;

View File

@ -171,6 +171,7 @@ private:
using SharedMediaKey = SharedMediaWithLastSlice::Key;
base::optional<SharedMediaType> sharedMediaType() const;
base::optional<SharedMediaKey> sharedMediaKey() const;
base::optional<SharedMediaType> 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();

View File

@ -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<int>(SharedMediaType::kCount);
constexpr bool IsValidSharedMediaType(SharedMediaType type) {