From a1e80ab4dcee50a4f036fe1a208ba01ba3081c13 Mon Sep 17 00:00:00 2001 From: hengyu Date: Tue, 5 Dec 2023 17:15:41 +0800 Subject: [PATCH] Support for visionOS platform --- Package.swift | 2 +- .../FeedbackViewController.swift | 18 +++++++++------ Sources/FeedbackSwift/FeedbackWireframe.swift | 5 ++++- Sources/FeedbackSwift/Functions.swift | 22 ++++++++++++++----- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Package.swift b/Package.swift index f135f25..527a05f 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "FeedbackSwift", defaultLocalization: "en", - platforms: [.iOS(.v14), .macCatalyst(.v14)], + platforms: [.iOS(.v14), .macCatalyst(.v14), .visionOS(.v1)], products: [ .library(name: "FeedbackSwift", targets: ["FeedbackSwift"]) ], diff --git a/Sources/FeedbackSwift/FeedbackViewController.swift b/Sources/FeedbackSwift/FeedbackViewController.swift index 46d042b..3f26360 100644 --- a/Sources/FeedbackSwift/FeedbackViewController.swift +++ b/Sources/FeedbackSwift/FeedbackViewController.swift @@ -71,7 +71,9 @@ open class FeedbackViewController: UITableViewController { tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 44.0 + #if os(iOS) tableView.keyboardDismissMode = .onDrag + #endif tableView.cellLayoutMarginsFollowReadableWidth = true cellFactories.forEach(tableView.register(with:)) @@ -284,13 +286,15 @@ extension FeedbackViewController: UIImagePickerControllerDelegate, UINavigationC _ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any] ) { - switch getMediaFromImagePickerInfo(info) { - case let media?: - feedbackEditingService.update(attachmentMedia: media) - wireframe.dismiss(completion: .none) - case _: - wireframe.dismiss(completion: .none) - wireframe.showUnknownErrorAlert() + Task { + switch await getMediaFromImagePickerInfo(info) { + case let media?: + feedbackEditingService.update(attachmentMedia: media) + wireframe.dismiss(completion: .none) + case _: + wireframe.dismiss(completion: .none) + wireframe.showUnknownErrorAlert() + } } } diff --git a/Sources/FeedbackSwift/FeedbackWireframe.swift b/Sources/FeedbackSwift/FeedbackWireframe.swift index 68cf57f..d86e825 100644 --- a/Sources/FeedbackSwift/FeedbackWireframe.swift +++ b/Sources/FeedbackSwift/FeedbackWireframe.swift @@ -6,6 +6,7 @@ import UIKit import MobileCoreServices import MessageUI +import UniformTypeIdentifiers protocol FeedbackWireframeProtocol { func showTopicsView(with service: FeedbackEditingServiceProtocol) @@ -94,6 +95,7 @@ extension FeedbackWireframe: FeedbackWireframeProtocol { } ) } + #if os(iOS) if UIImagePickerController.isSourceTypeAvailable(.camera) { alertController.addAction( UIAlertAction( @@ -108,6 +110,7 @@ extension FeedbackWireframe: FeedbackWireframeProtocol { } }) } + #endif if let deleteAction { alertController.addAction( @@ -188,7 +191,7 @@ private extension FeedbackWireframe { func showImagePicker(sourceType: UIImagePickerController.SourceType) { let imagePicker = UIImagePickerController() imagePicker.sourceType = sourceType - imagePicker.mediaTypes = [kUTTypeImage as String, kUTTypeMovie as String] + imagePicker.mediaTypes = [UTType.image.identifier, UTType.movie.identifier] imagePicker.allowsEditing = false imagePicker.delegate = imagePickerDelegate imagePicker.modalPresentationStyle = .formSheet diff --git a/Sources/FeedbackSwift/Functions.swift b/Sources/FeedbackSwift/Functions.swift index cc6b852..02e9bb8 100644 --- a/Sources/FeedbackSwift/Functions.swift +++ b/Sources/FeedbackSwift/Functions.swift @@ -26,7 +26,7 @@ func localized(_ key: String) -> String { return key } -func getMediaFromImagePickerInfo(_ info: [UIImagePickerController.InfoKey: Any]) -> Media? { +func getMediaFromImagePickerInfo(_ info: [UIImagePickerController.InfoKey: Any]) async -> Media? { let imageType: String let movieType: String if #available(iOS 14.0, macCatalyst 14.0, tvOS 14.0, watchOS 7.0, macOS 11.0, *) { @@ -43,19 +43,29 @@ func getMediaFromImagePickerInfo(_ info: [UIImagePickerController.InfoKey: Any]) return .image(image) case movieType?: guard let url = info[.mediaURL] as? URL else { return nil } - return getMediaFromURL(url) + let image = try? await getMediaFromURL(url) + return image default: return nil } } -func getMediaFromURL(_ url: URL) -> Media? { +func getMediaFromURL(_ url: URL) async throws -> Media { let asset = AVURLAsset(url: url) let generator = AVAssetImageGenerator(asset: asset) generator.appliesPreferredTrackTransform = true let time = CMTimeMake(value: 1, timescale: 1) - guard let cgImage = try? generator.copyCGImage(at: time, actualTime: nil) - else { return nil } - return .video(UIImage(cgImage: cgImage), url) + #if os(visionOS) + let image = try await generator.image(at: time) + return Media.video(.init(cgImage: image.image), url) + #else + if #available(iOS 16.0, macCatalyst 16.0, *) { + let image = try await generator.image(at: time) + return Media.video(.init(cgImage: image.image), url) + } else { + let image = try generator.copyCGImage(at: time, actualTime: nil) + return .video(UIImage(cgImage: image), url) + } + #endif } func push(_ item: Item?) -> (((Item) -> Void) -> Void)? {