Display round video messages using HistoryGif.

Use autodownload and autoplay options from GIFs.
Also improve EditCaptionBox code.
This commit is contained in:
John Preston 2017-04-02 13:25:54 +03:00
parent 8d28d0691f
commit 8eb7f1f1aa
16 changed files with 220 additions and 192 deletions

View File

@ -484,11 +484,6 @@ autoDownloadTopDelta: 10px;
autoDownloadTitlePosition: point(23px, 18px);
autoDownloadTitleFont: font(15px semibold);
editTextArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 276px;
}
confirmCaptionArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 78px;

View File

@ -269,10 +269,9 @@ void AutoDownloadBox::onSave() {
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
cSetAutoDownloadAudio(autoDownloadAudio);
if (enabledPrivate || enabledGroups) {
const DocumentsData &data(App::documentsData());
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
if (i.value()->voice()) {
i.value()->automaticLoadSettingsChanged();
for (auto document : App::documentsData()) {
if (document->voice()) {
document->automaticLoadSettingsChanged();
}
}
}
@ -284,10 +283,9 @@ void AutoDownloadBox::onSave() {
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
cSetAutoDownloadGif(autoDownloadGif);
if (enabledPrivate || enabledGroups) {
const DocumentsData &data(App::documentsData());
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
if (i.value()->isAnimation()) {
i.value()->automaticLoadSettingsChanged();
for (auto document : App::documentsData()) {
if (document->isAnimation()) {
document->automaticLoadSettingsChanged();
}
}
}

View File

@ -450,46 +450,46 @@ void SendFilesBox::closeHook() {
}
}
EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg)
: _msgId(msg->fullId()) {
EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) : _msgId(msgId) {
Expects(media->canEditCaption());
QSize dimensions;
ImagePtr image;
QString caption;
DocumentData *doc = nullptr;
if (auto media = msg->getMedia()) {
auto t = media->type();
switch (t) {
case MediaTypeGif: {
_animated = true;
doc = static_cast<HistoryGif*>(media)->getDocument();
dimensions = doc->dimensions;
image = doc->thumb;
} break;
case MediaTypePhoto: {
_photo = true;
PhotoData *photo = static_cast<HistoryPhoto*>(media)->photo();
dimensions = QSize(photo->full->width(), photo->full->height());
image = photo->full;
} break;
switch (media->type()) {
case MediaTypeGif: {
_animated = true;
doc = static_cast<HistoryGif*>(media)->getDocument();
dimensions = doc->dimensions;
image = doc->thumb;
} break;
case MediaTypeVideo: {
_animated = true;
doc = static_cast<HistoryVideo*>(media)->getDocument();
dimensions = doc->dimensions;
image = doc->thumb;
} break;
case MediaTypePhoto: {
_photo = true;
auto photo = static_cast<HistoryPhoto*>(media)->photo();
dimensions = QSize(photo->full->width(), photo->full->height());
image = photo->full;
} break;
case MediaTypeFile:
case MediaTypeMusicFile:
case MediaTypeVoiceFile: {
_doc = true;
doc = static_cast<HistoryDocument*>(media)->getDocument();
image = doc->thumb;
} break;
}
caption = media->getCaption().text;
case MediaTypeVideo: {
_animated = true;
doc = static_cast<HistoryVideo*>(media)->getDocument();
dimensions = doc->dimensions;
image = doc->thumb;
} break;
case MediaTypeFile:
case MediaTypeMusicFile:
case MediaTypeVoiceFile: {
_doc = true;
doc = static_cast<HistoryDocument*>(media)->getDocument();
image = doc->thumb;
} break;
}
caption = media->getCaption().text;
if ((!_animated && (dimensions.isEmpty() || doc)) || image->isNull()) {
_animated = false;
if (image->isNull()) {
@ -563,17 +563,11 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg)
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
}
if (_animated || _photo || _doc) {
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
} else {
auto original = msg->originalText();
auto text = textApplyEntities(original.text, original.entities);
_field.create(this, st::editTextArea, lang(lng_photo_caption), text);
// _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid
_field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmit::CtrlEnter : Ui::CtrlEnterSubmit::Enter);
}
t_assert(_animated || _photo || _doc);
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
}
void EditCaptionBox::prepareGifPreview(DocumentData *document) {
@ -613,20 +607,6 @@ void EditCaptionBox::clipCallback(Media::Clip::Notification notification) {
}
}
bool EditCaptionBox::canEdit(HistoryItem *message) {
if (auto media = message->getMedia()) {
switch (media->type()) {
case MediaTypeGif:
case MediaTypePhoto:
case MediaTypeVideo:
case MediaTypeFile:
case MediaTypeMusicFile:
case MediaTypeVoiceFile: return true;
}
}
return false;
}
void EditCaptionBox::prepare() {
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });

View File

@ -115,8 +115,7 @@ class EditCaptionBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
EditCaptionBox(QWidget*, HistoryItem *msg);
static bool canEdit(HistoryItem *message);
EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId);
public slots:
void onCaptionResized();

View File

@ -756,20 +756,19 @@ void HistoryItem::setId(MsgId newId) {
bool HistoryItem::canEdit(const QDateTime &cur) const {
auto messageToMyself = (_history->peer->id == AuthSession::CurrentUserPeerId());
auto messageTooOld = messageToMyself ? false : (date.secsTo(cur) >= Global::EditTimeLimit());
if (id < 0 || messageTooOld) return false;
if (id < 0 || messageTooOld) {
return false;
}
if (auto msg = toHistoryMessage()) {
if (msg->Has<HistoryMessageVia>() || msg->Has<HistoryMessageForwarded>()) return false;
if (msg->Has<HistoryMessageVia>() || msg->Has<HistoryMessageForwarded>()) {
return false;
}
if (auto media = msg->getMedia()) {
auto type = media->type();
if (type != MediaTypePhoto &&
type != MediaTypeVideo &&
type != MediaTypeFile &&
type != MediaTypeGif &&
type != MediaTypeMusicFile &&
type != MediaTypeVoiceFile &&
type != MediaTypeWebPage) {
if (media->canEditCaption()) {
return true;
} else if (media->type() != MediaTypeWebPage) {
return false;
}
}
@ -785,8 +784,12 @@ bool HistoryItem::canEdit(const QDateTime &cur) const {
bool HistoryItem::canDeleteForEveryone(const QDateTime &cur) const {
auto messageToMyself = (_history->peer->id == AuthSession::CurrentUserPeerId());
auto messageTooOld = messageToMyself ? false : (date.secsTo(cur) >= Global::EditTimeLimit());
if (id < 0 || messageToMyself || messageTooOld) return false;
if (history()->peer->isChannel()) return false;
if (id < 0 || messageToMyself || messageTooOld) {
return false;
}
if (history()->peer->isChannel()) {
return false;
}
if (auto msg = toHistoryMessage()) {
return !isPost() && out();
@ -803,21 +806,31 @@ bool HistoryItem::unread() const {
if (out()) {
// Outgoing messages in converted chats are always read.
if (history()->peer->migrateTo()) return false;
if (history()->peer->migrateTo()) {
return false;
}
if (id > 0) {
if (id < history()->outboxReadBefore) return false;
if (id < history()->outboxReadBefore) {
return false;
}
if (auto user = history()->peer->asUser()) {
if (user->botInfo) return false;
if (user->botInfo) {
return false;
}
} else if (auto channel = history()->peer->asChannel()) {
if (!channel->isMegagroup()) return false;
if (!channel->isMegagroup()) {
return false;
}
}
}
return true;
}
if (id > 0) {
if (id < history()->inboxReadBefore) return false;
if (id < history()->inboxReadBefore) {
return false;
}
return true;
}
return (_flags & MTPDmessage_ClientFlag::f_clientside_unread);
@ -867,11 +880,15 @@ void HistoryItem::setUnreadBarFreezed() {
void HistoryItem::clipCallback(Media::Clip::Notification notification) {
using namespace Media::Clip;
HistoryMedia *media = getMedia();
if (!media) return;
auto media = getMedia();
if (!media) {
return;
}
Reader *reader = media ? media->getClipReader() : 0;
if (!reader) return;
auto reader = media ? media->getClipReader() : nullptr;
if (!reader) {
return;
}
switch (notification) {
case NotificationReinit: {
@ -903,7 +920,9 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
void HistoryItem::recountDisplayDate() {
bool displayingDate = ([this]() {
if (isEmpty()) return false;
if (isEmpty()) {
return false;
}
if (auto previous = previousItem()) {
return previous->isEmpty() || (previous->date.date() != date.date());
@ -930,7 +949,9 @@ QString HistoryItem::notificationText() const {
};
auto result = getText();
if (result.size() > 0xFF) result = result.mid(0, 0xFF) + qsl("...");
if (result.size() > 0xFF) {
result = result.mid(0, 0xFF) + qsl("...");
}
return result;
}

View File

@ -171,6 +171,10 @@ public:
return false;
}
virtual bool canEditCaption() const {
return false;
}
// Sometimes click on media in message is overloaded by the messsage:
// (for example it can open a link or a game instead of opening media)
// But the overloading click handler should be used only when media

View File

@ -175,6 +175,9 @@ public:
bool skipBubbleTail() const override {
return isBubbleBottom() && _caption.isEmpty();
}
bool canEditCaption() const override {
return true;
}
bool isReadyForOpen() const override {
return _data->loaded();
}
@ -191,7 +194,7 @@ protected:
}
private:
PhotoData *_data;
gsl::not_null<PhotoData*> _data;
int16 _pixw = 1;
int16 _pixh = 1;
Text _caption;
@ -266,6 +269,9 @@ public:
bool skipBubbleTail() const override {
return isBubbleBottom() && _caption.isEmpty();
}
bool canEditCaption() const override {
return true;
}
protected:
float64 dataProgress() const override {
@ -279,7 +285,7 @@ protected:
}
private:
DocumentData *_data;
gsl::not_null<DocumentData*> _data;
int32 _thumbw;
Text _caption;
@ -417,6 +423,9 @@ public:
bool hideForwardedFrom() const override {
return _data->song();
}
bool canEditCaption() const override {
return true;
}
void step_voiceProgress(float64 ms, bool timer);
@ -445,7 +454,7 @@ private:
template <typename Callback>
void buildStringRepresentation(Callback callback) const;
DocumentData *_data;
gsl::not_null<DocumentData*> _data;
};
@ -523,6 +532,9 @@ public:
bool skipBubbleTail() const override {
return isBubbleBottom() && _caption.isEmpty();
}
bool canEditCaption() const override {
return !_data->isRoundVideo();
}
bool isReadyForOpen() const override {
return _data->loaded();
}
@ -535,7 +547,7 @@ protected:
bool dataLoaded() const override;
private:
DocumentData *_data;
gsl::not_null<DocumentData*> _data;
int32 _thumbw = 1;
int32 _thumbh = 1;
Text _caption;
@ -606,7 +618,7 @@ private:
int16 _pixw = 1;
int16 _pixh = 1;
ClickHandlerPtr _packLink;
DocumentData *_data;
gsl::not_null<DocumentData*> _data;
QString _emoji;
};
@ -659,8 +671,7 @@ public:
}
private:
int32 _userId;
int32 _userId = 0;
UserData *_contact = nullptr;
int _phonew = 0;
@ -671,6 +682,7 @@ private:
ClickHandlerPtr _linkl;
int _linkw = 0;
QString _link;
};
class HistoryWebPage : public HistoryMedia {
@ -769,6 +781,7 @@ private:
int16 _pixw = 0;
int16 _pixh = 0;
};
class HistoryGame : public HistoryMedia {

View File

@ -434,8 +434,8 @@ MTPDmessage::Flags newForwardedFlags(PeerData *p, int32 from, HistoryMessage *fw
if (HistoryMedia *media = fwd->getMedia()) {
if (media->type() == MediaTypeVoiceFile) {
result |= MTPDmessage::Flag::f_media_unread;
// } else if (media->type() == MediaTypeVideo) {
// result |= MTPDmessage::flag_media_unread;
// } else if (media->type() == MediaTypeVideo) {
// result |= MTPDmessage::flag_media_unread;
}
}
}

View File

@ -89,7 +89,11 @@ MTPVector<MTPDocumentAttribute> composeDocumentAttributes(DocumentData *document
if (document->dimensions.width() > 0 && document->dimensions.height() > 0) {
int32 duration = document->duration();
if (duration >= 0) {
attributes.push_back(MTP_documentAttributeVideo(MTP_flags(0), MTP_int(duration), MTP_int(document->dimensions.width()), MTP_int(document->dimensions.height())));
auto flags = MTPDdocumentAttributeVideo::Flags(0);
if (document->isRoundVideo()) {
flags |= MTPDdocumentAttributeVideo::Flag::f_round_message;
}
attributes.push_back(MTP_documentAttributeVideo(MTP_flags(flags), MTP_int(duration), MTP_int(document->dimensions.width()), MTP_int(document->dimensions.height())));
} else {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(document->dimensions.width()), MTP_int(document->dimensions.height())));
}
@ -1449,20 +1453,20 @@ void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) {
if (gifs.type() != mtpc_messages_savedGifs) return;
auto &d = gifs.c_messages_savedGifs();
auto &d_gifs = d.vgifs.v;
auto &gifsList = d.vgifs.v;
SavedGifs &saved(cRefSavedGifs());
auto &saved = cRefSavedGifs();
saved.clear();
saved.reserve(d_gifs.size());
for (int32 i = 0, l = d_gifs.size(); i != l; ++i) {
DocumentData *doc = App::feedDocument(d_gifs.at(i));
if (!doc || !doc->isAnimation()) {
saved.reserve(gifsList.size());
for (auto &gif : gifsList) {
auto document = App::feedDocument(gif);
if (!document || !document->isGifv()) {
LOG(("API Error: bad document returned in HistoryWidget::savedGifsGot!"));
continue;
}
saved.push_back(doc);
saved.push_back(document);
}
if (Local::countSavedGifsHash() != d.vhash.v) {
LOG(("API Error: received saved gifs hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countSavedGifsHash()));
@ -5315,55 +5319,58 @@ void HistoryWidget::onEditMessage() {
auto to = App::contextItem();
if (!to) return;
if (EditCaptionBox::canEdit(to)) {
Ui::show(Box<EditCaptionBox>(to));
} else {
if (_recording) {
// Just fix some strange inconsistency.
_send->clearState();
if (auto media = to->getMedia()) {
if (media->canEditCaption()) {
Ui::show(Box<EditCaptionBox>(media, to->fullId()));
return;
}
if (!_editMsgId) {
if (_replyToId || !_field->isEmpty()) {
_history->setLocalDraft(std::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled));
} else {
_history->clearLocalDraft();
}
}
auto original = to->originalText();
auto editText = textApplyEntities(original.text, original.entities);
auto editTags = ConvertEntitiesToTextTags(original.entities);
TextWithTags editData = { editText, editTags };
MessageCursor cursor = { editText.size(), editText.size(), QFIXED_MAX };
_history->setEditDraft(std::make_unique<Data::Draft>(editData, to->id, cursor, false));
applyDraft(false);
_previewData = nullptr;
if (auto media = to->getMedia()) {
if (media->type() == MediaTypeWebPage) {
_previewData = static_cast<HistoryWebPage*>(media)->webpage();
updatePreview();
}
}
if (!_previewData) {
onPreviewParse();
}
updateBotKeyboard();
if (!_field->isHidden()) _fieldBarCancel->show();
updateFieldPlaceholder();
updateMouseTracking();
updateReplyToName();
updateControlsGeometry();
updateField();
_saveDraftText = true;
_saveDraftStart = getms();
onDraftSave();
_field->setFocus();
}
if (_recording) {
// Just fix some strange inconsistency.
_send->clearState();
}
if (!_editMsgId) {
if (_replyToId || !_field->isEmpty()) {
_history->setLocalDraft(std::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled));
} else {
_history->clearLocalDraft();
}
}
auto original = to->originalText();
auto editText = textApplyEntities(original.text, original.entities);
auto editTags = ConvertEntitiesToTextTags(original.entities);
TextWithTags editData = { editText, editTags };
MessageCursor cursor = { editText.size(), editText.size(), QFIXED_MAX };
_history->setEditDraft(std::make_unique<Data::Draft>(editData, to->id, cursor, false));
applyDraft(false);
_previewData = nullptr;
if (auto media = to->getMedia()) {
if (media->type() == MediaTypeWebPage) {
_previewData = static_cast<HistoryWebPage*>(media)->webpage();
updatePreview();
}
}
if (!_previewData) {
onPreviewParse();
}
updateBotKeyboard();
if (!_field->isHidden()) _fieldBarCancel->show();
updateFieldPlaceholder();
updateMouseTracking();
updateReplyToName();
updateControlsGeometry();
updateField();
_saveDraftText = true;
_saveDraftStart = getms();
onDraftSave();
_field->setFocus();
}
void HistoryWidget::onPinMessage() {

View File

@ -764,7 +764,7 @@ void MediaPreviewWidget::resizeEvent(QResizeEvent *e) {
}
void MediaPreviewWidget::showPreview(DocumentData *document) {
if (!document || (!document->isAnimation() && !document->sticker())) {
if (!document || (!document->isAnimation() && !document->sticker()) || document->isRoundVideo()) {
hidePreview();
return;
}

View File

@ -487,7 +487,9 @@ bool MainWindow::ui_isLayerShown() {
}
void MainWindow::ui_showMediaPreview(DocumentData *document) {
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) {
return;
}
if (!_mediaPreview) {
_mediaPreview.create(bodyWidget(), controller());
updateControlsGeometry();

View File

@ -528,7 +528,7 @@ void MediaView::step_radial(TimeMs ms, bool timer) {
if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideo())) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
} else {
const FileLocation &location(_doc->location(true));
auto &location = _doc->location(true);
if (location.accessEnable()) {
if (_doc->isAnimation() || _doc->isVideo() || _doc->isTheme() || QImageReader(location.name()).canRead()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
@ -1384,8 +1384,8 @@ void MediaView::displayFinished() {
}
void MediaView::initAnimation() {
t_assert(_doc != nullptr);
t_assert(_doc->isAnimation() || _doc->isVideo());
Expects(_doc != nullptr);
Expects(_doc->isAnimation() || _doc->isVideo());
auto &location = _doc->location(true);
if (!_doc->data().isEmpty()) {
@ -1406,8 +1406,8 @@ void MediaView::initAnimation() {
void MediaView::createClipReader() {
if (_gif) return;
t_assert(_doc != nullptr);
t_assert(_doc->isAnimation() || _doc->isVideo());
Expects(_doc != nullptr);
Expects(_doc->isAnimation() || _doc->isVideo());
if (_doc->dimensions.width() && _doc->dimensions.height()) {
int w = _doc->dimensions.width();

View File

@ -3662,8 +3662,8 @@ void readSavedGifs() {
saved.reserve(cnt);
OrderedSet<DocumentId> read;
for (uint32 i = 0; i < cnt; ++i) {
DocumentData *document = Serialize::Document::readFromStream(gifs.version, gifs.stream);
if (!document || !document->isAnimation()) continue;
auto document = Serialize::Document::readFromStream(gifs.version, gifs.stream);
if (!document || !document->isGifv()) continue;
if (read.contains(document->id)) continue;
read.insert(document->id);

View File

@ -119,6 +119,9 @@ DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &
if (width > 0 && height > 0) {
if (duration >= 0) {
auto flags = MTPDdocumentAttributeVideo::Flags(0);
if (type == RoundVideoDocument) {
flags |= MTPDdocumentAttributeVideo::Flag::f_round_message;
}
attributes.push_back(MTP_documentAttributeVideo(MTP_flags(flags), MTP_int(duration), MTP_int(width), MTP_int(height)));
} else {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));

View File

@ -1299,9 +1299,6 @@ VoiceData::~VoiceData() {
}
}
DocumentAdditionalData::~DocumentAdditionalData() {
}
DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector<MTPDocumentAttribute> &attributes)
: id(id)
, _dc(dc)
@ -1353,7 +1350,7 @@ void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes
case mtpc_documentAttributeVideo: {
auto &d = attributes[i].c_documentAttributeVideo();
if (type == FileDocument) {
type = VideoDocument;
type = d.is_round_message() ? RoundVideoDocument : VideoDocument;
}
_duration = d.vduration.v;
dimensions = QSize(d.vw.v, d.vh.v);
@ -1440,8 +1437,10 @@ void DocumentData::automaticLoad(const HistoryItem *item) {
}
void DocumentData::automaticLoadSettingsChanged() {
if (loaded() || status != FileReady || (!isAnimation() && !voice()) || !saveToCache() || _loader != CancelledMtpFileLoader) return;
_loader = 0;
if (loaded() || status != FileReady || (!isAnimation() && !voice()) || !saveToCache() || _loader != CancelledMtpFileLoader) {
return;
}
_loader = nullptr;
}
void DocumentData::performActionOnLoad() {
@ -1450,10 +1449,10 @@ void DocumentData::performActionOnLoad() {
auto loc = location(true);
auto already = loc.name();
auto item = _actionOnLoadMsgId.msg ? App::histItemById(_actionOnLoadMsgId) : nullptr;
bool showImage = !isVideo() && (size < App::kImageSizeLimit);
bool playVoice = voice() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
bool playMusic = song() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
bool playAnimation = isAnimation() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && showImage && item && item->getMedia();
auto showImage = !isVideo() && (size < App::kImageSizeLimit);
auto playVoice = voice() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
auto playMusic = song() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
auto playAnimation = isAnimation() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && showImage && item && item->getMedia();
if (auto applyTheme = isTheme()) {
if (!loc.isEmpty() && loc.accessEnable()) {
App::wnd()->showDocument(this, item);
@ -1784,7 +1783,9 @@ bool fileIsImage(const QString &name, const QString &mime) {
}
void DocumentData::recountIsImage() {
if (isAnimation() || isVideo()) return;
if (isAnimation() || isVideo()) {
return;
}
_duration = fileIsImage(name, mime) ? 1 : -1; // hack
}

View File

@ -1074,17 +1074,20 @@ enum FileStatus {
FileReady = 1,
};
// Don't change the values. This type is used for serialization.
enum DocumentType {
FileDocument = 0,
VideoDocument = 1,
SongDocument = 2,
StickerDocument = 3,
AnimatedDocument = 4,
VoiceDocument = 5,
FileDocument = 0,
VideoDocument = 1,
SongDocument = 2,
StickerDocument = 3,
AnimatedDocument = 4,
VoiceDocument = 5,
RoundVideoDocument = 6,
};
struct DocumentAdditionalData {
virtual ~DocumentAdditionalData();
virtual ~DocumentAdditionalData() = default;
};
struct StickerData : public DocumentAdditionalData {
@ -1099,9 +1102,7 @@ struct StickerData : public DocumentAdditionalData {
};
struct SongData : public DocumentAdditionalData {
SongData() : duration(0) {
}
int32 duration;
int32 duration = 0;
QString title, performer;
};
@ -1193,8 +1194,11 @@ public:
const VoiceData *voice() const {
return const_cast<DocumentData*>(this)->voice();
}
bool isRoundVideo() const {
return (type == RoundVideoDocument);
}
bool isAnimation() const {
return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
return (type == AnimatedDocument) || isRoundVideo() || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
}
bool isGifv() const {
return (type == AnimatedDocument) && !mime.compare(qstr("video/mp4"), Qt::CaseInsensitive);
@ -1246,11 +1250,12 @@ public:
~DocumentData();
DocumentId id;
DocumentId id = 0;
DocumentType type = FileDocument;
QSize dimensions;
int32 date = 0;
QString name, mime;
QString name;
QString mime;
ImagePtr thumb, replyPreview;
int32 size = 0;