Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit d23b694

Browse files
authored
1 parent 3e9c5b4 commit d23b694

17 files changed

+314
-57
lines changed

DuckDuckGo/Common/Extensions/NSOpenPanelExtensions.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ import UniformTypeIdentifiers
2121

2222
extension NSOpenPanel {
2323

24-
static func downloadDirectoryPanel() -> NSOpenPanel {
25-
let downloadPreferences = DownloadsPreferences()
24+
static func downloadDirectoryPanel(downloadsPreferences: DownloadsPreferences = .shared) -> NSOpenPanel {
2625
let panel = NSOpenPanel()
2726

28-
panel.directoryURL = downloadPreferences.effectiveDownloadLocation
27+
panel.directoryURL = downloadsPreferences.effectiveDownloadLocation
2928
panel.canChooseFiles = false
3029
panel.canChooseDirectories = true
3130
panel.canCreateDirectories = true

DuckDuckGo/Common/View/AppKit/CircularProgressView.swift

+17-14
Original file line numberDiff line numberDiff line change
@@ -439,72 +439,75 @@ struct CircularProgress: NSViewRepresentable {
439439
var body: some View {
440440
HStack {
441441
VStack {
442-
Toggle("Animate", isOn: $animate)
443-
Toggle("Slow animations", isOn: $slowAnimations)
442+
Toggle(isOn: $animate) {
443+
Text(verbatim: "Animate")
444+
}
445+
Toggle(isOn: $slowAnimations) {
446+
Text(verbatim: "Slow animations")
447+
}
444448
Divider()
445449

446450
Button {
447451
perform {
448452
progress = nil
449453
}
450454
} label: {
451-
Text("Reset (nil)").frame(width: 120)
455+
Text(verbatim: "Reset (nil)").frame(width: 120)
452456
}
453457
Button {
454458
perform {
455459
progress = -1
456460
}
457461
} label: {
458-
Text("Indeterminate (-1)").frame(width: 120)
462+
Text(verbatim: "Indeterminate (-1)").frame(width: 120)
459463
}
460464
Button {
461465
perform {
462466
progress = 0
463467
}
464468
} label: {
465-
Text("Zero").frame(width: 120)
469+
Text(verbatim: "Zero").frame(width: 120)
466470
}
467471
Button {
468472
perform {
469473
progress = 0.1
470474
}
471475
} label: {
472-
Text("10%").frame(width: 120)
476+
Text(verbatim: "10%").frame(width: 120)
473477
}
474478
Button {
475479
perform {
476480
progress = 0.2
477481
}
478482
} label: {
479-
Text("20%").frame(width: 120)
483+
Text(verbatim: "20%").frame(width: 120)
480484
}
481485
Button {
482486
perform {
483487
progress = 0.5
484488
}
485489
} label: {
486-
Text("50%").frame(width: 120)
490+
Text(verbatim: "50%").frame(width: 120)
487491
}
488492
Button {
489493
perform {
490494
progress = 0.8
491495
}
492496
} label: {
493-
Text("80%").frame(width: 120)
497+
Text(verbatim: "80%").frame(width: 120)
494498
}
495499
Button {
496500
perform {
497501
progress = 1
498502
}
499503
} label: {
500-
Text("100%").frame(width: 120)
504+
Text(verbatim: "100%").frame(width: 120)
501505
}
502506
Divider()
503507

504508
Button {
505509
Task {
506510
progress = nil
507-
508511
perform {
509512
progress = 0
510513
}
@@ -515,7 +518,7 @@ struct CircularProgress: NSViewRepresentable {
515518
}
516519
}
517520
} label: {
518-
Text("nil->0->nil").frame(width: 120)
521+
Text(verbatim: "nil->0->nil").frame(width: 120)
519522
}
520523

521524
Button {
@@ -532,7 +535,7 @@ struct CircularProgress: NSViewRepresentable {
532535
}
533536
}
534537
} label: {
535-
Text("0->1->nil").frame(width: 120)
538+
Text(verbatim: "0->1->nil").frame(width: 120)
536539
}
537540

538541
Button {
@@ -561,7 +564,7 @@ struct CircularProgress: NSViewRepresentable {
561564
}
562565
}
563566
} label: {
564-
Text("-1 -> 0 ... 1").frame(width: 120)
567+
Text(verbatim: "-1 -> 0 ... 1").frame(width: 120)
565568
}
566569

567570
Spacer()

DuckDuckGo/FileDownload/Model/FileDownloadManager.swift

+27-4
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ final class FileDownloadManager: FileDownloadManagerProtocol {
5656

5757
weak var delegate: FileDownloadManagerDelegate?
5858

59-
init(preferences: DownloadsPreferences = .init()) {
59+
init(preferences: DownloadsPreferences = .shared) {
6060
self.preferences = preferences
6161
}
6262

@@ -102,7 +102,17 @@ final class FileDownloadManager: FileDownloadManagerProtocol {
102102
tempURL: location.tempURL,
103103
isBurner: fromBurnerWindow)
104104

105-
self.downloadTaskDelegates[task] = { [weak delegate] in delegate }
105+
let shouldCancelDownloadIfDelegateIsGone = delegate != nil
106+
self.downloadTaskDelegates[task] = { [weak delegate] in
107+
if let delegate {
108+
return delegate
109+
}
110+
// if the delegate was originally provided but deallocated since then – the download task should be cancelled
111+
if shouldCancelDownloadIfDelegateIsGone {
112+
return CancelledDownloadTaskDelegate()
113+
}
114+
return nil
115+
}
106116

107117
downloads.insert(task)
108118
downloadAddedSubject.send(task)
@@ -205,7 +215,7 @@ extension FileDownloadManager: WebKitDownloadTaskDelegate {
205215
fileTypes.append(fileType)
206216
}
207217

208-
delegate.chooseDestination(suggestedFilename: suggestedFilename, directoryURL: downloadLocation, fileTypes: fileTypes) { [weak self] url, fileType in
218+
delegate.chooseDestination(suggestedFilename: suggestedFilename, fileTypes: fileTypes) { [weak self] url, fileType in
209219
guard let self, let url else {
210220
completion(nil, nil)
211221
return
@@ -259,8 +269,21 @@ extension FileDownloadManager: WebKitDownloadTaskDelegate {
259269
protocol DownloadTaskDelegate: AnyObject {
260270

261271
@MainActor
262-
func chooseDestination(suggestedFilename: String?, directoryURL: URL?, fileTypes: [UTType], callback: @escaping @MainActor (URL?, UTType?) -> Void)
272+
func chooseDestination(suggestedFilename: String?, fileTypes: [UTType], callback: @escaping @MainActor (URL?, UTType?) -> Void)
263273
@MainActor
264274
func fileIconFlyAnimationOriginalRect(for downloadTask: WebKitDownloadTask) -> NSRect?
265275

266276
}
277+
278+
// if the original Download Task delegate is gone, this one is used to cancel the download
279+
final class CancelledDownloadTaskDelegate: DownloadTaskDelegate {
280+
281+
func chooseDestination(suggestedFilename: String?, fileTypes: [UTType], callback: @escaping @MainActor (URL?, UTType?) -> Void) {
282+
callback(nil, nil)
283+
}
284+
285+
func fileIconFlyAnimationOriginalRect(for downloadTask: WebKitDownloadTask) -> NSRect? {
286+
nil
287+
}
288+
289+
}

DuckDuckGo/FileDownload/View/DownloadsViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ final class DownloadsViewController: NSViewController {
158158
// MARK: User Actions
159159

160160
@IBAction func openDownloadsFolderAction(_ sender: Any) {
161-
let prefs = DownloadsPreferences()
161+
let prefs = DownloadsPreferences.shared
162162
var url: URL?
163163
var itemToSelect: URL?
164164

DuckDuckGo/Localizable.xcstrings

+1-1
Original file line numberDiff line numberDiff line change
@@ -49861,4 +49861,4 @@
4986149861
}
4986249862
},
4986349863
"version" : "1.0"
49864-
}
49864+
}

DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,11 @@ final class NavigationBarViewController: NSViewController {
670670
guard let self else { return }
671671

672672
let shouldShowPopover = update.kind == .updated
673-
&& DownloadsPreferences().shouldOpenPopupOnCompletion
674-
&& update.item.destinationURL != nil
675-
&& update.item.tempURL == nil
676-
&& !update.item.isBurner
677-
&& WindowControllersManager.shared.lastKeyMainWindowController?.window === downloadsButton.window
673+
&& DownloadsPreferences.shared.shouldOpenPopupOnCompletion
674+
&& update.item.destinationURL != nil
675+
&& update.item.tempURL == nil
676+
&& !update.item.isBurner
677+
&& WindowControllersManager.shared.lastKeyMainWindowController?.window === downloadsButton.window
678678

679679
if shouldShowPopover {
680680
self.popovers.showDownloadsPopoverAndAutoHide(usingView: downloadsButton,

DuckDuckGo/Preferences/Model/DownloadsPreferences.swift

+9-3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ struct DownloadsPreferencesUserDefaultsPersistor: DownloadsPreferencesPersistor
6363

6464
final class DownloadsPreferences: ObservableObject {
6565

66+
static let shared = DownloadsPreferences(persistor: DownloadsPreferencesUserDefaultsPersistor())
67+
6668
private func validatedDownloadLocation(_ location: String?) -> URL? {
6769
if let selectedLocation = location,
6870
let selectedLocationURL = URL(string: selectedLocation),
@@ -81,9 +83,13 @@ final class DownloadsPreferences: ObservableObject {
8183

8284
var lastUsedCustomDownloadLocation: URL? {
8385
get {
84-
persistor.lastUsedCustomDownloadLocation?.url
86+
let url = persistor.lastUsedCustomDownloadLocation?.url
87+
var isDirectory: ObjCBool = false
88+
guard let url, FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory), isDirectory.boolValue else {
89+
return nil
90+
}
91+
return url
8592
}
86-
8793
set {
8894
defer {
8995
objectWillChange.send()
@@ -148,7 +154,7 @@ final class DownloadsPreferences: ObservableObject {
148154
}
149155
}
150156

151-
init(persistor: DownloadsPreferencesPersistor = DownloadsPreferencesUserDefaultsPersistor()) {
157+
init(persistor: DownloadsPreferencesPersistor) {
152158
self.persistor = persistor
153159

154160
// Fix the selected download location if it needs it

DuckDuckGo/Preferences/View/PreferencesDownloadsView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ extension Preferences {
5656
#Preview {
5757
VStack {
5858
HStack {
59-
Preferences.DownloadsView(model: DownloadsPreferences())
59+
Preferences.DownloadsView(model: DownloadsPreferences(persistor: DownloadsPreferencesUserDefaultsPersistor()))
6060
.padding()
6161
Spacer()
6262
}.frame(width: 500)

DuckDuckGo/Preferences/View/PreferencesRootView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ enum Preferences {
8484
case .autofill:
8585
AutofillView(model: AutofillPreferencesModel())
8686
case .downloads:
87-
DownloadsView(model: DownloadsPreferences())
87+
DownloadsView(model: .shared)
8888
case .duckPlayer:
8989
DuckPlayerView(model: .shared)
9090
case .about:

DuckDuckGo/Tab/TabExtensions/DownloadsTabExtension.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ final class DownloadsTabExtension: NSObject {
5757

5858
weak var delegate: TabDownloadsDelegate?
5959

60-
init(downloadManager: FileDownloadManagerProtocol, isBurner: Bool, downloadsPreferences: DownloadsPreferences = DownloadsPreferences()) {
60+
init(downloadManager: FileDownloadManagerProtocol, isBurner: Bool, downloadsPreferences: DownloadsPreferences = .shared) {
6161
self.downloadManager = downloadManager
6262
self.isBurner = isBurner
6363
self.downloadsPreferences = downloadsPreferences
@@ -259,7 +259,7 @@ extension DownloadsTabExtension: WKNavigationDelegate {
259259
extension DownloadsTabExtension: DownloadTaskDelegate {
260260

261261
@MainActor
262-
func chooseDestination(suggestedFilename: String?, directoryURL: URL?, fileTypes: [UTType], callback: @escaping @MainActor (URL?, UTType?) -> Void) {
262+
func chooseDestination(suggestedFilename: String?, fileTypes: [UTType], callback: @escaping @MainActor (URL?, UTType?) -> Void) {
263263
savePanelDialogRequest = SavePanelDialogRequest(SavePanelParameters(suggestedFilename: suggestedFilename, fileTypes: fileTypes)) { result in
264264
guard case let .success(.some( (url: url, fileType: fileType) )) = result else {
265265
callback(nil, nil)
@@ -310,7 +310,7 @@ extension DownloadsTabExtension: TabExtension, DownloadsTabExtensionProtocol {
310310
case .prompt:
311311
let fileTypes = UTType(mimeType: mimeType).map { [$0] } ?? []
312312
let url: URL? = await withCheckedContinuation { continuation in
313-
chooseDestination(suggestedFilename: suggestedFilename, directoryURL: nil, fileTypes: fileTypes) { url, _ in
313+
chooseDestination(suggestedFilename: suggestedFilename, fileTypes: fileTypes) { url, _ in
314314
continuation.resume(returning: url)
315315
}
316316
}

DuckDuckGo/Tab/View/BrowserTabViewController.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,11 @@ extension BrowserTabViewController: TabDelegate {
934934
dispatchPrecondition(condition: .onQueue(.main))
935935
guard let window = view.window else { return nil }
936936

937+
let preferences = DownloadsPreferences.shared
938+
let directoryURL = preferences.lastUsedCustomDownloadLocation ?? preferences.effectiveDownloadLocation
937939
let savePanel = NSSavePanel.savePanelWithFileTypeChooser(fileTypes: request.parameters.fileTypes,
938940
suggestedFilename: request.parameters.suggestedFilename,
939-
directoryURL: DownloadsPreferences().effectiveDownloadLocation)
941+
directoryURL: directoryURL)
940942

941943
savePanel.beginSheetModal(for: window) { [request] response in
942944
if case .abort = response {

0 commit comments

Comments
 (0)