diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index d41e71a1f9..6c791bf62f 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -702,7 +702,7 @@ void BackgroundPreviewBox::checkLoadedDocument() { const auto document = _paper.document(); if (!_full.isNull() || !document - || !document->loaded(DocumentData::FilePathResolveChecked) + || !document->loaded(DocumentData::FilePathResolve::Checked) || _generating) { return; } diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index c263d0db57..fd442a1ba8 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -35,6 +35,8 @@ namespace { constexpr auto kMemoryForCache = 32 * 1024 * 1024; +using FilePathResolve = DocumentData::FilePathResolve; + Core::MediaActiveCache &ActiveCache() { static auto Instance = Core::MediaActiveCache( kMemoryForCache, @@ -294,6 +296,19 @@ void DocumentOpenClickHandler::Open( return; } + const auto openFile = [&] { + const auto &location = data->location(true); + if (data->size < App::kImageSizeLimit && location.accessEnable()) { + const auto guard = gsl::finally([&] { + location.accessDisable(); + }); + if (QImageReader(location.name()).canRead()) { + Core::App().showDocument(data, context); + return; + } + } + LaunchWithWarning(location.name(), context); + }; const auto &location = data->location(true); if (data->isTheme() && !location.isEmpty() && location.accessEnable()) { Core::App().showDocument(data, context); @@ -309,17 +324,11 @@ void DocumentOpenClickHandler::Open( } else { Core::App().showDocument(data, context); } - } else if (!location.isEmpty()) { - if (data->size < App::kImageSizeLimit && location.accessEnable()) { - const auto guard = gsl::finally([&] { - location.accessDisable(); - }); - if (QImageReader(location.name()).canRead()) { - Core::App().showDocument(data, context); - return; - } - } - LaunchWithWarning(location.name(), context); + } else if (!location.isEmpty() + || (data->loaded() + && !data->filepath( + FilePathResolve::SaveFromDataSilent).isEmpty())) { + openFile(); } else if (data->status == FileReady || data->status == FileDownloadFailed) { DocumentSaveClickHandler::Save(origin, data); @@ -338,19 +347,13 @@ void DocumentSaveClickHandler::Save( return; } - if (mode == Mode::ToCacheOrFile - && data->loaded(DocumentData::FilePathResolveSaveFromDataSilent)) { - File::OpenWith(data->filepath(), QCursor::pos()); - return; - } auto savename = QString(); if (mode != Mode::ToCacheOrFile || !data->saveToCache()) { - const auto filepath = data->filepath( - DocumentData::FilePathResolveChecked); + const auto filepath = data->filepath(FilePathResolve::Checked); if (mode != Mode::ToNewFile && (!filepath.isEmpty() || !data->filepath( - DocumentData::FilePathResolveSaveFromData).isEmpty())) { + FilePathResolve::SaveFromData).isEmpty())) { return; } const auto fileinfo = QFileInfo(filepath); @@ -389,6 +392,31 @@ void DocumentCancelClickHandler::onClickImpl() const { } } +void DocumentOpenWithClickHandler::Open( + Data::FileOrigin origin, + not_null data) { + if (!data->date) { + return; + } + + if (data->loaded()) { + const auto path = data->filepath( + FilePathResolve::SaveFromDataSilent); + if (!path.isEmpty()) { + File::OpenWith(path, QCursor::pos()); + return; + } + } + DocumentSaveClickHandler::Save( + origin, + data, + DocumentSaveClickHandler::Mode::ToFile); +} + +void DocumentOpenWithClickHandler::onClickImpl() const { + Open(context(), document()); +} + Data::FileOrigin StickerData::setOrigin() const { return set.match([&](const MTPDinputStickerSetID &data) { return Data::FileOrigin( @@ -689,7 +717,7 @@ void DocumentData::automaticLoadSettingsChanged() { _loader = nullptr; } -bool DocumentData::loaded(FilePathResolveType type) const { +bool DocumentData::loaded(FilePathResolve resolve) const { if (loading() && _loader->finished()) { if (_loader->cancelled()) { destroyLoader(CancelledMtpFileLoader); @@ -721,7 +749,7 @@ bool DocumentData::loaded(FilePathResolveType type) const { } _owner->notifyDocumentLayoutChanged(this); } - return !data().isEmpty() || !filepath(type).isEmpty(); + return !data().isEmpty() || !filepath(resolve).isEmpty(); } void DocumentData::destroyLoader(mtpFileLoader *newValue) const { @@ -782,7 +810,7 @@ void DocumentData::save( const QString &toFile, LoadFromCloudSetting fromCloud, bool autoLoading) { - if (loaded(FilePathResolveChecked)) { + if (loaded(FilePathResolve::Checked)) { auto &l = location(true); if (!toFile.isEmpty()) { if (!_data.isEmpty()) { @@ -946,14 +974,16 @@ void DocumentData::setLocation(const FileLocation &loc) { } } -QString DocumentData::filepath(FilePathResolveType type) const { - bool check = (type != FilePathResolveCached); +QString DocumentData::filepath(FilePathResolve resolve) const { + bool check = (resolve != FilePathResolve::Cached); QString result = (check && _location.name().isEmpty()) ? QString() : location(check).name(); bool saveFromData = result.isEmpty() && !data().isEmpty(); if (saveFromData) { - if (type != FilePathResolveSaveFromData && type != FilePathResolveSaveFromDataSilent) { + if (resolve != FilePathResolve::SaveFromData + && resolve != FilePathResolve::SaveFromDataSilent) { saveFromData = false; - } else if (type == FilePathResolveSaveFromDataSilent && Global::AskDownloadPath()) { + } else if (resolve == FilePathResolve::SaveFromDataSilent + && Global::AskDownloadPath()) { saveFromData = false; } } @@ -1284,7 +1314,7 @@ bool DocumentData::isVideoMessage() const { bool DocumentData::isAnimation() const { return (type == AnimatedDocument) || isVideoMessage() - || hasMimeType(qstr("image/gif")); + || (hasMimeType(qstr("image/gif")) && !_inappPlaybackFailed); } bool DocumentData::isGifv() const { @@ -1553,7 +1583,7 @@ base::binary_guard ReadImageAsync( // // document->setInappPlaybackFailed(); // const auto filepath = document->filepath( -// DocumentData::FilePathResolveSaveFromData); +// DocumentData::FilePathResolve::SaveFromData); // if (filepath.isEmpty()) { // const auto save = [=] { // Ui::hideLayer(); diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index f34d09f2e2..8ca27e1441 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -99,14 +99,14 @@ public: const HistoryItem *item); void automaticLoadSettingsChanged(); - enum FilePathResolveType { - FilePathResolveCached, - FilePathResolveChecked, - FilePathResolveSaveFromData, - FilePathResolveSaveFromDataSilent, + enum class FilePathResolve { + Cached, + Checked, + SaveFromData, + SaveFromDataSilent, }; [[nodiscard]] bool loaded( - FilePathResolveType type = FilePathResolveCached) const; + FilePathResolve resolve = FilePathResolve::Cached) const; [[nodiscard]] bool loading() const; [[nodiscard]] QString loadingFilePath() const; [[nodiscard]] bool displayLoading() const; @@ -129,7 +129,7 @@ public: void setLocation(const FileLocation &loc); [[nodiscard]] QString filepath( - FilePathResolveType type = FilePathResolveCached) const; + FilePathResolve resolve = FilePathResolve::Cached) const; [[nodiscard]] bool saveToCache() const; @@ -344,6 +344,18 @@ protected: }; +class DocumentOpenWithClickHandler : public DocumentClickHandler { +public: + using DocumentClickHandler::DocumentClickHandler; + static void Open( + Data::FileOrigin origin, + not_null document); + +protected: + void onClickImpl() const override; + +}; + class VoiceSeekClickHandler : public DocumentOpenClickHandler { public: using DocumentOpenClickHandler::DocumentOpenClickHandler; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 2f79645b61..0cdc426b88 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -1011,7 +1011,7 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }); } } - if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) { + if (!document->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) { _menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] { showContextInFolder(document); }); @@ -1118,7 +1118,7 @@ void InnerWidget::cancelContextDownload(not_null document) { void InnerWidget::showContextInFolder(not_null document) { const auto filepath = document->filepath( - DocumentData::FilePathResolveChecked); + DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { File::ShowInFolder(filepath); } @@ -1625,7 +1625,7 @@ void InnerWidget::performDrag() { // auto mimeData = std::make_unique(); // mimeData->setData(forwardMimeType, "1"); // if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { - // auto filepath = document->filepath(DocumentData::FilePathResolveChecked); + // auto filepath = document->filepath(DocumentData::FilePathResolve::Checked); // if (!filepath.isEmpty()) { // QList urls; // urls.push_back(QUrl::fromLocalFile(filepath)); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 0344b9b347..c17def5770 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1192,7 +1192,7 @@ std::unique_ptr HistoryInner::prepareDrag() { if (const auto media = view->media()) { if (const auto document = media->getDocument()) { const auto filepath = document->filepath( - DocumentData::FilePathResolveChecked); + DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { QList urls; urls.push_back(QUrl::fromLocalFile(filepath)); @@ -1538,7 +1538,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { saveContextGif(itemId); }); } - if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) { + if (!document->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) { _menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] { showContextInFolder(document); }); @@ -1814,7 +1814,7 @@ void HistoryInner::cancelContextDownload(not_null document) { void HistoryInner::showContextInFolder(not_null document) { const auto filepath = document->filepath( - DocumentData::FilePathResolveChecked); + DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { File::ShowInFolder(filepath); } diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index 7403c8f7f9..f356e019ee 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -340,7 +340,9 @@ struct HistoryMessageLogEntryOriginal class FileClickHandler; struct HistoryDocumentThumbed : public RuntimeComponent { - std::shared_ptr _linksavel, _linkcancell; + std::shared_ptr _linksavel; + std::shared_ptr _linkopenwithl; + std::shared_ptr _linkcancell; int _thumbw = 0; mutable int _linkw = 0; diff --git a/Telegram/SourceFiles/history/media/history_media_document.cpp b/Telegram/SourceFiles/history/media/history_media_document.cpp index 877255cca2..69fb970c03 100644 --- a/Telegram/SourceFiles/history/media/history_media_document.cpp +++ b/Telegram/SourceFiles/history/media/history_media_document.cpp @@ -86,6 +86,9 @@ void HistoryDocument::createComponents(bool caption) { thumbed->_linksavel = std::make_shared( _data, _parent->data()->fullId()); + thumbed->_linkopenwithl = std::make_shared( + _data, + _parent->data()->fullId()); thumbed->_linkcancell = std::make_shared( _data, _parent->data()->fullId()); @@ -282,6 +285,8 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, if (_data->status != FileUploadFailed) { const auto &lnk = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell + : _data->loaded() + ? thumbed->_linkopenwithl : thumbed->_linksavel; bool over = ClickHandler::showAsActive(lnk); p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); @@ -474,6 +479,8 @@ TextState HistoryDocument::textState(QPoint point, StateRequest request) const { if (rtlrect(nameleft, linktop, thumbed->_linkw, st::semiboldFont->height, width()).contains(point)) { result.link = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell + : _data->loaded() + ? thumbed->_linkopenwithl : thumbed->_linksavel; return result; } diff --git a/Telegram/SourceFiles/history/media/history_media_gif.cpp b/Telegram/SourceFiles/history/media/history_media_gif.cpp index e2a51d847f..f16afae6f1 100644 --- a/Telegram/SourceFiles/history/media/history_media_gif.cpp +++ b/Telegram/SourceFiles/history/media/history_media_gif.cpp @@ -874,7 +874,7 @@ void HistoryGif::playAnimation(bool autoplay) { using Mode = Media::Clip::Reader::Mode; if (_gif) { stopAnimation(); - } else if (_data->loaded(DocumentData::FilePathResolveChecked)) { + } else if (_data->loaded(DocumentData::FilePathResolve::Checked)) { if (!cAutoPlayGif()) { history()->owner().stopAutoplayAnimations(); } diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 497f3a026a..a3165c3956 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -112,7 +112,7 @@ void OpenGif(FullMsgId itemId) { void ShowInFolder(not_null document) { const auto filepath = document->filepath( - DocumentData::FilePathResolveChecked); + DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { File::ShowInFolder(filepath); } @@ -175,7 +175,7 @@ void AddDocumentActions( [=] { ToggleFavedSticker(document, contextId); }); } if (!document->filepath( - DocumentData::FilePathResolveChecked).isEmpty()) { + DocumentData::FilePathResolve::Checked).isEmpty()) { menu->addAction( lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index cecb677c6b..163d15ee29 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -2311,7 +2311,7 @@ std::unique_ptr ListWidget::prepareDrag() { if (const auto media = pressedView->media()) { if (const auto document = media->getDocument()) { const auto filepath = document->filepath( - DocumentData::FilePathResolveChecked); + DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { QList urls; urls.push_back(QUrl::fromLocalFile(filepath)); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 2ffd6da8df..816425a535 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -1256,7 +1256,7 @@ void ListWidget::showContextMenu( document->cancel(); }); } else { - auto filepath = document->filepath(DocumentData::FilePathResolveChecked); + auto filepath = document->filepath(DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { auto handler = App::LambdaDelayed( st::defaultDropdownMenu.menu.ripple.hideDuration, @@ -1957,7 +1957,7 @@ void ListWidget::performDrag() { // auto mimeData = std::make_unique(); // mimeData->setData(forwardMimeType, "1"); // if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { - // auto filepath = document->filepath(DocumentData::FilePathResolveChecked); + // auto filepath = document->filepath(DocumentData::FilePathResolve::Checked); // if (!filepath.isEmpty()) { // QList urls; // urls.push_back(QUrl::fromLocalFile(filepath)); diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index f3ca16a077..d336eed174 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -466,7 +466,7 @@ void OverlayWidget::updateControls() { _docCancel->moveToLeft(_docRect.x() + 2 * st::mediaviewFilePadding + st::mediaviewFileIconSize, _docRect.y() + st::mediaviewFilePadding + st::mediaviewFileLinksTop); _docCancel->show(); } else { - if (_doc->loaded(DocumentData::FilePathResolveChecked)) { + if (_doc->loaded(DocumentData::FilePathResolve::Checked)) { _docDownload->hide(); _docSaveAs->moveToLeft(_docRect.x() + 2 * st::mediaviewFilePadding + st::mediaviewFileIconSize, _docRect.y() + st::mediaviewFilePadding + st::mediaviewFileLinksTop); _docSaveAs->show(); @@ -490,7 +490,7 @@ void OverlayWidget::updateControls() { updateThemePreviewGeometry(); _saveVisible = (_photo && _photo->loaded()) - || (_doc && (_doc->loaded(DocumentData::FilePathResolveChecked) + || (_doc && (_doc->loaded(DocumentData::FilePathResolve::Checked) || !documentContentShown())); _saveNav = myrtlrect(width() - st::mediaviewIconSize.width() * 2, height() - st::mediaviewIconSize.height(), st::mediaviewIconSize.width(), st::mediaviewIconSize.height()); _saveNavIcon = centerrect(_saveNav, st::mediaviewSave); @@ -593,7 +593,7 @@ void OverlayWidget::updateActions() { if (IsServerMsgId(_msgid.msg)) { _actions.push_back({ lang(lng_context_to_msg), SLOT(onToMessage()) }); } - if (_doc && !_doc->filepath(DocumentData::FilePathResolveChecked).isEmpty()) { + if (_doc && !_doc->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) { _actions.push_back({ lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), SLOT(onShowInFolder()) }); } if ((_doc && documentContentShown()) || (_photo && _photo->loaded())) { @@ -1194,7 +1194,7 @@ void OverlayWidget::onSaveCancel() { void OverlayWidget::onShowInFolder() { if (!_doc) return; - auto filepath = _doc->filepath(DocumentData::FilePathResolveChecked); + auto filepath = _doc->filepath(DocumentData::FilePathResolve::Checked); if (!filepath.isEmpty()) { File::ShowInFolder(filepath); }