diff --git a/Core/Core/Common/Extensions/PDFKit/PDFDocumentExtensions.swift b/Core/Core/Common/Extensions/PDFKit/PDFDocumentExtensions.swift new file mode 100644 index 0000000000..e436203782 --- /dev/null +++ b/Core/Core/Common/Extensions/PDFKit/PDFDocumentExtensions.swift @@ -0,0 +1,39 @@ +// +// This file is part of Canvas. +// Copyright (C) 2025-present Instructure, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +import PDFKit + +extension PDFDocument { + + @discardableResult + public func write(to url: URL? = nil, name: String? = nil) throws -> URL { + let directory = url ?? URL.Directories.temporary.appendingPathComponent("Documents", isDirectory: true) + let name = name ?? String(Clock.now.timeIntervalSince1970) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil) + var url = directory.appendingPathComponent(name, isDirectory: false) + url = url.pathExtension != "pdf" ? url.appendingPathExtension("pdf") : url + guard let data = dataRepresentation() else { + throw NSError.instructureError(String(localized: "Failed to save pdf", bundle: .core)) + } + if FileManager.default.fileExists(atPath: url.path) { + try FileManager.default.removeItem(at: url) + } + try data.write(to: url) + return url + } +} diff --git a/Core/Core/Features/Files/Model/Entities/UTI.swift b/Core/Core/Features/Files/Model/Entities/UTI.swift index 9c1856441f..628700608b 100644 --- a/Core/Core/Features/Files/Model/Entities/UTI.swift +++ b/Core/Core/Features/Files/Model/Entities/UTI.swift @@ -131,6 +131,9 @@ public struct UTI: Equatable, Hashable { public var isImage: Bool { return uttype?.conforms(to: .image) ?? false } + public var isPdf: Bool { + return uttype?.conforms(to: .pdf) ?? false + } public var isAudio: Bool { return uttype?.conforms(to: .audio) ?? false diff --git a/Core/Core/Features/Files/View/FilePicker/FilePickerViewController.swift b/Core/Core/Features/Files/View/FilePicker/FilePickerViewController.swift index 728acd2f7a..f6ee83eafc 100644 --- a/Core/Core/Features/Files/View/FilePicker/FilePickerViewController.swift +++ b/Core/Core/Features/Files/View/FilePicker/FilePickerViewController.swift @@ -20,6 +20,7 @@ import Combine import UIKit import MobileCoreServices import VisionKit +import PDFKit import UniformTypeIdentifiers public enum FilePickerSource: Int, CaseIterable { @@ -377,13 +378,29 @@ extension FilePickerViewController: UITableViewDelegate, UITableViewDataSource { extension FilePickerViewController: VNDocumentCameraViewControllerDelegate { public func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) { controller.dismiss(animated: true) - for i in 0..