Using any form of ShareLink
with an URL
or a String
having an URL as text, never is the option Copy-Link offered, even when enabled and showed in the settings
ShareLink(item: url)
i had to resort to NSViewRepresentable and my custom service...
to create a replacable ShareLink
<-> XShareLink
XShareLink(item: url) {
Image(systemName: "ellipsis")
.imageScale(.large)
}
if anybody finds a more pure SwiftUI way, pls feel free
////////////////////////////////////////////////////////////////////////
// MARK: - Share Link alternative -
////////////////////////////////////////////////////////////////////////
// as the default ShareLink doesn't offer copy link
// https://stackoverflow.com/questions/77220687/sharelink-in-swiftui-doesnt-offer-copy-link
struct XSharingsPicker: NSViewRepresentable {
@Binding var isPresented: Bool
var sharingItems: [Any] = []
func makeNSView(context: Context) -> NSView {
let view = NSView()
return view
}
func updateNSView(_ nsView: NSView, context: Context) {
if isPresented {
let picker = NSSharingServicePicker(items: sharingItems)
picker.delegate = context.coordinator
// !! MUST BE CALLED IN ASYNC, otherwise blocks update
DispatchQueue.main.async {
picker.show(relativeTo: .zero, of: nsView, preferredEdge: .minY)
}
}
}
func makeCoordinator() -> Coordinator {
Coordinator(owner: self)
}
class Coordinator: NSObject, NSSharingServicePickerDelegate {
let owner: XSharingsPicker
init(owner: XSharingsPicker) {
self.owner = owner
}
func sharingServicePicker(_ sharingServicePicker: NSSharingServicePicker, sharingServicesForItems items: [Any], proposedSharingServices proposedServices: [NSSharingService]) -> [NSSharingService] {
guard let url = items.compactMap({ $0 as? URL }).first else {
return proposedServices
}
guard let image = NSImage(systemSymbolName: "link", accessibilityDescription: nil) else {
return proposedServices
}
var share = proposedServices
let customService = NSSharingService(title: "Copy Link", image: image, alternateImage: image, handler: {
let p = NSPasteboard.general
p.clearContents()
p.setString(url.absoluteString, forType: .string)
})
share.insert(customService, at: 0)
return share
}
func sharingServicePicker(_ sharingServicePicker: NSSharingServicePicker, didChoose service: NSSharingService?) {
// do here whatever more needed here with selected service
sharingServicePicker.delegate = nil // << cleanup
self.owner.isPresented = false // << dismiss
}
}
}
struct XShareLink<Label>: View where Label: View {
var item: URL
var label: () -> Label
@State private var showPicker = false
var body: some View {
Button(action: {
self.showPicker = true
}) {
label()
}
.background(XSharingsPicker(isPresented: $showPicker, sharingItems: [item]))
}
}