Skip to content

Commit

Permalink
Improve download manager (#3158)
Browse files Browse the repository at this point in the history
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
![Simulator Screenshot - iPhone 16 - 2024-11-14 at 11 54
53](https://github.com/user-attachments/assets/65483b7e-31d6-46f2-abf1-3cf26856d9fc)

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
  • Loading branch information
bgoncal authored Nov 14, 2024
1 parent abc06d3 commit 5da88f3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
29 changes: 23 additions & 6 deletions Sources/App/WebView/DownloadManager/DownloadManagerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct DownloadManagerView: View {
VStack(spacing: .zero) {
HStack {
Button(action: {
viewModel.cancelDownload()
viewModel.deleteFile()
dismiss()
}, label: {
Expand All @@ -25,6 +26,7 @@ struct DownloadManagerView: View {
.gray.opacity(0.5)
)
})
.buttonStyle(.plain)
.frame(maxWidth: .infinity, alignment: .trailing)
.padding()
}
Expand All @@ -41,9 +43,16 @@ struct DownloadManagerView: View {
Text(L10n.DownloadManager.Downloading.title)
.font(.title.bold())
fileCard
Text(viewModel.progress)
.animation(.easeInOut(duration: 1), value: viewModel.progress)
}
Spacer()
}
.onChange(of: viewModel.finished) { _, newValue in
if newValue, Current.isCatalyst {
UIApplication.shared.open(AppConstants.DownloadsDirectory)
}
}
}

private var successView: some View {
Expand All @@ -58,12 +67,20 @@ struct DownloadManagerView: View {
Text(L10n.DownloadManager.Finished.title)
.font(.title.bold())
if let url = viewModel.lastURLCreated {
ShareLink(viewModel.fileName, item: url)
.padding()
.foregroundStyle(.white)
.background(Color.asset(Asset.Colors.haPrimary))
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding()
if Current.isCatalyst {
Button {
UIApplication.shared.open(AppConstants.DownloadsDirectory)
} label: {
Label(viewModel.fileName, systemSymbol: .folder)
}
} else {
ShareLink(viewModel.fileName, item: url)
.padding()
.foregroundStyle(.white)
.background(Color.asset(Asset.Colors.haPrimary))
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding()
}
}
}
}
Expand Down
26 changes: 23 additions & 3 deletions Sources/App/WebView/DownloadManager/DownloadManagerViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ final class DownloadManagerViewModel: NSObject, ObservableObject {
@Published var finished: Bool = false
@Published var failed: Bool = false
@Published var errorMessage: String = ""
@Published var progress: String = ""
@Published var lastURLCreated: URL?

private var progressObservation: NSKeyValueObservation?
private var lastDownload: WKDownload?

func deleteFile() {
if let url = lastURLCreated {
// Guarantee to delete file before leaving screen
Expand All @@ -20,6 +24,18 @@ final class DownloadManagerViewModel: NSObject, ObservableObject {
}
}
}

func cancelDownload() {
progressObservation?.invalidate()
lastDownload?.cancel()
}

private func bytesToMBString(_ bytes: Int64) -> String {
let formatter = ByteCountFormatter()
formatter.allowedUnits = [.useMB]
formatter.countStyle = .file
return formatter.string(fromByteCount: bytes)
}
}

extension DownloadManagerViewModel: WKDownloadDelegate {
Expand All @@ -28,18 +44,22 @@ extension DownloadManagerViewModel: WKDownloadDelegate {
decideDestinationUsing response: URLResponse,
suggestedFilename: String
) async -> URL? {
let urls = FileManager.default.urls(for: .cachesDirectory, in: .allDomainsMask)
lastDownload = download
let name = suggestedFilename.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "Unknown"
fileName = name
if let url = URL(string: name, relativeTo: urls[0]) {
if let url = URL(string: name, relativeTo: AppConstants.DownloadsDirectory) {
lastURLCreated = url
// Guarantee file does not exist, otherwise download will fail
do {
try FileManager.default.removeItem(at: url)
} catch {
Current.Log.error("Failed to remove file for download manager at \(url), error: \(error)")
}

progressObservation?.invalidate()
progressObservation = download.progress.observe(\.completedUnitCount) { [weak self] progress, _ in
guard let self else { return }
self.progress = bytesToMBString(progress.completedUnitCount)
}
return url
} else {
return nil
Expand Down
19 changes: 19 additions & 0 deletions Sources/Shared/Environment/AppConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,25 @@ public enum AppConstants {
return directoryURL
}

public static var DownloadsDirectory: URL {
let fileManager = FileManager.default
let directoryURL = FileManager.default.urls(for: .cachesDirectory, in: .allDomainsMask).first!
.appendingPathComponent(
"Downloads",
isDirectory: true
)

if !fileManager.fileExists(atPath: directoryURL.path) {
do {
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
} catch {
fatalError("Error while attempting to create downloads path URL: \(error)")
}
}

return directoryURL
}

/// An initialized Keychain from KeychainAccess.
public static var Keychain: KeychainAccess.Keychain {
KeychainAccess.Keychain(service: BundleID)
Expand Down

0 comments on commit 5da88f3

Please sign in to comment.