import SwiftUI import SwiftData import Storage import BookParser struct LibraryView: View { @Environment(\.modelContext) private var modelContext @Query(sort: \StoredBook.lastRead, order: .reverse) private var books: [StoredBook] @State private var showFileImporter = false private var bookStore: BookStore { BookStore( modelContainer: modelContext.container, documentsDirectory: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] ) } var body: some View { NavigationStack { List { ForEach(books) { book in NavigationLink(value: book) { VStack(alignment: .leading) { Text(book.title) .font(.headline) if let author = book.author { Text(author) .font(.subheadline) .foregroundStyle(.secondary) } } } } .onDelete(perform: deleteBooks) } .navigationTitle("Library") .navigationDestination(for: StoredBook.self) { storedBook in ReaderView(storedBook: storedBook) } .toolbar { Button("Import", systemImage: "plus") { showFileImporter = true } } .fileImporter( isPresented: $showFileImporter, allowedContentTypes: [.epub, .plainText], allowsMultipleSelection: false ) { result in handleImport(result) } } } private func handleImport(_ result: Result<[URL], Error>) { guard case .success(let urls) = result, let url = urls.first else { return } guard url.startAccessingSecurityScopedResource() else { return } defer { url.stopAccessingSecurityScopedResource() } Task { do { let parsed = try BookParser.parse(url: url) try bookStore.importBook(from: url, title: parsed.title, author: parsed.author) } catch { print("Import failed: \(error)") } } } private func deleteBooks(at offsets: IndexSet) { for index in offsets { try? bookStore.deleteBook(books[index]) } } }