RedditShareBridgeStyle.swift 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import Foundation
  2. enum RedditShareBridgeStyle {
  3. static let messageHandlerName = "reddoraShare"
  4. /// WKWebView does not implement navigator.share. Reddit's share button relies on it
  5. /// in Safari, so we bridge to the native macOS share sheet.
  6. static let injectionScript = """
  7. (function() {
  8. if (window.__reddoraShareBridgeInstalled) return;
  9. window.__reddoraShareBridgeInstalled = true;
  10. function hasBridge() {
  11. return !!(
  12. window.webkit &&
  13. window.webkit.messageHandlers &&
  14. window.webkit.messageHandlers.reddoraShare
  15. );
  16. }
  17. window.__reddoraShareCallback = function(success) {
  18. const resolve = window.__reddoraShareResolve;
  19. const reject = window.__reddoraShareReject;
  20. window.__reddoraShareResolve = null;
  21. window.__reddoraShareReject = null;
  22. if (success && resolve) {
  23. resolve();
  24. } else if (!success && reject) {
  25. reject(new DOMException('Share canceled', 'AbortError'));
  26. }
  27. };
  28. function nativeShare(data) {
  29. return new Promise(function(resolve, reject) {
  30. if (!hasBridge()) {
  31. reject(new DOMException('Share unavailable', 'NotSupportedError'));
  32. return;
  33. }
  34. window.__reddoraShareResolve = resolve;
  35. window.__reddoraShareReject = reject;
  36. window.webkit.messageHandlers.reddoraShare.postMessage({
  37. title: data && data.title ? String(data.title) : '',
  38. text: data && data.text ? String(data.text) : '',
  39. url: data && data.url ? String(data.url) : ''
  40. });
  41. });
  42. }
  43. function canShare(data) {
  44. if (!hasBridge()) return false;
  45. if (!data) return true;
  46. if (data.files && data.files.length) return false;
  47. return !!(data.url || data.text || data.title);
  48. }
  49. try {
  50. Object.defineProperty(navigator, 'share', {
  51. value: nativeShare,
  52. configurable: true,
  53. writable: true
  54. });
  55. Object.defineProperty(navigator, 'canShare', {
  56. value: canShare,
  57. configurable: true,
  58. writable: true
  59. });
  60. } catch (error) {
  61. navigator.share = nativeShare;
  62. navigator.canShare = canShare;
  63. }
  64. })();
  65. """
  66. }