@craft-native/ios 0.0.191 → 0.0.193

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/ios",
3
- "version": "0.0.191",
3
+ "version": "0.0.193",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/ios#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -5748,9 +5748,11 @@ struct CraftWebView: UIViewRepresentable {
5748
5748
  return
5749
5749
  }
5750
5750
  var items: [Any] = []
5751
- if let title = options["title"] as? String, !title.isEmpty { items.append(title) }
5751
+ let title = options["title"] as? String ?? ""
5752
5752
  if let text = options["text"] as? String, !text.isEmpty { items.append(text) }
5753
- if let urlString = options["url"] as? String, let url = URL(string: urlString) { items.append(url) }
5753
+ if let urlString = options["url"] as? String, let url = URL(string: urlString) {
5754
+ items.append(CraftShareLink(url: url, title: title))
5755
+ } else if !title.isEmpty { items.append(title) }
5754
5756
  if let files = options["files"] as? [String] {
5755
5757
  for file in files {
5756
5758
  if let url = URL(string: file), url.isFileURL { items.append(url) }
@@ -726,6 +726,11 @@ private func craftNativeAlignContentCode(_ value: String) -> UInt32 {
726
726
  }
727
727
  }
728
728
 
729
+ /// Keep the indicator's intrinsic size separate from authored style transforms.
730
+ private final class CraftNativeActivityIndicatorView: UIActivityIndicatorView {
731
+ var indicatorScale: CGFloat = 1
732
+ }
733
+
729
734
  /// A native screen's `<Video>`: AVPlayerViewController in place.
730
735
  ///
731
736
  /// With sound, a video takes the audio session as a playing sound does
@@ -5510,7 +5515,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
5510
5515
  updateHandler(nonEmptyHandler(events["onValueChange"]) ?? nonEmptyHandler(events["onChange"]), for: slider)
5511
5516
  updateAuxiliaryHandler(events["onSlidingComplete"], in: &sliderCompleteHandlers, for: slider)
5512
5517
  case "ActivityIndicator":
5513
- let indicator = result as! UIActivityIndicatorView
5518
+ let indicator = result as! CraftNativeActivityIndicatorView
5514
5519
  let requestedSize = props["size"]
5515
5520
  indicator.style = (requestedSize as? String) == "large" ? .large : .medium
5516
5521
  let scale: CGFloat
@@ -5522,7 +5527,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
5522
5527
  } else {
5523
5528
  scale = 1
5524
5529
  }
5525
- indicator.transform = CGAffineTransform(scaleX: scale, y: scale)
5530
+ indicator.indicatorScale = scale
5526
5531
  indicator.color = color(props["color"]) ?? .tintColor
5527
5532
  indicator.hidesWhenStopped = props["hidesWhenStopped"] as? Bool ?? true
5528
5533
  if props["animating"] as? Bool == false {
@@ -5728,7 +5733,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
5728
5733
  slider.addTarget(self, action: #selector(sliderFinished(_:)), for: [.touchUpInside, .touchUpOutside, .touchCancel])
5729
5734
  return slider
5730
5735
  case "ActivityIndicator":
5731
- return UIActivityIndicatorView(style: .medium)
5736
+ return CraftNativeActivityIndicatorView(style: .medium)
5732
5737
  case "StatusBar", "RefreshControl":
5733
5738
  return CraftNativeFlowView()
5734
5739
  case "Image":
@@ -6437,8 +6442,9 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
6437
6442
  }
6438
6443
 
6439
6444
  private func applyTransform(_ raw: Any?, to view: UIView) {
6440
- view.transform = .identity
6445
+ let intrinsicScale = (view as? CraftNativeActivityIndicatorView)?.indicatorScale ?? 1
6441
6446
  view.layer.transform = CATransform3DIdentity
6447
+ view.transform = CGAffineTransform(scaleX: intrinsicScale, y: intrinsicScale)
6442
6448
  guard let transforms = raw as? [[String: Any]] else { return }
6443
6449
  var affine = CGAffineTransform.identity
6444
6450
  var threeDimensional = CATransform3DIdentity
@@ -6461,6 +6467,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
6461
6467
  hasThreeDimensionalRotation = true
6462
6468
  }
6463
6469
  }
6470
+ affine = affine.scaledBy(x: intrinsicScale, y: intrinsicScale)
6464
6471
  if hasThreeDimensionalRotation {
6465
6472
  view.layer.transform = CATransform3DConcat(CATransform3DMakeAffineTransform(affine), threeDimensional)
6466
6473
  } else {
@@ -1,5 +1,6 @@
1
1
  import AVFoundation
2
2
  import Foundation
3
+ import LinkPresentation
3
4
  import UIKit
4
5
  import UserNotifications
5
6
 
@@ -687,6 +688,32 @@ enum CraftNativePush {
687
688
 
688
689
  // MARK: - Share sheet
689
690
 
691
+ /// A URL stays a URL in Messages, AirDrop and Copy. Its title belongs in the
692
+ /// system preview and mail subject, rather than becoming a second text item.
693
+ final class CraftShareLink: NSObject, UIActivityItemSource {
694
+ let url: URL
695
+ let title: String
696
+
697
+ init(url: URL, title: String) {
698
+ self.url = url
699
+ self.title = title
700
+ }
701
+
702
+ func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any { url }
703
+
704
+ func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? { url }
705
+
706
+ func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String { title }
707
+
708
+ func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
709
+ let metadata = LPLinkMetadata()
710
+ metadata.originalURL = url
711
+ metadata.url = url
712
+ if !title.isEmpty { metadata.title = title }
713
+ return metadata
714
+ }
715
+ }
716
+
690
717
  /// `craft.share` on a native screen: the system share sheet with the page's
691
718
  /// options (`title`, `text`, `url`, `files`), plus `image`, a picture by URL
692
719
  /// that is shared as the picture rather than as its address. Answers true
@@ -694,9 +721,11 @@ enum CraftNativePush {
694
721
  enum CraftNativeShare {
695
722
  static func share(_ options: [String: Any], done: @escaping (Result<Any, CraftNativeActionError>) -> Void) {
696
723
  var items: [Any] = []
697
- if let title = options["title"] as? String, !title.isEmpty { items.append(title) }
724
+ let title = options["title"] as? String ?? ""
698
725
  if let text = options["text"] as? String, !text.isEmpty { items.append(text) }
699
- if let address = options["url"] as? String, let url = URL(string: address) { items.append(url) }
726
+ if let address = options["url"] as? String, let url = URL(string: address) {
727
+ items.append(CraftShareLink(url: url, title: title))
728
+ } else if !title.isEmpty { items.append(title) }
700
729
  // A path or file URL, or a file craft.files made (`{ path, name }`).
701
730
  let files = (options["files"] as? [Any] ?? []).compactMap { item -> String? in
702
731
  item as? String ?? (item as? [String: Any])?["path"] as? String
@@ -715,7 +744,7 @@ enum CraftNativeShare {
715
744
  if let error { done(.failure(CraftNativeActionError(code: "SHARE_ERROR", message: error.localizedDescription))) }
716
745
  else { done(.success(completed)) }
717
746
  }
718
- if !CraftPresenter.present(sheet, from: nil, anchor: nil) {
747
+ if !CraftPresenter.present(sheet, from: nil, anchor: CraftPresenter.rect(options["anchor"])) {
719
748
  done(.failure(CraftNativeActionError(code: "SHARE_ERROR", message: "Unable to present the share sheet")))
720
749
  }
721
750
  }