From f336546343d4ef48381f649a1ea4f2e5fd55830c Mon Sep 17 00:00:00 2001 From: Alexey Bukhtin Date: Thu, 5 Oct 2023 01:54:25 +0200 Subject: [PATCH] Demo: Add a folder downloading --- Demo/Hubble/ImageView.swift | 10 ++++-- Demo/Hubble/ImagesView.swift | 69 +++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/Demo/Hubble/ImageView.swift b/Demo/Hubble/ImageView.swift index 9126fb2..d63a694 100644 --- a/Demo/Hubble/ImageView.swift +++ b/Demo/Hubble/ImageView.swift @@ -51,8 +51,12 @@ struct ImageView: View { .symbolRenderingMode(.multicolor) .padding(.horizontal) } else { - ProgressView(value: progress) - .padding(.horizontal) + if progress < 1 { + ProgressView(value: progress) + .padding(.horizontal) + } else { + Text("Decompressing...") + } } } .navigationTitle(entry?.fileName ?? "") @@ -60,7 +64,7 @@ struct ImageView: View { guard let entry, let url else { return } do { - let data = try await URLSession(configuration: .ephemeral) + let data = try await URLSession(configuration: .default) .zipEntryData( entry, from: url, diff --git a/Demo/Hubble/ImagesView.swift b/Demo/Hubble/ImagesView.swift index 1e171f5..1a7bdaa 100644 --- a/Demo/Hubble/ImagesView.swift +++ b/Demo/Hubble/ImagesView.swift @@ -5,11 +5,15 @@ struct ImagesView: View { let title: String let url: URL + private let urlSession = URLSession(configuration: .default) @State private var entries = [ZIPEntry]() @State private var rootFolder: ZIPFolder @State private var hoveredEntry: ZIPEntry? @State private var isLoading = false @State private var error: String? + @State private var progress: Double = 0 + @State private var progressFolderId: UUID? + @State private var folderDownloadingTask: Task<(), Error>? init(title: String, url: URL, rootFolder: ZIPFolder? = nil) { self.title = title @@ -39,7 +43,7 @@ struct ImagesView: View { do { isLoading = true - entries = try await URLSession(configuration: .ephemeral).zipEntries(from: url) + entries = try await urlSession.zipEntries(from: url) rootFolder = entries.rootFolder() } catch let zipError as ZIPError { self.error = zipError.localizedDescription @@ -77,21 +81,62 @@ struct ImagesView: View { NavigationLink { ImagesView(title: folder.name, url: url, rootFolder: folder) } label: { - HStack(spacing: 16) { - Image(systemName: "folder") - - VStack(alignment: .leading, spacing: 4) { - Text(folder.name) - folderMetaInfo(folder) + ZStack(alignment: .bottom) { + HStack(spacing: 16) { + Image(systemName: "folder") + + VStack(alignment: .leading, spacing: 4) { + Text(folder.name) + folderMetaInfo(folder) + } + + Spacer() + + Text(ByteCountFormatter.appFormatter.string(fromByteCount: folder.compressedSize)) + .foregroundColor(.secondary) + .font(.caption) } - Spacer() - - Text(ByteCountFormatter.appFormatter.string(fromByteCount: folder.compressedSize)) - .foregroundColor(.secondary) - .font(.caption) + if progressFolderId == folder.id { + ProgressView(value: progress) + .offset(y: 10) + } } } + .swipeActions(edge: .trailing) { + Button(action: { + folderDownloadingTask?.cancel() + folderDownloadingTask = Task { + progressFolderId = folder.id + + do { + _ = try await urlSession.zipFolderData( + folder, from: url, + progress: .init(callback: { value in + Task { @MainActor in + self.progress = value + + if value == 1 { + self.progressFolderId = nil + } + } + }) + ) + } catch let zipError as ZIPError { + self.error = zipError.localizedDescription + print("💥 ImagesView:", zipError) + } catch { + self.error = error.localizedDescription + print("💥 ImagesView:", error) + } + } + }, label: { + Image(systemName: "arrow.down.circle.fill") + }) + } + .onDisappear { + folderDownloadingTask?.cancel() + } } @ViewBuilder