Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDF saving, printing #2247

Merged
merged 29 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a70b754
PDF saving, printing
mallexxx Feb 23, 2024
27f5ef9
fix getting active tab in a Popup window
mallexxx Feb 23, 2024
6f9e967
fix tests
mallexxx Feb 23, 2024
66b8402
fix tests
mallexxx Feb 23, 2024
d94de89
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Feb 26, 2024
e8ee236
fix resetting savePanelDialogRequest
mallexxx Feb 26, 2024
2dc38b7
cleanup PDF after printing
mallexxx Feb 26, 2024
84de49b
improve naming, add comments
mallexxx Feb 26, 2024
3016796
fix assertion for context menu shown in background
mallexxx Feb 26, 2024
c1a5c80
rollback InfoPlist.xcstrings
mallexxx Feb 26, 2024
9334b1b
Position Print&SaveAs items below Open with Preview
mallexxx Feb 26, 2024
ffe9c0a
add tests
mallexxx Feb 26, 2024
bc305a1
Extend test timeouts
mallexxx Feb 27, 2024
fb5be90
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Feb 27, 2024
d5ff3a5
disabled context menu tests - would it fix the tests?!
mallexxx Feb 27, 2024
d96c3b6
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Feb 28, 2024
b1a1eaf
refactor 1 test
mallexxx Feb 29, 2024
0f26ab8
fixing hanging test
mallexxx Feb 29, 2024
54a5f45
add MainActor
mallexxx Feb 29, 2024
529e332
fixing the test
mallexxx Feb 29, 2024
c4af141
fix tests
mallexxx Feb 29, 2024
04ea192
final touches
mallexxx Feb 29, 2024
e01bc85
add main menu print/save tests
mallexxx Feb 29, 2024
d6c8400
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Feb 29, 2024
16f66bc
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Feb 29, 2024
4fe31fc
Merge remote-tracking branch 'origin/main' into alex/pdf-saving
mallexxx Mar 1, 2024
37161e5
extend test timeout
mallexxx Mar 1, 2024
ffc5269
fixing testWhenTabWithNoConnectionErrorActivated_reloadTriggered
mallexxx Mar 1, 2024
1086c36
fixing Error page tests
mallexxx Mar 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2720,6 +2720,8 @@
B64C85422694590B0048FEBE /* PermissionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64C85412694590B0048FEBE /* PermissionButton.swift */; };
B64CE01E2B8622D700126CA5 /* AddressBarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64CE01D2B8622D700126CA5 /* AddressBarTests.swift */; };
B64CE01F2B8622D700126CA5 /* AddressBarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64CE01D2B8622D700126CA5 /* AddressBarTests.swift */; };
B64E42AB2B909DC9006C1346 /* test.pdf in Resources */ = {isa = PBXBuildFile; fileRef = B64E42AA2B909DC9006C1346 /* test.pdf */; };
B64E42AC2B909DC9006C1346 /* test.pdf in Resources */ = {isa = PBXBuildFile; fileRef = B64E42AA2B909DC9006C1346 /* test.pdf */; };
B65211252B29A42C00B30633 /* BookmarkStoreMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA652CDA25DDAB32009059CC /* BookmarkStoreMock.swift */; };
B65211262B29A42E00B30633 /* BookmarkStoreMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA652CDA25DDAB32009059CC /* BookmarkStoreMock.swift */; };
B65211272B29A43000B30633 /* BookmarkStoreMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA652CDA25DDAB32009059CC /* BookmarkStoreMock.swift */; };
Expand All @@ -2736,6 +2738,9 @@
B658BAB62B0F845D00D1F2C7 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = B658BAB52B0F845D00D1F2C7 /* Localizable.xcstrings */; };
B658BAB72B0F848D00D1F2C7 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = B658BAB52B0F845D00D1F2C7 /* Localizable.xcstrings */; };
B658BAB92B0F849100D1F2C7 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = B658BAB52B0F845D00D1F2C7 /* Localizable.xcstrings */; };
B65C7DFB2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65C7DFA2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift */; };
B65C7DFC2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65C7DFA2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift */; };
B65C7DFD2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65C7DFA2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift */; };
B65CD8CB2B316DF100A595BB /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = B65CD8CA2B316DF100A595BB /* SnapshotTesting */; };
B65CD8CD2B316DFC00A595BB /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = B65CD8CC2B316DFC00A595BB /* SnapshotTesting */; };
B65CD8CF2B316E0200A595BB /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = B65CD8CE2B316E0200A595BB /* SnapshotTesting */; };
Expand Down Expand Up @@ -3021,6 +3026,8 @@
B6EC37FC29B83E99001ACE79 /* TestsURLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EC37FB29B83E99001ACE79 /* TestsURLExtension.swift */; };
B6EC37FD29B83E99001ACE79 /* TestsURLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EC37FB29B83E99001ACE79 /* TestsURLExtension.swift */; };
B6EC37FF29B8D915001ACE79 /* Configuration in Frameworks */ = {isa = PBXBuildFile; productRef = B6EC37FE29B8D915001ACE79 /* Configuration */; };
B6EEDD7D2B8C69E900637EBC /* TabContentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EEDD7C2B8C69E900637EBC /* TabContentTests.swift */; };
B6EEDD7E2B8C69E900637EBC /* TabContentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EEDD7C2B8C69E900637EBC /* TabContentTests.swift */; };
B6F1C80B2761C45400334924 /* LocalUnprotectedDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336B39E22726B4B700C417D3 /* LocalUnprotectedDomains.swift */; };
B6F41031264D2B23003DA42C /* ProgressExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F41030264D2B23003DA42C /* ProgressExtension.swift */; };
B6F56567299A414300A04298 /* WKWebViewMockingExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F56566299A414300A04298 /* WKWebViewMockingExtension.swift */; };
Expand Down Expand Up @@ -4213,6 +4220,7 @@
B64C853C26944B940048FEBE /* PermissionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionStore.swift; sourceTree = "<group>"; };
B64C85412694590B0048FEBE /* PermissionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionButton.swift; sourceTree = "<group>"; };
B64CE01D2B8622D700126CA5 /* AddressBarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressBarTests.swift; sourceTree = "<group>"; };
B64E42AA2B909DC9006C1346 /* test.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = test.pdf; sourceTree = "<group>"; };
B65349A9265CF45000DCC645 /* DispatchQueueExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueueExtensionsTests.swift; sourceTree = "<group>"; };
B6553691268440D700085A79 /* WKProcessPool+GeolocationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WKProcessPool+GeolocationProvider.swift"; sourceTree = "<group>"; };
B65536962684413900085A79 /* WKGeolocationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKGeolocationProvider.h; sourceTree = "<group>"; };
Expand All @@ -4224,6 +4232,7 @@
B657841925FA484B00D8DB33 /* NSException+Catch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSException+Catch.m"; sourceTree = "<group>"; };
B657841E25FA497600D8DB33 /* NSException+Catch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSException+Catch.swift"; sourceTree = "<group>"; };
B658BAB52B0F845D00D1F2C7 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
B65C7DFA2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKPDFHUDViewWrapper.swift; sourceTree = "<group>"; };
B65CD8D42B316FCA00A595BB /* __Snapshots__ */ = {isa = PBXFileReference; lastKnownFileType = folder; path = __Snapshots__; sourceTree = "<group>"; };
B65CD8D72B341FD300A595BB /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
B65E6B9D26D9EC0800095F96 /* CircularProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4406,6 +4415,7 @@
B6EC37EA29B5DA2A001ACE79 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
B6EC37FA29B6447F001ACE79 /* TestsServer.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TestsServer.xcconfig; sourceTree = "<group>"; };
B6EC37FB29B83E99001ACE79 /* TestsURLExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestsURLExtension.swift; sourceTree = "<group>"; };
B6EEDD7C2B8C69E900637EBC /* TabContentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabContentTests.swift; sourceTree = "<group>"; };
B6F41030264D2B23003DA42C /* ProgressExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressExtension.swift; sourceTree = "<group>"; };
B6F56566299A414300A04298 /* WKWebViewMockingExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WKWebViewMockingExtension.swift; sourceTree = "<group>"; };
B6F7127D29F6779000594A45 /* QRSharingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRSharingService.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7633,6 +7643,7 @@
B602E7CE2A93A5FF00F12201 /* WKBackForwardListExtension.swift */,
B68412242B6A67920092F66A /* WKBackForwardListItemExtension.swift */,
B6DA06E7291401D700225DE2 /* WKMenuItemIdentifier.swift */,
B65C7DFA2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift */,
B645D8F529FA95440024461F /* WKProcessPoolExtension.swift */,
AAA0CC69253CC43C0079BC96 /* WKUserContentControllerExtension.swift */,
B63D466725BEB6C200874977 /* WKWebView+Private.h */,
Expand Down Expand Up @@ -7869,8 +7880,10 @@
B644B43C29D56811003FA9AB /* Tab */ = {
isa = PBXGroup;
children = (
B64E42AA2B909DC9006C1346 /* test.pdf */,
B644B43929D565DB003FA9AB /* SearchNonexistentDomainTests.swift */,
B693766D2B6B5F26005BD9D4 /* ErrorPageTests.swift */,
B6EEDD7C2B8C69E900637EBC /* TabContentTests.swift */,
B64CE01D2B8622D700126CA5 /* AddressBarTests.swift */,
);
path = Tab;
Expand Down Expand Up @@ -9022,6 +9035,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B64E42AC2B909DC9006C1346 /* test.pdf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -9036,6 +9050,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B64E42AB2B909DC9006C1346 /* test.pdf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -9725,6 +9740,7 @@
1D36E659298AA3BA00AA485D /* InternalUserDeciderStore.swift in Sources */,
B6BCC5242AFCDABB002C5499 /* DataImportSourceViewModel.swift in Sources */,
3706FEBC293F6EFF00E42796 /* BWResponse.swift in Sources */,
B65C7DFC2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */,
3706FAF4293F65D500E42796 /* SafariBookmarksReader.swift in Sources */,
31C9ADE62AF0564500CEF57D /* WaitlistFeatureSetupHandler.swift in Sources */,
B65211262B29A42E00B30633 /* BookmarkStoreMock.swift in Sources */,
Expand Down Expand Up @@ -10567,6 +10583,7 @@
B62A234129C41D4400D22475 /* HistoryIntegrationTests.swift in Sources */,
B603973929BF0EBE00902A34 /* PrivacyDashboardIntegrationTests.swift in Sources */,
B644B43E29D5682B003FA9AB /* SearchNonexistentDomainTests.swift in Sources */,
B6EEDD7E2B8C69E900637EBC /* TabContentTests.swift in Sources */,
3706FEA5293F662100E42796 /* CoreDataEncryptionTesting.xcdatamodeld in Sources */,
B603973D29BF1D7D00902A34 /* AutoconsentIntegrationTests.swift in Sources */,
B60C6F8729B1CAB2007BFAA8 /* TestRunHelper.swift in Sources */,
Expand Down Expand Up @@ -10609,6 +10626,7 @@
4B1AD92125FC474E00261379 /* CoreDataEncryptionTesting.xcdatamodeld in Sources */,
B62A234029C41D4400D22475 /* HistoryIntegrationTests.swift in Sources */,
B603973829BF0EBE00902A34 /* PrivacyDashboardIntegrationTests.swift in Sources */,
B6EEDD7D2B8C69E900637EBC /* TabContentTests.swift in Sources */,
B644B43D29D56829003FA9AB /* SearchNonexistentDomainTests.swift in Sources */,
B603973C29BF1D7D00902A34 /* AutoconsentIntegrationTests.swift in Sources */,
B60C6F8629B1CAB0007BFAA8 /* TestRunHelper.swift in Sources */,
Expand Down Expand Up @@ -10979,6 +10997,7 @@
4B957A192AC7AE700062CA31 /* PasswordManagerCoordinator.swift in Sources */,
4B957A1A2AC7AE700062CA31 /* PasswordManagementIdentityModel.swift in Sources */,
4B957A1B2AC7AE700062CA31 /* UserDefaultsWrapper.swift in Sources */,
B65C7DFD2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */,
4B957A1C2AC7AE700062CA31 /* PasswordManagementPopover.swift in Sources */,
4B957A1D2AC7AE700062CA31 /* BWCommunicator.swift in Sources */,
4B957A1E2AC7AE700062CA31 /* HomePageRecentlyVisitedModel.swift in Sources */,
Expand Down Expand Up @@ -11592,6 +11611,7 @@
AA6EF9AD25066F42004754E6 /* WindowsManager.swift in Sources */,
1D43EB3A292B63B00065E5D6 /* BWRequest.swift in Sources */,
B684121C2B6A1D880092F66A /* ErrorPageHTMLTemplate.swift in Sources */,
B65C7DFB2B886CF0001E2D5C /* WKPDFHUDViewWrapper.swift in Sources */,
B68458CD25C7EB9000DC17B6 /* WKWebViewConfigurationExtensions.swift in Sources */,
85AC7ADD27BEB6EE00FFB69B /* HomePageDefaultBrowserModel.swift in Sources */,
B6619EFB2B111CC500CD9186 /* InstructionsFormatParser.swift in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions DuckDuckGo/Common/Extensions/FileManagerExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ import Foundation

extension FileManager {

@discardableResult
func moveItem(at srcURL: URL, to destURL: URL, incrementingIndexIfExists flag: Bool, pathExtension: String? = nil) throws -> URL {
return try self.perform(self.moveItem, from: srcURL, to: destURL, incrementingIndexIfExists: flag, pathExtension: pathExtension)
}

@discardableResult
func copyItem(at srcURL: URL, to destURL: URL, incrementingIndexIfExists flag: Bool, pathExtension: String? = nil) throws -> URL {
return try self.perform(self.copyItem, from: srcURL, to: destURL, incrementingIndexIfExists: flag, pathExtension: pathExtension)
}

private func perform(_ operation: (URL, URL) throws -> Void,
from srcURL: URL,
to destURL: URL,
Expand Down
97 changes: 97 additions & 0 deletions DuckDuckGo/Common/Extensions/WKPDFHUDViewWrapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// WKPDFHUDViewWrapper.swift
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation
import WebKit

/// A wrapper for the PDF HUD window with Zoom controls, Download and Open in Preview buttons
/// Used to trigger Save PDF
struct WKPDFHUDViewWrapper {

static let WKPDFHUDViewClass: AnyClass? = NSClassFromString("WKPDFHUDView")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: can probably make these static let private as they don’t have to be accessed by/known to the outside

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used in availability tests

static let performActionForControlSelector = NSSelectorFromString("_performActionForControl:")
static let visibleKey = "_visible"
static let setVisibleSelector = NSSelectorFromString("_setVisible:")
static let savePDFControlId = "arrow.down.circle"

private let hudView: NSView

var isVisible: Bool {
get {
hudView.layer?.sublayers?.first?.opacity ?? 0 > 0
}
nonmutating set {
guard hudView.responds(to: Self.setVisibleSelector) else { return }
hudView.perform(Self.setVisibleSelector, with: newValue)
}
}

/// Create a wrapper over the PDF HUD view validating its class is `WKPDFHUDView`
/// - parameter view: the WKPDFHUDView to wrap
/// - returns nil if the view
init?(view: NSView) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Would be good to add some markdown documentation for the two init. I think it would make it clearer to know when/how to use it, and in what scenario they would fail to create the instance without having to look at the implementation.

guard type(of: view) == Self.WKPDFHUDViewClass else { return nil }

guard Self.WKPDFHUDViewClass?.instancesRespond(to: Self.performActionForControlSelector) == true else {
assertionFailure("WKPDFHUDView doesn‘t respond to _performActionForControl:")
return nil
}
self.hudView = view
}

/// Find WebView‘s PDF HUD view at a clicked point
///
/// Used to get PDF controls view of a clicked WebView frame for `Print…` and `Save As…` PDF context menu commands
static func getPdfHudView(in webView: WKWebView, at location: NSPoint? = nil) -> Self? {
guard let hudView = webView.subviews.last(where: { type(of: $0) == Self.WKPDFHUDViewClass && $0.frame.contains(location ?? $0.frame.origin) }) else {
#if DEBUG
Task {
if await webView.mimeType == "application/pdf" {
assertionFailure("WebView doesn‘t have PDF HUD View")
}
}
#endif
return nil
}
return self.init(view: hudView)
}

func savePDF() {
Copy link
Contributor

@alessandroboron alessandroboron Feb 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to test this behaviour?

let wasVisible = isVisible
self.setIsVisibleIVar(true)
defer {
if !wasVisible {
self.setIsVisibleIVar(false)
}
}
hudView.perform(Self.performActionForControlSelector, with: Self.savePDFControlId)
}

// try to set _visible ivar value directly to avoid actually showing the HUD
private func setIsVisibleIVar(_ value: Bool) {
do {
try NSException.catch {
hudView.setValue(value, forKey: Self.visibleKey)
}
} catch {
assertionFailure("\(error)")
self.isVisible = value
}
}

}
10 changes: 10 additions & 0 deletions DuckDuckGo/Common/Extensions/WKWebViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@ extension WKWebView {
return self.printOperation(with: printInfo)
}

func hudView(at point: NSPoint? = nil) -> WKPDFHUDViewWrapper? {
WKPDFHUDViewWrapper.getPdfHudView(in: self, at: point)
}

func savePDF(_ pdfHUD: WKPDFHUDViewWrapper? = nil) -> Bool {
guard let hudView = pdfHUD ?? hudView() else { return false }
hudView.savePDF()
return true
}

var fullScreenPlaceholderView: NSView? {
guard self.responds(to: Selector.fullScreenPlaceholderView) else { return nil }
return self.value(forKey: NSStringFromSelector(Selector.fullScreenPlaceholderView)) as? NSView
Expand Down
7 changes: 4 additions & 3 deletions DuckDuckGo/FileDownload/Model/FileDownloadManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ final class FileDownloadManager: FileDownloadManagerProtocol {
return url
}

var promptForLocation: Bool {
func shouldPromptForLocation(for url: URL?) -> Bool {
switch self {
case .prompt: return true
case .preset, .auto: return false
case .preset: return false
case .auto: return url?.isFileURL ?? true // always prompt when "downloading" a local file
}
}
}
Expand All @@ -96,7 +97,7 @@ final class FileDownloadManager: FileDownloadManagerProtocol {
dispatchPrecondition(condition: .onQueue(.main))

let task = WebKitDownloadTask(download: download,
promptForLocation: location.promptForLocation,
promptForLocation: location.shouldPromptForLocation(for: download.originalRequest?.url),
destinationURL: location.destinationURL,
tempURL: location.tempURL,
isBurner: fromBurnerWindow)
Expand Down
Loading
Loading