mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Display photos and videos together in MediaView.
This commit is contained in:
parent
e07a7a4b4c
commit
54d6673d0b
5 changed files with 90 additions and 48 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue