From b7800ca4df4bf69e1903373c8a68a83016b0941b Mon Sep 17 00:00:00 2001 From: Shaps Benkau Date: Mon, 3 Oct 2022 14:58:31 +0100 Subject: [PATCH] Introduces a basic ShareLink implementation --- .../Multiple Items/Items+Label+Preview.swift | 74 +++++++-------- .../Multiple Items/Items+Preview.swift | 50 +++++------ .../Shared/ShareLink/ShareLink.swift | 82 ++++++++--------- .../Shared/ShareLink/ShareSheet.swift | 6 +- .../Single Item/Item+Label+Preview.swift | 68 +++++++------- .../ShareLink/Single Item/Item+Preview.swift | 50 +++++------ .../{Shareable.swift => Transferable.swift} | 16 ++-- .../Shared/Transferable/_Transferable.swift | 89 +++++++++++++++++++ 8 files changed, 264 insertions(+), 171 deletions(-) rename Sources/SwiftUIBackports/Shared/ShareLink/{Shareable.swift => Transferable.swift} (85%) create mode 100644 Sources/SwiftUIBackports/Shared/Transferable/_Transferable.swift diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Label+Preview.swift b/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Label+Preview.swift index 24283999..50c9b013 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Label+Preview.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Label+Preview.swift @@ -1,37 +1,37 @@ -import SwiftUI - -@available(iOS, deprecated: 16) -@available(macOS, deprecated: 13) -@available(watchOS, deprecated: 9) -@available(tvOS, unavailable) -public extension Backport.ShareLink where Wrapped == Any { - init(_ title: S, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) - where Data.Element: BackportTransferable, Label == DefaultShareLinkLabel - { - self.label = .init(title) - self.data = items - self.subject = subject - self.message = message - self.preview = preview - } - - init(_ titleKey: LocalizedStringKey, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) - where Data.Element: BackportTransferable, Label == DefaultShareLinkLabel - { - self.label = .init(titleKey) - self.data = items - self.subject = subject - self.message = message - self.preview = preview - } - - init(_ title: Text, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) - where Data.Element: BackportTransferable, Label == DefaultShareLinkLabel - { - self.label = .init(title) - self.data = items - self.subject = subject - self.message = message - self.preview = preview - } -} +//import SwiftUI +// +//@available(iOS, deprecated: 16) +//@available(macOS, deprecated: 13) +//@available(watchOS, deprecated: 9) +//@available(tvOS, unavailable) +//public extension Backport.ShareLink where Wrapped == Any { +// init(_ title: S, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) +// where Data.Element: Shareable, Label == DefaultShareLinkLabel +// { +// self.label = .init(title) +// self.data = items +// self.subject = subject +// self.message = message +// self.preview = preview +// } +// +// init(_ titleKey: LocalizedStringKey, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) +// where Data.Element: Shareable, Label == DefaultShareLinkLabel +// { +// self.label = .init(titleKey) +// self.data = items +// self.subject = subject +// self.message = message +// self.preview = preview +// } +// +// init(_ title: Text, items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) +// where Data.Element: Shareable, Label == DefaultShareLinkLabel +// { +// self.label = .init(title) +// self.data = items +// self.subject = subject +// self.message = message +// self.preview = preview +// } +//} diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Preview.swift b/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Preview.swift index 8413615a..aa3c4b69 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Preview.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/Multiple Items/Items+Preview.swift @@ -1,25 +1,25 @@ -import SwiftUI - -@available(iOS, deprecated: 16) -@available(macOS, deprecated: 13) -@available(watchOS, deprecated: 9) -@available(tvOS, unavailable) -public extension Backport.ShareLink where Wrapped == Any { - init(items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) - where Data.Element: BackportTransferable, Label == DefaultShareLinkLabel { - self.label = .init() - self.data = items - self.subject = subject - self.message = message - self.preview = preview - } - - init(items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview, @ViewBuilder label: () -> Label) - where Data.Element: BackportTransferable { - self.label = label() - self.data = items - self.subject = subject - self.message = message - self.preview = preview - } -} +//import SwiftUI +// +//@available(iOS, deprecated: 16) +//@available(macOS, deprecated: 13) +//@available(watchOS, deprecated: 9) +//@available(tvOS, unavailable) +//public extension Backport.ShareLink where Wrapped == Any { +// init(items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview) +// where Data.Element: Shareable, Label == DefaultShareLinkLabel { +// self.label = .init() +// self.data = items +// self.subject = subject +// self.message = message +// self.preview = preview +// } +// +// init(items: Data, subject: String? = nil, message: String? = nil, preview: @escaping (Data.Element) -> SharePreview, @ViewBuilder label: () -> Label) +// where Data.Element: Shareable { +// self.label = label() +// self.data = items +// self.subject = subject +// self.message = message +// self.preview = preview +// } +//} diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/ShareLink.swift b/Sources/SwiftUIBackports/Shared/ShareLink/ShareLink.swift index 4423f90d..257f91eb 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/ShareLink.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/ShareLink.swift @@ -6,7 +6,7 @@ import LinkPresentation @available(watchOS, deprecated: 9) @available(tvOS, unavailable) public extension Backport where Wrapped == Any { - struct ShareLink: View where Data: RandomAccessCollection, Data.Element: BackportTransferable, Label: View { + struct ShareLink: View where Data: RandomAccessCollection, Data.Element: Shareable, Label: View { @State private var activity: ActivityItem? let label: Label @@ -17,7 +17,7 @@ public extension Backport where Wrapped == Any { public var body: some View { Button { - + activity = ActivityItem(data: data) } label: { label } @@ -26,42 +26,42 @@ public extension Backport where Wrapped == Any { } } -final class TransferableActivityProvider: UIActivityItemProvider where Data: BackportTransferable { - let title: String? - let subject: String? - let message: String? - let image: Image? - let icon: Icon? - let data: Data - - init(data: Data, title: String?, subject: String?, message: String?, image: Image?, icon: Icon?) { - self.title = title - self.subject = subject - self.message = message - self.image = image - self.icon = icon - self.data = data - - let url = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent("tmp") - .appendingPathExtension(data.pathExtension) - - super.init(placeholderItem: url) - } - - override var item: Any { - data.itemProvider as Any - } - - override func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? { - let metadata = LPLinkMetadata() - metadata.title = title -// let icon = ImageRenderer(content: activity.icon) -// metadata.iconProvider = NSItemProvider(object: UIImage()) -// metadata.imageProvider = NSItemProvider(object: UIImage()) - return metadata - } - - override func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String { subject ?? "" } - -} +//final class TransferableActivityProvider: UIActivityItemProvider { +// let title: String? +// let subject: String? +// let message: String? +// let image: Image? +// let icon: Icon? +// let data: Data +// +// init(data: Data, title: String?, subject: String?, message: String?, image: Image?, icon: Icon?) { +// self.title = title +// self.subject = subject +// self.message = message +// self.image = image +// self.icon = icon +// self.data = data +// +// let url = URL(fileURLWithPath: NSTemporaryDirectory()) +// .appendingPathComponent("tmp") +// .appendingPathExtension(data.pathExtension) +// +// super.init(placeholderItem: url) +// } +// +// override var item: Any { +// data.itemProvider as Any +// } +// +// override func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? { +// let metadata = LPLinkMetadata() +// metadata.title = title +//// let icon = ImageRenderer(content: activity.icon) +//// metadata.iconProvider = NSItemProvider(object: UIImage()) +//// metadata.imageProvider = NSItemProvider(object: UIImage()) +// return metadata +// } +// +// override func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String { subject ?? "" } +// +//} diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/ShareSheet.swift b/Sources/SwiftUIBackports/Shared/ShareLink/ShareSheet.swift index 8fe69567..46429223 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/ShareSheet.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/ShareSheet.swift @@ -2,7 +2,7 @@ import SwiftUI extension View { @ViewBuilder - func shareSheet(item activityItems: Binding?>) -> some View where Data: RandomAccessCollection, Data.Element: BackportTransferable { + func shareSheet(item activityItems: Binding?>) -> some View where Data: RandomAccessCollection, Data.Element: Shareable { #if os(macOS) background(ShareSheet(item: activityItems)) #elseif os(iOS) @@ -13,7 +13,7 @@ extension View { #if os(macOS) -private struct ShareSheet: NSViewRepresentable where Data: RandomAccessCollection, Data.Element: BackportTransferable { +private struct ShareSheet: NSViewRepresentable where Data: RandomAccessCollection, Data.Element: Shareable { @Binding var item: ActivityItem? public func makeNSView(context: Context) -> SourceView { @@ -86,7 +86,7 @@ private struct ShareSheet: NSViewRepresentable where Data: RandomAccessCollectio #elseif os(iOS) -private struct ShareSheet: UIViewControllerRepresentable where Data: RandomAccessCollection, Data.Element: BackportTransferable { +private struct ShareSheet: UIViewControllerRepresentable where Data: RandomAccessCollection, Data.Element: Shareable { @Binding var item: ActivityItem? init(item: Binding?>) { diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Label+Preview.swift b/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Label+Preview.swift index 67c84336..c8239e04 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Label+Preview.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Label+Preview.swift @@ -1,34 +1,34 @@ -import SwiftUI - -@available(iOS, deprecated: 16) -@available(macOS, deprecated: 13) -@available(watchOS, deprecated: 9) -@available(tvOS, unavailable) -public extension Backport.ShareLink where Wrapped == Any { - init(_ title: S, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) - where Data == CollectionOfOne, Label == DefaultShareLinkLabel { - self.label = .init(title) - self.data = .init(item) - self.subject = subject - self.message = message - self.preview = { _ in preview } - } - - init(_ titleKey: LocalizedStringKey, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) - where Data == CollectionOfOne, Label == DefaultShareLinkLabel { - self.label = .init(titleKey) - self.data = .init(item) - self.subject = subject - self.message = message - self.preview = { _ in preview } - } - - init(_ title: Text, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) - where Data == CollectionOfOne, Label == DefaultShareLinkLabel { - self.label = .init(title) - self.data = .init(item) - self.subject = subject - self.message = message - self.preview = { _ in preview } - } -} +//import SwiftUI +// +//@available(iOS, deprecated: 16) +//@available(macOS, deprecated: 13) +//@available(watchOS, deprecated: 9) +//@available(tvOS, unavailable) +//public extension Backport.ShareLink where Wrapped == Any { +// init(_ title: S, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) +// where Data == CollectionOfOne, Label == DefaultShareLinkLabel { +// self.label = .init(title) +// self.data = .init(item) +// self.subject = subject +// self.message = message +// self.preview = { _ in preview } +// } +// +// init(_ titleKey: LocalizedStringKey, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) +// where Data == CollectionOfOne, Label == DefaultShareLinkLabel { +// self.label = .init(titleKey) +// self.data = .init(item) +// self.subject = subject +// self.message = message +// self.preview = { _ in preview } +// } +// +// init(_ title: Text, item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) +// where Data == CollectionOfOne, Label == DefaultShareLinkLabel { +// self.label = .init(title) +// self.data = .init(item) +// self.subject = subject +// self.message = message +// self.preview = { _ in preview } +// } +//} diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Preview.swift b/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Preview.swift index 61339ff7..00b08418 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Preview.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/Single Item/Item+Preview.swift @@ -1,25 +1,25 @@ -import SwiftUI - -@available(iOS, deprecated: 16) -@available(macOS, deprecated: 13) -@available(watchOS, deprecated: 9) -@available(tvOS, unavailable) -public extension Backport.ShareLink where Wrapped == Any { - init(item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) - where Data == CollectionOfOne, Label == DefaultShareLinkLabel { - self.label = .init() - self.data = .init(item) - self.subject = subject - self.message = message - self.preview = { _ in preview } - } - - init(item: I, subject: String? = nil, message: String? = nil, preview: SharePreview, @ViewBuilder label: () -> Label) - where Data == CollectionOfOne { - self.label = label() - self.data = .init(item) - self.subject = subject - self.message = message - self.preview = { _ in preview } - } -} +//import SwiftUI +// +//@available(iOS, deprecated: 16) +//@available(macOS, deprecated: 13) +//@available(watchOS, deprecated: 9) +//@available(tvOS, unavailable) +//public extension Backport.ShareLink where Wrapped == Any { +// init(item: I, subject: String? = nil, message: String? = nil, preview: SharePreview) +// where Data == CollectionOfOne, Label == DefaultShareLinkLabel { +// self.label = .init() +// self.data = .init(item) +// self.subject = subject +// self.message = message +// self.preview = { _ in preview } +// } +// +// init(item: I, subject: String? = nil, message: String? = nil, preview: SharePreview, @ViewBuilder label: () -> Label) +// where Data == CollectionOfOne { +// self.label = label() +// self.data = .init(item) +// self.subject = subject +// self.message = message +// self.preview = { _ in preview } +// } +//} diff --git a/Sources/SwiftUIBackports/Shared/ShareLink/Shareable.swift b/Sources/SwiftUIBackports/Shared/ShareLink/Transferable.swift similarity index 85% rename from Sources/SwiftUIBackports/Shared/ShareLink/Shareable.swift rename to Sources/SwiftUIBackports/Shared/ShareLink/Transferable.swift index 8db56c62..4db75228 100644 --- a/Sources/SwiftUIBackports/Shared/ShareLink/Shareable.swift +++ b/Sources/SwiftUIBackports/Shared/ShareLink/Transferable.swift @@ -3,16 +3,20 @@ import SwiftUI @available(iOS, deprecated: 16.0) @available(macOS, deprecated: 13.0) @available(watchOS, deprecated: 9.0) -public protocol BackportTransferable { + +/// TEMPORARY, DO NOT RELY ON THIS! +/// +/// - Note: This **will be removed** in an upcoming release, regardless of semantic versioning +public protocol Shareable { var pathExtension: String { get } var itemProvider: NSItemProvider? { get } } -internal struct ActivityItem where Data: RandomAccessCollection, Data.Element: BackportTransferable { +internal struct ActivityItem where Data: RandomAccessCollection, Data.Element: Shareable { internal var data: Data } -extension String: BackportTransferable { +extension String: Shareable { public var pathExtension: String { "txt" } public var itemProvider: NSItemProvider? { do { @@ -27,13 +31,13 @@ extension String: BackportTransferable { } } -extension URL: BackportTransferable { +extension URL: Shareable { public var itemProvider: NSItemProvider? { .init(contentsOf: self) } } -extension Image: BackportTransferable { +extension Image: Shareable { public var pathExtension: String { "jpg" } public var itemProvider: NSItemProvider? { do { @@ -50,7 +54,7 @@ extension Image: BackportTransferable { } } -extension PlatformImage: BackportTransferable { +extension PlatformImage: Shareable { public var pathExtension: String { "jpg" } public var itemProvider: NSItemProvider? { do { diff --git a/Sources/SwiftUIBackports/Shared/Transferable/_Transferable.swift b/Sources/SwiftUIBackports/Shared/Transferable/_Transferable.swift new file mode 100644 index 00000000..e1beeac7 --- /dev/null +++ b/Sources/SwiftUIBackports/Shared/Transferable/_Transferable.swift @@ -0,0 +1,89 @@ +//import Foundation +// +//public protocol _Transferable { +// associatedtype Representation: _TransferRepresentation +// @_TransferRepresentationBuilder static var transferRepresentation: Representation { get } +//} +// +//public protocol _TransferRepresentation: Sendable { +// associatedtype Item: _Transferable +// associatedtype Body: _TransferRepresentation +// @_TransferRepresentationBuilder var body: Body { get } +//} +// +//@resultBuilder +//public struct _TransferRepresentationBuilder where Item: _Transferable { +// public static func buildBlock(_ content: Content) -> Content where Item == Content.Item, Content: _TransferRepresentation { +// content +// } +//} +// +//public struct _DataRepresentation: _TransferRepresentation where Item: _Transferable { +// public var body: some _TransferRepresentation { +// fatalError() +// } +// +// public init(contentType: String, exporting: @escaping @Sendable (Item) async throws -> Data, importing: @escaping @Sendable (Data) async throws -> Item) { +// +// } +// +// public init(exportedContentType: String, exporting: @escaping @Sendable (Item) async throws -> Data) { +// +// } +// +// public init(importingContentType: String, importing: @escaping @Sendable (Data) async throws -> Item) { +// +// } +//} +// +//extension Data: Transferable, @unchecked Sendable { +// public typealias Representation = Never +// public static var transferRepresentation: Never { +// fatalError() +// } +//} +// +//extension Never: _TransferRepresentation { +// public typealias Item = Never +// public var body: Never { +// fatalError() +// } +//} +// +//extension Never: _Transferable { +// public static var transferRepresentation: Never { +// fatalError() +// } +//} +// +//import SwiftUI +//import UniformTypeIdentifiers +// +//@available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) +//extension UIImage: Transferable { +// public static var transferRepresentation: some TransferRepresentation { +// DataRepresentation(exportedContentType: .jpeg) { image in +// image.jpegData(compressionQuality: 1) ?? .init() +// } +// } +//} +// +//struct ImageDocumentLayer { +// init(data: Data) { } +// func data() -> Data { fatalError() } +// func pngData() -> Data { fatalError() } +//} +// +//@available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) +//extension UTType { +// static var layer: UTType { UTType(exportedAs: "com.example.layer") } +//} +// +//@available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) +//extension ImageDocumentLayer: Transferable { +// static var transferRepresentation: some TransferRepresentation { +// DataRepresentation(exportedContentType: .png) { layer in +// layer.pngData() +// } +// } +//}