mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-21 15:47:38 +00:00
Display round video messages using HistoryGif.
Use autodownload and autoplay options from GIFs. Also improve EditCaptionBox code.
This commit is contained in:
parent
8d28d0691f
commit
8eb7f1f1aa
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(); });
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user