RedditShareScriptBridge.swift 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import AppKit
  2. import WebKit
  3. @MainActor
  4. final class RedditShareScriptBridge: NSObject, WKScriptMessageHandler {
  5. static let shared = RedditShareScriptBridge()
  6. weak var webView: WKWebView?
  7. private override init() {
  8. super.init()
  9. }
  10. nonisolated func userContentController(
  11. _ userContentController: WKUserContentController,
  12. didReceive message: WKScriptMessage
  13. ) {
  14. guard message.name == RedditShareBridgeStyle.messageHandlerName else { return }
  15. Task { @MainActor in
  16. handleShareMessage(message)
  17. }
  18. }
  19. private func handleShareMessage(_ message: WKScriptMessage) {
  20. let targetWebView = webView ?? message.webView
  21. guard let targetWebView else {
  22. return
  23. }
  24. var items: [Any] = []
  25. if let payload = message.body as? [String: Any] {
  26. if let urlString = payload["url"] as? String,
  27. !urlString.isEmpty,
  28. let url = URL(string: urlString) {
  29. items.append(url)
  30. }
  31. if let text = payload["text"] as? String, !text.isEmpty {
  32. items.append(text)
  33. }
  34. if let title = payload["title"] as? String, !title.isEmpty {
  35. items.append(title)
  36. }
  37. } else if let urlString = message.body as? String,
  38. let url = URL(string: urlString) {
  39. items.append(url)
  40. }
  41. guard !items.isEmpty else {
  42. resolveShare(on: targetWebView, success: false)
  43. return
  44. }
  45. let picker = NSSharingServicePicker(items: items)
  46. let anchor = NSRect(
  47. x: targetWebView.bounds.midX,
  48. y: targetWebView.bounds.midY,
  49. width: 1,
  50. height: 1
  51. )
  52. picker.show(relativeTo: anchor, of: targetWebView, preferredEdge: .minY)
  53. resolveShare(on: targetWebView, success: true)
  54. }
  55. private func resolveShare(on webView: WKWebView, success: Bool) {
  56. webView.evaluateJavaScript(
  57. "window.__reddoraShareCallback && window.__reddoraShareCallback(\(success));",
  58. completionHandler: nil
  59. )
  60. }
  61. }