this repo has no description

Warnings and remove JSON view

+20 -69
+12 -6
AtProtoBackup/AccountDetailView.swift
··· 18 .fontWeight(.bold) 19 20 AccountInfoSection(account: account) 21 - 22 DownloadSection(account: account, downloadManager: downloadManager) 23 - 24 - JSONResponseSection(jsonData: account.jsonResponse) 25 - 26 Spacer() 27 } 28 .padding() ··· 32 33 struct AccountInfoSection: View { 34 let account: Account 35 - 36 var body: some View { 37 VStack(alignment: .leading, spacing: 8) { 38 HStack { ··· 40 .fontWeight(.semibold) 41 Text(account.handle) 42 } 43 - 44 HStack { 45 Text("DID:") 46 .fontWeight(.semibold) 47 Text(account.did) 48 .lineLimit(1) 49 .truncationMode(.middle) 50 } 51 } 52 }
··· 18 .fontWeight(.bold) 19 20 AccountInfoSection(account: account) 21 + 22 DownloadSection(account: account, downloadManager: downloadManager) 23 + 24 Spacer() 25 } 26 .padding() ··· 30 31 struct AccountInfoSection: View { 32 let account: Account 33 + 34 var body: some View { 35 VStack(alignment: .leading, spacing: 8) { 36 HStack { ··· 38 .fontWeight(.semibold) 39 Text(account.handle) 40 } 41 + 42 HStack { 43 Text("DID:") 44 .fontWeight(.semibold) 45 Text(account.did) 46 .lineLimit(1) 47 .truncationMode(.middle) 48 + } 49 + 50 + HStack { 51 + Text("PDS:") 52 + .fontWeight(.semibold) 53 + Text(account.pds) 54 + .lineLimit(1) 55 + .truncationMode(.tail) 56 } 57 } 58 }
+3 -4
AtProtoBackup/AppDelegate.swift
··· 27 28 func applicationDidEnterBackground(_ application: UIApplication) { 29 // Request background processing time 30 - var backgroundTask: UIBackgroundTaskIdentifier = .invalid 31 - backgroundTask = application.beginBackgroundTask { 32 - application.endBackgroundTask(backgroundTask) 33 } 34 - 35 // You get ~30 seconds to update Live Activities 36 Task { 37 // Note: We could update Live Activities here but we don't have
··· 27 28 func applicationDidEnterBackground(_ application: UIApplication) { 29 // Request background processing time 30 + let backgroundTask = application.beginBackgroundTask { 31 + // Expiration handler - called if we run out of time 32 } 33 + 34 // You get ~30 seconds to update Live Activities 35 Task { 36 // Note: We could update Live Activities here but we don't have
+5 -19
AtProtoBackup/BlobDownloader.swift
··· 105 } 106 } 107 108 - func urlSession( 109 - _ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, 110 - completionHandler: @escaping (URLSession.ResponseDisposition) -> Void 111 - ) { 112 - // Store response for download tasks 113 - if let downloadTask = dataTask as? URLSessionDownloadTask { 114 - completionQueue.sync { 115 - taskResponses[downloadTask] = response 116 - } 117 - } 118 - completionHandler(.allow) 119 - } 120 - 121 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 122 { 123 completionQueue.sync { ··· 169 170 // Initialize and restore any pending background downloads 171 public init() { 172 - // Force creation of the session to reconnect with any existing downloads 173 - _ = backgroundSession 174 } 175 176 // Static method to handle background session events (call from AppDelegate) ··· 255 // Create all download tasks immediately so they continue in background 256 var results: [String: URL] = [:] 257 var newDownloadCount = 0 258 - let resultsLock = NSLock() 259 260 // Semaphore to limit concurrent downloads 261 let semaphore = AsyncSemaphore(value: maxConcurrent) ··· 290 var downloadedCount = 0 291 for try await result in group { 292 if let (cid, url, wasNewDownload) = result { 293 - resultsLock.lock() 294 results[cid] = url 295 downloadedCount += 1 296 if wasNewDownload { 297 newDownloadCount += 1 298 } 299 - resultsLock.unlock() 300 301 progressHandler?(downloadedCount, cids.count) 302 } ··· 628 ) 629 630 if let fileEnumerator = fileEnumerator { 631 - for case let fileURL as URL in fileEnumerator { 632 let fileName = fileURL.deletingPathExtension().lastPathComponent 633 if fileName == cid { 634 print("Blob \(cid) already exists at \(fileURL.path), skipping download")
··· 105 } 106 } 107 108 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 109 { 110 completionQueue.sync { ··· 156 157 // Initialize and restore any pending background downloads 158 public init() { 159 + // Note: backgroundSession will be lazily created on first use 160 + // which will automatically reconnect with any existing downloads 161 } 162 163 // Static method to handle background session events (call from AppDelegate) ··· 242 // Create all download tasks immediately so they continue in background 243 var results: [String: URL] = [:] 244 var newDownloadCount = 0 245 246 // Semaphore to limit concurrent downloads 247 let semaphore = AsyncSemaphore(value: maxConcurrent) ··· 276 var downloadedCount = 0 277 for try await result in group { 278 if let (cid, url, wasNewDownload) = result { 279 results[cid] = url 280 downloadedCount += 1 281 if wasNewDownload { 282 newDownloadCount += 1 283 } 284 285 progressHandler?(downloadedCount, cids.count) 286 } ··· 612 ) 613 614 if let fileEnumerator = fileEnumerator { 615 + // Convert to array to avoid async iteration issues 616 + let files = fileEnumerator.allObjects.compactMap { $0 as? URL } 617 + for fileURL in files { 618 let fileName = fileURL.deletingPathExtension().lastPathComponent 619 if fileName == cid { 620 print("Blob \(cid) already exists at \(fileURL.path), skipping download")
-40
AtProtoBackup/JSONResponseSection.swift
··· 1 - // 2 - // JSONResponseSection.swift 3 - // AtProtoBackup 4 - // 5 - // Created by Corey Alexander on 8/25/25. 6 - // 7 - 8 - import SwiftUI 9 - 10 - struct JSONResponseSection: View { 11 - let jsonData: Data? 12 - 13 - var body: some View { 14 - if let jsonData = jsonData { 15 - VStack(alignment: .leading, spacing: 8) { 16 - Text("JSON Response:") 17 - .font(.headline) 18 - 19 - ScrollView { 20 - if let jsonObject = try? JSONSerialization.jsonObject(with: jsonData), 21 - let prettyData = try? JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted]), 22 - let prettyString = String(data: prettyData, encoding: .utf8) { 23 - Text(prettyString) 24 - .font(.system(.body, design: .monospaced)) 25 - .textSelection(.enabled) 26 - .padding() 27 - .background(Color.gray.opacity(0.1)) 28 - .cornerRadius(8) 29 - } else { 30 - Text("Unable to decode JSON data") 31 - .foregroundColor(.secondary) 32 - } 33 - } 34 - } 35 - } else { 36 - Text("No JSON response available") 37 - .foregroundColor(.secondary) 38 - } 39 - } 40 - }
···