Files

183 lines
5.1 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The MIT License (MIT)
//
// Copyright (c) 2020-2026 Alexander Grebenyuk (github.com/kean).
import SwiftUI
#if os(iOS) || os(visionOS)
import UIKit
package struct ShareView: UIViewControllerRepresentable {
var activityItems: [Any]
var applicationActivities: [UIActivity]?
private let cleanup: () -> Void
private var completion: (() -> Void)?
package init(activityItems: [Any]) {
self.activityItems = activityItems
self.cleanup = {}
}
package init(_ items: ShareItems) {
self.activityItems = items.items
self.cleanup = items.cleanup
}
package func onCompletion(_ completion: @escaping () -> Void) -> Self {
var copy = self
copy.completion = completion
return copy
}
package func makeUIViewController(context: UIViewControllerRepresentableContext<ShareView>) -> UIActivityViewController {
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
controller.completionWithItemsHandler = { _, _, _, _ in
cleanup()
completion?()
}
return controller
}
package func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ShareView>) {
}
}
#endif
#if os(macOS)
import AppKit
import Pulse
package struct ShareView: View {
package let items: ShareItems
private var cleanup: (() -> Void)?
private var completion: (() -> Void)?
package init(_ items: ShareItems) {
self.items = items
self.cleanup = items.cleanup
}
package func onCompletion(_ completion: @escaping () -> Void) -> Self {
var copy = self
copy.completion = completion
return copy
}
package var body: some View {
VStack(alignment: .leading, spacing: 0) {
let services = NSSharingService.sharingServices(forItems: items.items)
ForEach(services, id: \.title) { service in
Item(item: service) {
service.perform(withItems: items.items)
}
}
}.padding(4)
}
private struct Item: View {
let item: NSSharingService
let action: () -> Void
@State private var isHighlighted = false
var body: some View {
Button(action: action) {
HStack {
Image(nsImage: item.image)
Text(item.title)
Spacer()
}.contentShape(Rectangle())
}
.buttonStyle(.plain)
.padding(4)
.onHover { isHighlighted = $0 }
.background {
if isHighlighted {
Color.separator.cornerRadius(4)
}
}
}
}
}
#endif
#if os(macOS)
@available(iOS 18, tvOS 18, macOS 15, watchOS 11, visionOS 1, *)
package struct ShareNetworkTaskView: View {
@ObservedObject var task: NetworkTaskEntity
@AppStorage("com-github-kean-selected-task-sharing-option") private var output: Output = .plainText
@State private var items: ShareItems?
@Environment(\.store) private var store
package init(task: NetworkTaskEntity) {
self.task = task
}
package var body: some View {
VStack(spacing: 0) {
VStack(spacing: 8) {
NetworkRequestStatusCell(viewModel: .init(task: task, store: store))
HStack {
VStack(alignment: .leading) {
Text(task.httpMethod ?? "GET").fontWeight(.semibold)
Text(task.url ?? "–")
.lineLimit(3)
.fixedSize(horizontal: false, vertical: true)
}
Spacer()
}
}
.padding(8)
Picker("", selection: $output) {
ForEach(Output.allCases, id: \.self) {
Text($0.rawValue).tag($0.rawValue)
}
}
.labelsHidden()
.padding(8)
Divider()
if let items = items {
ShareView(items)
}
}
.onChange(of: output, perform: render)
.onAppear { render(with: output) }
.frame(width: 240)
}
private func render(with output: Output) {
var asString: NSAttributedString {
TextRenderer(options: .sharing).make {
$0.render(task, content: .sharing, store: store)
}
}
switch output {
case .plainText:
items = ShareService.share(asString, as: .plainText)
case .html:
items = ShareService.share(asString, as: .html)
case .curl:
items = ShareItems([task.cURLDescription()])
}
}
enum Output: String, CaseIterable {
case plainText = "Plain Text"
case html = "HTML"
case curl = "cURL"
}
}
#if DEBUG
@available(iOS 18, tvOS 18, macOS 15, watchOS 11, visionOS 1, *)
#Preview {
ShareNetworkTaskView(task: LoggerStore.demo.entity(for: .login))
.frame(height: 400)
}
#endif
#endif