diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 3a7413bc0..4cd2a35f7 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -69,10 +69,10 @@ namespace { auto ListFromMimeData(not_null data, bool premium) { using Error = Ui::PreparedList::Error; - auto result = data->hasUrls() + const auto list = Core::ReadMimeUrls(data); + auto result = !list.isEmpty() ? Storage::PrepareMediaList( - // When we edit media, we need only 1 file. - base::GetMimeUrls(data).mid(0, 1), + list.mid(0, 1), // When we edit media, we need only 1 file. st::sendMediaPreviewSize, premium) : Ui::PreparedList(Error::EmptyFile, QString()); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index ab4672334..205d0ba9a 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -1091,13 +1091,13 @@ void SendFilesBox::captionResized() { } bool SendFilesBox::canAddFiles(not_null data) const { - return CanAddUrls(base::GetMimeUrls(data)) || data->hasImage(); + return data->hasImage() || CanAddUrls(Core::ReadMimeUrls(data)); } bool SendFilesBox::addFiles(not_null data) { const auto premium = _controller->session().premium(); auto list = [&] { - const auto urls = base::GetMimeUrls(data); + const auto urls = Core::ReadMimeUrls(data); auto result = CanAddUrls(urls) ? Storage::PrepareMediaList( urls, diff --git a/Telegram/SourceFiles/core/mime_type.cpp b/Telegram/SourceFiles/core/mime_type.cpp index 9fcace352..a3270775b 100644 --- a/Telegram/SourceFiles/core/mime_type.cpp +++ b/Telegram/SourceFiles/core/mime_type.cpp @@ -14,6 +14,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include namespace Core { +namespace { + +[[nodiscard]] bool IsImageFromFirefox(not_null data) { + // See https://bugs.telegram.org/c/6765/public + // See https://github.com/telegramdesktop/tdesktop/issues/10564 + // + // Usually we prefer pasting from URLs list instead of pasting from + // image data, because sometimes a file is copied together with an + // image data of its File Explorer thumbnail or smth like that. In + // that case you end up sending this thumbnail instead of the file. + // + // But in case of "Copy Image" from Firefox on Windows we get both + // URLs list with a file path to some Temp folder in the list and + // the image data that was copied. The file is read slower + it may + // have incorrect content in case the URL can't be accessed without + // authorization. So in that case we want only image data and we + // check for a special Firefox mime type to check for that case. + return data->hasFormat(u"application/x-moz-nativeimage"_q) + && data->hasImage(); +} + +} // namespace MimeType::MimeType(const QMimeType &type) : _typeStruct(type) { } @@ -170,9 +192,10 @@ std::shared_ptr ShareMimeMediaData( result->setData(u"application/x-td-use-jpeg"_q, "1"); result->setData(u"image/jpeg"_q, original->data(u"image/jpeg"_q)); } - if (auto list = base::GetMimeUrls(original); !list.isEmpty()) { + if (auto list = Core::ReadMimeUrls(original); !list.isEmpty()) { result->setUrls(std::move(list)); } + result->setText(Core::ReadMimeText(original)); return result; } @@ -192,4 +215,16 @@ MimeImageData ReadMimeImage(not_null data) { return {}; } +QString ReadMimeText(not_null data) { + return IsImageFromFirefox(data) ? QString() : data->text(); +} + +QList ReadMimeUrls(not_null data) { + return (data->hasUrls() && !IsImageFromFirefox(data)) + ? KUrlMimeData::urlsFromMimeData( + data, + KUrlMimeData::PreferLocalUrls) + : QList(); +} + } // namespace Core diff --git a/Telegram/SourceFiles/core/mime_type.h b/Telegram/SourceFiles/core/mime_type.h index 9406f57ba..d5aaa9eb0 100644 --- a/Telegram/SourceFiles/core/mime_type.h +++ b/Telegram/SourceFiles/core/mime_type.h @@ -65,5 +65,7 @@ struct MimeImageData { } }; [[nodiscard]] MimeImageData ReadMimeImage(not_null data); +[[nodiscard]] QString ReadMimeText(not_null data); +[[nodiscard]] QList ReadMimeUrls(not_null data); } // namespace Core diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h index a09f60bd3..aef0d45e0 100644 --- a/Telegram/SourceFiles/core/utils.h +++ b/Telegram/SourceFiles/core/utils.h @@ -38,18 +38,6 @@ inline bool in_range(Value &&value, From &&from, Till &&till) { return (value >= from) && (value < till); } -#if __has_include() -inline QList GetMimeUrls(const QMimeData *data) { - if (!data->hasUrls()) { - return {}; - } - - return KUrlMimeData::urlsFromMimeData( - data, - KUrlMimeData::PreferLocalUrls); -} -#endif - #if __has_include() inline QString IconName() { static const auto Result = KSandbox::isFlatpak() diff --git a/Telegram/SourceFiles/editor/editor_paint.cpp b/Telegram/SourceFiles/editor/editor_paint.cpp index b77e9d529..4375cca96 100644 --- a/Telegram/SourceFiles/editor/editor_paint.cpp +++ b/Telegram/SourceFiles/editor/editor_paint.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "editor/editor_paint.h" +#include "core/mime_type.h" #include "ui/boxes/confirm_box.h" #include "editor/controllers/controllers.h" #include "editor/scene/scene.h" @@ -204,16 +205,17 @@ void Paint::handleMimeData(const QMimeData *data) { using Error = Ui::PreparedList::Error; const auto premium = false; // Don't support > 2GB files here. - auto result = data->hasUrls() + const auto list = Core::ReadMimeUrls(data); + auto result = !list.isEmpty() ? Storage::PrepareMediaList( - base::GetMimeUrls(data).mid(0, 1), + list.mid(0, 1), _imageSize.width() / 2, premium) : Ui::PreparedList(Error::EmptyFile, QString()); if (result.error == Error::None) { add(base::take(result.files.front().preview)); - } else if (data->hasImage()) { - add(qvariant_cast(data->imageData())); + } else if (auto read = Core::ReadMimeImage(data)) { + add(std::move(read.image)); } } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 0580829fd..22681f1b4 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -459,7 +459,10 @@ HistoryWidget::HistoryWidget( if (action == Ui::InputField::MimeAction::Check) { return canSendFiles(data); } else if (action == Ui::InputField::MimeAction::Insert) { - return confirmSendingFiles(data, std::nullopt, data->text()); + return confirmSendingFiles( + data, + std::nullopt, + Core::ReadMimeText(data)); } Unexpected("action in MimeData hook."); }); @@ -5230,7 +5233,7 @@ bool HistoryWidget::canSendFiles(not_null data) const { return false; } else if (data->hasImage()) { return true; - } else if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + } else if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { if (ranges::all_of(urls, &QUrl::isLocalFile)) { return true; } @@ -5249,7 +5252,7 @@ bool HistoryWidget::confirmSendingFiles( const auto hasImage = data->hasImage(); const auto premium = controller()->session().user()->isPremium(); - if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { auto list = Storage::PrepareMediaList( urls, st::sendMediaPreviewSize, diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index c41065d04..40b891335 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -100,7 +100,7 @@ constexpr auto kRefreshSlowmodeLabelTimeout = crl::time(200); bool CanSendFiles(not_null data) { if (data->hasImage()) { return true; - } else if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + } else if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { if (ranges::all_of(urls, &QUrl::isLocalFile)) { return true; } @@ -825,7 +825,10 @@ void RepliesWidget::setupComposeControls() { if (action == Ui::InputField::MimeAction::Check) { return CanSendFiles(data); } else if (action == Ui::InputField::MimeAction::Insert) { - return confirmSendingFiles(data, std::nullopt, data->text()); + return confirmSendingFiles( + data, + std::nullopt, + Core::ReadMimeText(data)); } Unexpected("action in MimeData hook."); }); @@ -908,7 +911,7 @@ bool RepliesWidget::confirmSendingFiles( const auto hasImage = data->hasImage(); const auto premium = controller()->session().user()->isPremium(); - if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { auto list = Storage::PrepareMediaList( urls, st::sendMediaPreviewSize, diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 370642714..33710b711 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -70,7 +70,7 @@ namespace { bool CanSendFiles(not_null data) { if (data->hasImage()) { return true; - } else if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + } else if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { if (ranges::all_of(urls, &QUrl::isLocalFile)) { return true; } @@ -314,7 +314,10 @@ void ScheduledWidget::setupComposeControls() { if (action == Ui::InputField::MimeAction::Check) { return CanSendFiles(data); } else if (action == Ui::InputField::MimeAction::Insert) { - return confirmSendingFiles(data, std::nullopt, data->text()); + return confirmSendingFiles( + data, + std::nullopt, + Core::ReadMimeText(data)); } Unexpected("action in MimeData hook."); }); @@ -373,7 +376,7 @@ bool ScheduledWidget::confirmSendingFiles( const auto hasImage = data->hasImage(); const auto premium = controller()->session().user()->isPremium(); - if (const auto urls = base::GetMimeUrls(data); !urls.empty()) { + if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { auto list = Storage::PrepareMediaList( urls, st::sendMediaPreviewSize, diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 145234b74..18d23e662 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -74,7 +74,7 @@ void PrepareDetailsInParallel(PreparedList &result, int previewWidth) { } // namespace bool ValidatePhotoEditorMediaDragData(not_null data) { - const auto urls = base::GetMimeUrls(data); + const auto urls = Core::ReadMimeUrls(data); if (urls.size() > 1) { return false; } else if (data->hasImage()) { @@ -98,7 +98,7 @@ bool ValidatePhotoEditorMediaDragData(not_null data) { bool ValidateEditMediaDragData( not_null data, Ui::AlbumType albumType) { - const auto urls = base::GetMimeUrls(data); + const auto urls = Core::ReadMimeUrls(data); if (urls.size() > 1) { return false; } else if (data->hasImage()) { @@ -126,7 +126,7 @@ MimeDataState ComputeMimeDataState(const QMimeData *data) { return MimeDataState::Image; } - const auto urls = base::GetMimeUrls(data); + const auto urls = Core::ReadMimeUrls(data); if (urls.isEmpty()) { return MimeDataState::None; }