ImportedBrowseView.swift (3822B)
1 import SwiftUI 2 import UniformTypeIdentifiers 3 4 struct ImportedBrowseView: View { 5 let onSelected: (String) -> Void 6 7 @Environment(DriveMonitor.self) private var monitor 8 @State private var errorMessage: String? 9 @State private var showingImporter = false 10 11 var body: some View { 12 Group { 13 if !monitor.containerAvailable { 14 ContentUnavailableView { 15 Label("iCloud Drive Unavailable", systemImage: "icloud.slash") 16 } description: { 17 Text("Sign in to iCloud and enable iCloud Drive to import puzzles.") 18 } 19 } else if let root = monitor.root, !root.children.isEmpty { 20 List { 21 ForEach(root.children) { item in 22 DriveItemRow(item: item, onOpen: open) 23 } 24 } 25 } else { 26 ContentUnavailableView { 27 Label("No Imported Puzzles", systemImage: "folder") 28 } description: { 29 Text("Add .xd or .puz files to the Crossmate folder in Files, or tap the import button to bring one in.") 30 } 31 } 32 } 33 .toolbar { 34 ToolbarItem(placement: .primaryAction) { 35 Button { 36 showingImporter = true 37 } label: { 38 Label("Import", systemImage: "square.and.arrow.down") 39 } 40 .disabled(!monitor.containerAvailable) 41 } 42 } 43 .fileImporter( 44 isPresented: $showingImporter, 45 allowedContentTypes: [.xdPuzzle, .acrossLitePuzzle], 46 allowsMultipleSelection: false 47 ) { result in 48 handleImport(result) 49 } 50 .alert( 51 "Couldn't Open Puzzle", 52 isPresented: .init( 53 get: { errorMessage != nil }, 54 set: { if !$0 { errorMessage = nil } } 55 ), 56 presenting: errorMessage 57 ) { _ in 58 Button("OK", role: .cancel) {} 59 } message: { message in 60 Text(message) 61 } 62 } 63 64 private func handleImport(_ result: Result<[URL], Error>) { 65 do { 66 let urls = try result.get() 67 guard let url = urls.first else { return } 68 try monitor.importFile(from: url) 69 } catch { 70 errorMessage = error.localizedDescription 71 } 72 } 73 74 private func open(_ item: DriveItem) { 75 if !item.isDownloaded { 76 monitor.startDownloading(item) 77 errorMessage = "This puzzle is still downloading from iCloud. Try again in a moment." 78 return 79 } 80 do { 81 let source = try monitor.readSource(at: item.url) 82 onSelected(source) 83 } catch { 84 errorMessage = error.localizedDescription 85 } 86 } 87 } 88 89 private struct DriveItemRow: View { 90 let item: DriveItem 91 let onOpen: (DriveItem) -> Void 92 93 var body: some View { 94 if item.isDirectory { 95 DisclosureGroup { 96 ForEach(item.children) { child in 97 DriveItemRow(item: child, onOpen: onOpen) 98 } 99 } label: { 100 Label(item.name, systemImage: "folder") 101 } 102 } else { 103 Button { 104 onOpen(item) 105 } label: { 106 HStack { 107 Label(item.url.lastPathComponent, systemImage: "doc.text") 108 .foregroundStyle(.primary) 109 Spacer() 110 if !item.isDownloaded { 111 Image(systemName: "icloud.and.arrow.down") 112 .foregroundStyle(.secondary) 113 } 114 } 115 } 116 } 117 } 118 }