diff --git a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift index c010b6d80..9a6789b1c 100644 --- a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift +++ b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift @@ -8,6 +8,11 @@ import Utils import Services struct PDFViewer: View { + final class PDFStateObject: ObservableObject { + @Published var document: Document? + @Published var coordinator: PDFViewCoordinator? + } + @EnvironmentObject var dataService: DataService struct ShareLink: Identifiable { @@ -16,117 +21,124 @@ import Utils } let pdfURL: URL - let document: Document let viewModel: PDFViewerViewModel - let coordinator: PDFViewCoordinator + + @StateObject var pdfStateObject = PDFStateObject() @State var readerView: Bool = false @State private var shareLink: ShareLink? init(remoteURL: URL, viewModel: PDFViewerViewModel) { self.pdfURL = viewModel.dataURL(remoteURL: remoteURL) self.viewModel = viewModel - self.document = HighlightedDocument(url: pdfURL, viewModel: viewModel) - self.coordinator = PDFViewCoordinator(document: document, viewModel: viewModel) } var body: some View { - PDFView(document: document) - .useParentNavigationBar(true) - .updateConfiguration { builder in - builder.textSelectionShouldSnapToWord = true - } - .updateControllerConfiguration { controller in - print("document is valid", document.isValid) - coordinator.setController(controller: controller, dataService: dataService) - - // Disable the Document Editor - controller.navigationItem.setRightBarButtonItems( - [controller.thumbnailsButtonItem], - for: .thumbnails, - animated: false - ) - - let barButtonItems = [ - UIBarButtonItem( - image: UIImage(systemName: "textformat"), - style: .plain, - target: controller.settingsButtonItem.target, - action: controller.settingsButtonItem.action - ), - UIBarButtonItem( - image: UIImage(systemName: "book"), - style: .plain, - target: coordinator, - action: #selector(PDFViewCoordinator.toggleReaderView) - ), - UIBarButtonItem( - image: UIImage(systemName: "magnifyingglass"), - style: .plain, - target: controller.searchButtonItem.target, - action: controller.searchButtonItem.action - ) - ] - - document.areAnnotationsEnabled = true - - coordinator.viewer = self - - if viewModel.pdfItem.readingProgressAnchor > 0 { - let pageIndex = UInt(viewModel.pdfItem.readingProgressAnchor) - controller.setPageIndex(pageIndex, animated: false) + if let document = pdfStateObject.document, let coordinator = pdfStateObject.coordinator { + PDFView(document: document) + .useParentNavigationBar(true) + .updateConfiguration { builder in + builder.textSelectionShouldSnapToWord = true } + .updateControllerConfiguration { controller in + print("document is valid", document.isValid) + coordinator.setController(controller: controller, dataService: dataService) - controller.navigationItem.setRightBarButtonItems(barButtonItems, for: .document, animated: false) - } - .onShouldShowMenuItemsForSelectedText(perform: { pageView, menuItems, selectedText in - let copy = menuItems.first(where: { $0.identifier == "Copy" }) - let highlight = MenuItem(title: "Highlight", block: { - _ = self.coordinator.highlightSelection( - pageView: pageView, - selectedText: selectedText, - dataService: dataService + // Disable the Document Editor + controller.navigationItem.setRightBarButtonItems( + [controller.thumbnailsButtonItem], + for: .thumbnails, + animated: false ) - }) + + let barButtonItems = [ + UIBarButtonItem( + image: UIImage(systemName: "textformat"), + style: .plain, + target: controller.settingsButtonItem.target, + action: controller.settingsButtonItem.action + ), + UIBarButtonItem( + image: UIImage(systemName: "book"), + style: .plain, + target: coordinator, + action: #selector(PDFViewCoordinator.toggleReaderView) + ), + UIBarButtonItem( + image: UIImage(systemName: "magnifyingglass"), + style: .plain, + target: controller.searchButtonItem.target, + action: controller.searchButtonItem.action + ) + ] + + document.areAnnotationsEnabled = true + + coordinator.viewer = self + + if viewModel.pdfItem.readingProgressAnchor > 0 { + let pageIndex = UInt(viewModel.pdfItem.readingProgressAnchor) + controller.setPageIndex(pageIndex, animated: false) + } + + controller.navigationItem.setRightBarButtonItems(barButtonItems, for: .document, animated: false) + } + .onShouldShowMenuItemsForSelectedText(perform: { pageView, menuItems, selectedText in + let copy = menuItems.first(where: { $0.identifier == "Copy" }) + let highlight = MenuItem(title: "Highlight", block: { + _ = coordinator.highlightSelection( + pageView: pageView, + selectedText: selectedText, + dataService: dataService + ) + }) // let share = MenuItem(title: "Share", block: { // let shortId = self.coordinator.highlightSelection(pageView: pageView, selectedText: selectedText) // if let shareURL = viewModel.highlightShareURL(shortId: shortId) { // shareLink = ShareLink(id: UUID(), url: shareURL) // } // }) - return [copy, highlight /* , share */ ].compactMap { $0 } - }) - .onShouldShowMenuItemsForSelectedAnnotations(perform: { _, menuItems, annotations in - var result = [MenuItem]() - if let copy = menuItems.first(where: { $0.identifier == "Copy" }) { - result.append(copy) - } - - let remove = MenuItem(title: "Remove", block: { - self.coordinator.remove(dataService: dataService, annotations: annotations) + return [copy, highlight /* , share */ ].compactMap { $0 } }) - result.append(remove) + .onShouldShowMenuItemsForSelectedAnnotations(perform: { _, menuItems, annotations in + var result = [MenuItem]() + if let copy = menuItems.first(where: { $0.identifier == "Copy" }) { + result.append(copy) + } - let highlights = annotations?.compactMap { $0 as? HighlightAnnotation } - let shortId = highlights.flatMap { coordinator.shortHighlightIds($0).first } - - if let shortId = shortId, FeatureFlag.enableShareButton { - let share = MenuItem(title: "Share", block: { - if let shareURL = viewModel.highlightShareURL(dataService: dataService, shortId: shortId) { - shareLink = ShareLink(id: UUID(), url: shareURL) - } + let remove = MenuItem(title: "Remove", block: { + coordinator.remove(dataService: dataService, annotations: annotations) }) - result.append(share) - } + result.append(remove) - return result - }) - .fullScreenCover(isPresented: $readerView, content: { - PDFReaderViewController(document: document) - }) - .accentColor(Color(red: 255 / 255.0, green: 234 / 255.0, blue: 159 / 255.0)) - .sheet(item: $shareLink) { - ShareSheet(activityItems: [$0.url]) - } + let highlights = annotations?.compactMap { $0 as? HighlightAnnotation } + let shortId = highlights.flatMap { coordinator.shortHighlightIds($0).first } + + if let shortId = shortId, FeatureFlag.enableShareButton { + let share = MenuItem(title: "Share", block: { + if let shareURL = viewModel.highlightShareURL(dataService: dataService, shortId: shortId) { + shareLink = ShareLink(id: UUID(), url: shareURL) + } + }) + result.append(share) + } + + return result + }) + .fullScreenCover(isPresented: $readerView, content: { + PDFReaderViewController(document: document) + }) + .accentColor(Color(red: 255 / 255.0, green: 234 / 255.0, blue: 159 / 255.0)) + .sheet(item: $shareLink) { + ShareSheet(activityItems: [$0.url]) + } + } else { + Text("Loading...") + .task { + let document = HighlightedDocument(url: pdfURL, viewModel: viewModel) + pdfStateObject.document = document + pdfStateObject.coordinator = PDFViewCoordinator(document: document, viewModel: viewModel) + } + } } class PDFViewCoordinator: NSObject, PDFDocumentViewControllerDelegate, PDFViewControllerDelegate { diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift b/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift index a92404771..99ee55106 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift @@ -11,7 +11,12 @@ struct FeedCardNavigationLink: View { @ObservedObject var viewModel: HomeFeedViewModel var body: some View { - let destination = LinkItemDetailView(viewModel: LinkItemDetailViewModel(item: item, pdfItem: PDFItem.make(item: item))) + let destination = LinkItemDetailView( + viewModel: LinkItemDetailViewModel( + linkedItemObjectID: item.objectID, + dataService: dataService + ) + ) #if os(iOS) let modifiedDestination = destination .navigationTitle("") @@ -50,7 +55,12 @@ struct GridCardNavigationLink: View { @ObservedObject var viewModel: HomeFeedViewModel var body: some View { - let destination = LinkItemDetailView(viewModel: LinkItemDetailViewModel(item: item, pdfItem: PDFItem.make(item: item))) + let destination = LinkItemDetailView( + viewModel: LinkItemDetailViewModel( + linkedItemObjectID: item.objectID, + dataService: dataService + ) + ) #if os(iOS) let modifiedDestination = destination .navigationTitle("") diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift index fb39218e2..dea6b1963 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift @@ -1,4 +1,5 @@ import Combine +import CoreData import Models import Services import SwiftUI @@ -12,9 +13,14 @@ import Views var subscriptions = Set() - init(item: LinkedItem?, pdfItem: PDFItem?) { - self.item = item - self.pdfItem = pdfItem + init(linkedItemObjectID: NSManagedObjectID, dataService: DataService) { + if let linkedItem = dataService.viewContext.object(with: linkedItemObjectID) as? LinkedItem { + self.pdfItem = PDFItem.make(item: linkedItem) + self.item = linkedItem + } else { + self.pdfItem = nil + self.item = nil + } } func handleArchiveAction(dataService: DataService) {