From 8fce5877d9c530c061b43fcb3b55c560522d4a08 Mon Sep 17 00:00:00 2001 From: Dominic Go <18517029+dominicstop@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:55:26 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9D=8C=20Remove:=20All=20iOS=20Sources=20and?= =?UTF-8?q?=20Related=20Files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Extensions+Init/CGSize+Init.swift | 21 - ios/Extensions+Init/UIBlurEffect+Init.swift | 132 -- .../UIModalPresentationStyle+Init.swift | 81 -- .../UISheetPresentationController+Init.swift | 67 - ios/Extensions/CAAnimation+Block.swift | 61 - ios/Extensions/CAAnimation+Helpers.swift | 17 - ios/Extensions/CGRect+Helpers.swift | 54 - ios/Extensions/Collection+Helpers.swift | 41 - ios/Extensions/Encodable+Helpers.swift | 31 - ios/Extensions/FloatingPoint+Clamping.swift | 31 - ios/Extensions/KeyWindow+Helpers.swift | 21 - ios/Extensions/RNIUtilities+Helpers.swift | 158 -- .../UIGestureRecognizer+Helpers.swift | 23 - .../UIModalTransitionStyle+Helpers.swift | 34 - ios/Extensions/UIView+Helpers.swift | 60 - .../UIViewController+Swizzling.swift | 235 --- ios/Extensions/UIWindow+Helpers.swift | 12 - ios/Helpers+Utilities/CGSize+Helpers.swift | 14 - ios/Helpers+Utilities/WeakElement.swift | 13 - .../RNIAnimator/RNIAnimator.swift | 243 ---- .../RNIAnimator/RNIAnimatorSize.swift | 54 - .../RNIComputable/RNIComputableOffset.swift | 61 - .../RNIComputable/RNIComputableSize.swift | 148 -- .../RNIComputable/RNIComputableSizeMode.swift | 60 - .../RNIComputable/RNIComputableValue.swift | 116 -- .../RNIComputableValueMode.swift | 48 - .../RNIComputable/RNIViewMetadata.swift | 62 - .../RNIDictionaryRepresentable.swift | 12 - .../RNIDictionarySynthesizable+Default.swift | 140 -- .../RNIDictionarySynthesizable.swift | 29 - .../RNIError/RNIBaseError+Helpers.swift | 120 -- ios/React Native/RNIError/RNIBaseError.swift | 34 - ios/React Native/RNIError/RNIError.swift | 18 - .../RNIError/RNIErrorCodeDefaultable.swift | 70 - .../RNIError/RNIErrorCodeSynthesizable.swift | 24 - .../RNIError/RNIGenericErrorCode.swift | 15 - .../RNIIdentifiable+Default.swift | 37 - .../RNIIdentifiable/RNIIdentifiable.swift | 20 - .../RNIIdentifiable/RNIObjectIdentifier.swift | 54 - .../RNIModal/RNIModal+Helpers.swift | 122 -- ios/React Native/RNIModal/RNIModal.swift | 125 -- .../RNIModal/RNIModalCustomSheetDetent.swift | 111 -- ios/React Native/RNIModal/RNIModalData.swift | 28 - ios/React Native/RNIModal/RNIModalError.swift | 41 - .../RNIModal/RNIModalEventData.swift | 64 - ios/React Native/RNIModal/RNIModalFlags.swift | 21 - .../RNIModal/RNIModalFocusState.swift | 142 -- .../RNIModal/RNIModalManager.swift | 448 ------ .../RNIModalPresentationNotifiable.swift | 19 - .../RNIModal/RNIModalPresentationState.swift | 303 ---- .../RNIModalPresentationTrigger.swift | 16 - .../RNIModal/RNIModalUtilities.swift | 121 -- .../RNIModal/RNIModalWindowMap.swift | 140 -- .../RNIPresentedViewControllerCache.swift | 72 - .../RNIModalView/RNIModalView.swift | 1285 ----------------- .../RNIModalView/RNIModalViewController.swift | 369 ----- .../RNIModalView/RNIModalViewError.swift | 35 - .../RNIModalView/RNIModalViewManager.m | 83 -- .../RNIModalView/RNIModalViewManager.swift | 44 - .../RNIModalViewControllerWrapper.swift | 132 -- ...NIModalViewControllerWrapperRegistry.swift | 39 - .../RNIModalViewModule/RNIModalViewModule.m | 43 - .../RNIModalViewModule.swift | 223 --- .../CAAnimationMulticastDelegate.swift | 28 - .../RNIMulticastDelegate.swift | 27 - .../RNIObjectMetadata+Default.swift | 29 - .../RNIObjectMetadata/RNIObjectMetadata.swift | 14 - ...ontrollerLifeCycleNotifiable+Default.swift | 42 - ...RNIViewControllerLifeCycleNotifiable.swift | 35 - ios/React Native/RNIWeak/RNIWeakArray.swift | 64 - .../RNIWeak/RNIWeakDictionary.swift | 55 - ios/React Native/RNIWeak/RNIWeakRef.swift | 26 - .../CAGradientLayerType+Init.swift | 27 - ios/Temp/Extensions+Init/UIImage+Init.swift | 56 - ios/Temp/Extensions/UIColor+Helpers.swift | 446 ------ .../Extensions/UIViewController+Helpers.swift | 24 - ios/Temp/IosUtilities-Bridging-Header.h | 16 - .../RNIJSComponentWillUnmountNotifiable.swift | 18 - ios/Temp/RNICleanup/RNICleanable.swift | 17 - ios/Temp/RNICleanup/RNICleanupMode.swift | 25 - .../RNICleanup/RNIInternalCleanupMode.swift | 40 - ios/Temp/RNIImage/RNIImageGradientMaker.swift | 181 --- ios/Temp/RNIImage/RNIImageItem.swift | 212 --- ios/Temp/RNIImage/RNIImageLoadingConfig.swift | 26 - ios/Temp/RNIImage/RNIImageMaker.swift | 59 - ios/Temp/RNIImage/RNIImageOptions.swift | 35 - .../RNIImage/RNIImageRemoteURLMaker.swift | 361 ----- ios/Temp/RNIImage/RNIImageRequireMaker.swift | 76 - ios/Temp/RNIImage/RNIImageSystemMaker.swift | 113 -- ios/Temp/RNIImage/RNIImageType.swift | 29 - .../RNIRemoteURLImageLoadingConfig.swift | 52 - .../RNINavigationEventsNotifiable.swift | 14 - ...igationEventsReportingViewController.swift | 65 - ios/Temp/RNIUtilities/RNIUtilities.swift | 165 --- ios/Temp/RNIUtilities/RNIUtilitiesModule.m | 14 - .../RNIUtilities/RNIUtilitiesModule.swift | 29 - ios/Temp/RNIWrapperView/RNIWrapperView.swift | 273 ---- .../RNIWrapperViewEventsNotifiable.swift | 16 - .../RNIWrapperView/RNIWrapperViewManager.m | 28 - .../RNIWrapperViewManager.swift | 38 - .../RNIWrapperView/RNIWrapperViewModule.m | 15 - .../RNIWrapperView/RNIWrapperViewModule.swift | 55 - 102 files changed, 9342 deletions(-) delete mode 100644 ios/Extensions+Init/CGSize+Init.swift delete mode 100644 ios/Extensions+Init/UIBlurEffect+Init.swift delete mode 100644 ios/Extensions+Init/UIModalPresentationStyle+Init.swift delete mode 100644 ios/Extensions+Init/UISheetPresentationController+Init.swift delete mode 100644 ios/Extensions/CAAnimation+Block.swift delete mode 100644 ios/Extensions/CAAnimation+Helpers.swift delete mode 100644 ios/Extensions/CGRect+Helpers.swift delete mode 100644 ios/Extensions/Collection+Helpers.swift delete mode 100644 ios/Extensions/Encodable+Helpers.swift delete mode 100644 ios/Extensions/FloatingPoint+Clamping.swift delete mode 100644 ios/Extensions/KeyWindow+Helpers.swift delete mode 100644 ios/Extensions/RNIUtilities+Helpers.swift delete mode 100644 ios/Extensions/UIGestureRecognizer+Helpers.swift delete mode 100644 ios/Extensions/UIModalTransitionStyle+Helpers.swift delete mode 100644 ios/Extensions/UIView+Helpers.swift delete mode 100644 ios/Extensions/UIViewController+Swizzling.swift delete mode 100644 ios/Extensions/UIWindow+Helpers.swift delete mode 100644 ios/Helpers+Utilities/CGSize+Helpers.swift delete mode 100644 ios/Helpers+Utilities/WeakElement.swift delete mode 100644 ios/React Native/RNIAnimator/RNIAnimator.swift delete mode 100644 ios/React Native/RNIAnimator/RNIAnimatorSize.swift delete mode 100644 ios/React Native/RNIComputable/RNIComputableOffset.swift delete mode 100644 ios/React Native/RNIComputable/RNIComputableSize.swift delete mode 100644 ios/React Native/RNIComputable/RNIComputableSizeMode.swift delete mode 100644 ios/React Native/RNIComputable/RNIComputableValue.swift delete mode 100644 ios/React Native/RNIComputable/RNIComputableValueMode.swift delete mode 100644 ios/React Native/RNIComputable/RNIViewMetadata.swift delete mode 100644 ios/React Native/RNIDictionarySynthesizable/RNIDictionaryRepresentable.swift delete mode 100644 ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable+Default.swift delete mode 100644 ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable.swift delete mode 100644 ios/React Native/RNIError/RNIBaseError+Helpers.swift delete mode 100644 ios/React Native/RNIError/RNIBaseError.swift delete mode 100644 ios/React Native/RNIError/RNIError.swift delete mode 100644 ios/React Native/RNIError/RNIErrorCodeDefaultable.swift delete mode 100644 ios/React Native/RNIError/RNIErrorCodeSynthesizable.swift delete mode 100644 ios/React Native/RNIError/RNIGenericErrorCode.swift delete mode 100644 ios/React Native/RNIIdentifiable/RNIIdentifiable+Default.swift delete mode 100644 ios/React Native/RNIIdentifiable/RNIIdentifiable.swift delete mode 100644 ios/React Native/RNIIdentifiable/RNIObjectIdentifier.swift delete mode 100644 ios/React Native/RNIModal/RNIModal+Helpers.swift delete mode 100644 ios/React Native/RNIModal/RNIModal.swift delete mode 100644 ios/React Native/RNIModal/RNIModalCustomSheetDetent.swift delete mode 100644 ios/React Native/RNIModal/RNIModalData.swift delete mode 100644 ios/React Native/RNIModal/RNIModalError.swift delete mode 100644 ios/React Native/RNIModal/RNIModalEventData.swift delete mode 100644 ios/React Native/RNIModal/RNIModalFlags.swift delete mode 100644 ios/React Native/RNIModal/RNIModalFocusState.swift delete mode 100644 ios/React Native/RNIModal/RNIModalManager.swift delete mode 100644 ios/React Native/RNIModal/RNIModalPresentationNotifiable.swift delete mode 100644 ios/React Native/RNIModal/RNIModalPresentationState.swift delete mode 100644 ios/React Native/RNIModal/RNIModalPresentationTrigger.swift delete mode 100644 ios/React Native/RNIModal/RNIModalUtilities.swift delete mode 100644 ios/React Native/RNIModal/RNIModalWindowMap.swift delete mode 100644 ios/React Native/RNIModal/RNIPresentedViewControllerCache.swift delete mode 100644 ios/React Native/RNIModalView/RNIModalView.swift delete mode 100644 ios/React Native/RNIModalView/RNIModalViewController.swift delete mode 100644 ios/React Native/RNIModalView/RNIModalViewError.swift delete mode 100644 ios/React Native/RNIModalView/RNIModalViewManager.m delete mode 100644 ios/React Native/RNIModalView/RNIModalViewManager.swift delete mode 100644 ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapper.swift delete mode 100644 ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapperRegistry.swift delete mode 100644 ios/React Native/RNIModalViewModule/RNIModalViewModule.m delete mode 100644 ios/React Native/RNIModalViewModule/RNIModalViewModule.swift delete mode 100644 ios/React Native/RNIMulticastDelegate/CAAnimationMulticastDelegate.swift delete mode 100644 ios/React Native/RNIMulticastDelegate/RNIMulticastDelegate.swift delete mode 100644 ios/React Native/RNIObjectMetadata/RNIObjectMetadata+Default.swift delete mode 100644 ios/React Native/RNIObjectMetadata/RNIObjectMetadata.swift delete mode 100644 ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable+Default.swift delete mode 100644 ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable.swift delete mode 100644 ios/React Native/RNIWeak/RNIWeakArray.swift delete mode 100644 ios/React Native/RNIWeak/RNIWeakDictionary.swift delete mode 100644 ios/React Native/RNIWeak/RNIWeakRef.swift delete mode 100644 ios/Temp/Extensions+Init/CAGradientLayerType+Init.swift delete mode 100644 ios/Temp/Extensions+Init/UIImage+Init.swift delete mode 100644 ios/Temp/Extensions/UIColor+Helpers.swift delete mode 100644 ios/Temp/Extensions/UIViewController+Helpers.swift delete mode 100644 ios/Temp/IosUtilities-Bridging-Header.h delete mode 100644 ios/Temp/Protocols/RNIJSComponentWillUnmountNotifiable.swift delete mode 100644 ios/Temp/RNICleanup/RNICleanable.swift delete mode 100644 ios/Temp/RNICleanup/RNICleanupMode.swift delete mode 100644 ios/Temp/RNICleanup/RNIInternalCleanupMode.swift delete mode 100644 ios/Temp/RNIImage/RNIImageGradientMaker.swift delete mode 100644 ios/Temp/RNIImage/RNIImageItem.swift delete mode 100644 ios/Temp/RNIImage/RNIImageLoadingConfig.swift delete mode 100644 ios/Temp/RNIImage/RNIImageMaker.swift delete mode 100644 ios/Temp/RNIImage/RNIImageOptions.swift delete mode 100644 ios/Temp/RNIImage/RNIImageRemoteURLMaker.swift delete mode 100644 ios/Temp/RNIImage/RNIImageRequireMaker.swift delete mode 100644 ios/Temp/RNIImage/RNIImageSystemMaker.swift delete mode 100644 ios/Temp/RNIImage/RNIImageType.swift delete mode 100644 ios/Temp/RNIImage/RNIRemoteURLImageLoadingConfig.swift delete mode 100644 ios/Temp/RNINavigationEventsReporting/RNINavigationEventsNotifiable.swift delete mode 100644 ios/Temp/RNINavigationEventsReporting/RNINavigationEventsReportingViewController.swift delete mode 100644 ios/Temp/RNIUtilities/RNIUtilities.swift delete mode 100644 ios/Temp/RNIUtilities/RNIUtilitiesModule.m delete mode 100644 ios/Temp/RNIUtilities/RNIUtilitiesModule.swift delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperView.swift delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperViewEventsNotifiable.swift delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperViewManager.m delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperViewManager.swift delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperViewModule.m delete mode 100644 ios/Temp/RNIWrapperView/RNIWrapperViewModule.swift diff --git a/ios/Extensions+Init/CGSize+Init.swift b/ios/Extensions+Init/CGSize+Init.swift deleted file mode 100644 index 8b5b33b2..00000000 --- a/ios/Extensions+Init/CGSize+Init.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// CGSize+Init.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/28/23. -// - -import UIKit - -public extension CGSize { - init?(fromDict dict: NSDictionary){ - guard let width = dict["width"] as? NSNumber, - let height = dict["height"] as? NSNumber - else { return nil }; - - self.init( - width: width.doubleValue, - height: height.doubleValue - ); - }; -}; diff --git a/ios/Extensions+Init/UIBlurEffect+Init.swift b/ios/Extensions+Init/UIBlurEffect+Init.swift deleted file mode 100644 index 54f78cb3..00000000 --- a/ios/Extensions+Init/UIBlurEffect+Init.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// UIBlurEffect+Init.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/23/23. -// - -import UIKit - -extension UIBlurEffect.Style: CaseIterable, CustomStringConvertible { - - /// The available `UIBlurEffect.Style` that can be used based on the current - /// platform version - /// - public static var availableStyles: [UIBlurEffect.Style] { - var styles: [UIBlurEffect.Style] = [ - .light, - .extraLight, - .dark, - ]; - - if #available(iOS 10.0, *) { - styles.append(contentsOf: [ - .regular, - .prominent, - ]); - }; - - if #available(iOS 13.0, *) { - styles.append(contentsOf: [ - .systemUltraThinMaterial, - .systemThinMaterial, - .systemMaterial, - .systemThickMaterial, - .systemChromeMaterial, - .systemMaterialLight, - .systemThinMaterialLight, - .systemUltraThinMaterialLight, - .systemThickMaterialLight, - .systemChromeMaterialLight, - .systemChromeMaterialDark, - .systemMaterialDark, - .systemThickMaterialDark, - .systemThinMaterialDark, - .systemUltraThinMaterialDark, - ]); - }; - - return styles; - }; - - // MARK: - CaseIterable - // -------------------- - - public static var allCases: [UIBlurEffect.Style] { - return self.availableStyles; - }; - - // MARK: - CustomStringConvertible - // ------------------------------- - - /// Note:2023-03-23-23-14-57 - /// - /// * `UIBlurEffect.Style` is an objc enum, and as such, it's actually raw - /// value internally is `Int`. - /// - /// * As such, `String(describing:)` a ` UIBlurEffect.Style` enum value - /// outputs an `Int`. - /// - /// * Because of this, we have to manually map out the enum values to a string - /// representation. - /// - public var description: String { - switch self { - // Adaptable Styles - case .systemUltraThinMaterial: return "systemUltraThinMaterial"; - case .systemThinMaterial : return "systemThinMaterial"; - case .systemMaterial : return "systemMaterial"; - case .systemThickMaterial : return "systemThickMaterial"; - case .systemChromeMaterial : return "systemChromeMaterial"; - - // Light Styles - case .systemMaterialLight : return "systemMaterialLight"; - case .systemThinMaterialLight : return "systemThinMaterialLight"; - case .systemUltraThinMaterialLight: return "systemUltraThinMaterialLight"; - case .systemThickMaterialLight : return "systemThickMaterialLight"; - case .systemChromeMaterialLight : return "systemChromeMaterialLight"; - - // Dark Styles - case .systemChromeMaterialDark : return "systemChromeMaterialDark"; - case .systemMaterialDark : return "systemMaterialDark"; - case .systemThickMaterialDark : return "systemThickMaterialDark"; - case .systemThinMaterialDark : return "systemThinMaterialDark"; - case .systemUltraThinMaterialDark: return "systemUltraThinMaterialDark"; - - // Additional Styles - case .regular : return "regular"; - case .prominent : return "prominent"; - case .light : return "light"; - case .extraLight: return "extraLight"; - case .dark : return "dark"; - - @unknown default: return ""; - }; - }; - - // MARK: - Init - // ------------ - - init?(string: String){ - - /// Note:2023-03-23-23-21-21 - /// - /// * Normally, a simple `switch` + `case "foo": self = foo` would suffice, - /// (especially since it's O(1) access), but the usable enum values depend - /// on the platform version. - /// - /// * The useable enums are stored in `availableStyles`, and is used to - /// communicate to JS the available enum values. - /// - /// * As such, we might as well re-use `availableStyles` for the parsing - /// logic (even if it's less efficient). - /// - let style = Self.allCases.first{ - $0.description == string - }; - - guard let style = style else { return nil }; - self = style; - }; -}; - diff --git a/ios/Extensions+Init/UIModalPresentationStyle+Init.swift b/ios/Extensions+Init/UIModalPresentationStyle+Init.swift deleted file mode 100644 index d27c1c81..00000000 --- a/ios/Extensions+Init/UIModalPresentationStyle+Init.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// UIModalPresentationStyle+Init.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/24/23. -// - -import UIKit - -extension UIModalPresentationStyle: CaseIterable, CustomStringConvertible { - - /// The available `UIModalPresentationStyle` that can be used based on the - /// current platform version - /// - public static var availableStyles: [UIModalPresentationStyle] { - var styles: [UIModalPresentationStyle] = [ - .fullScreen, - .pageSheet, - .formSheet, - .currentContext, - .custom, - .overFullScreen, - .overCurrentContext, - .popover, - ]; - - if #available(iOS 13.0, *) { - styles.append(.automatic); - }; - - #if !os(iOS) - styles.append(.blurOverFullScreen); - #endif - - return styles; - }; - - - public static var allCases: [UIModalPresentationStyle] { - return self.availableStyles; - }; - - // MARK: - CustomStringConvertible - // ------------------------------- - - /// See: Note:2023-03-23-23-14-57 - public var description: String { - switch self { - case .automatic : return "automatic"; - case .none : return "none"; - case .fullScreen : return "fullScreen"; - case .pageSheet : return "pageSheet"; - case .formSheet : return "formSheet"; - case .currentContext : return "currentContext"; - case .custom : return "custom"; - case .overFullScreen : return "overFullScreen"; - case .overCurrentContext: return "overCurrentContext"; - case .popover : return "popover"; - - #if !os(iOS) - case .blurOverFullScreen: return "blurOverFullScreen"; - #endif - - @unknown default: return ""; - }; - }; - - - // MARK: - Init - // ------------ - - init?(string: String){ - /// See: Note:2023-03-23-23-21-21 - let style = Self.allCases.first{ - $0.description == string - }; - - guard let style = style else { return nil }; - self = style; - }; -}; diff --git a/ios/Extensions+Init/UISheetPresentationController+Init.swift b/ios/Extensions+Init/UISheetPresentationController+Init.swift deleted file mode 100644 index a24a3383..00000000 --- a/ios/Extensions+Init/UISheetPresentationController+Init.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// UISheetPresentationController+Init.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/21/23. -// - -import UIKit - - -@available(iOS 15.0, *) -extension UISheetPresentationController.Detent { - - // 2, - // _identifier=com.apple.UIKit.medium - // > - // - // 1, - // _identifier=com.apple.UIKit.large - // > - - static func fromString( - _ string: String - ) -> UISheetPresentationController.Detent? { - - switch string { - case "medium": return .medium(); - case "large" : return .large(); - - default: return nil; - }; - }; -}; - -@available(iOS 15.0, *) -extension UISheetPresentationController.Detent.Identifier: - CustomStringConvertible { - - public var description: String { - switch self { - case .medium: return "medium"; - case .large : return "large"; - - default: return self.rawValue; - }; - }; - - init?(fromSystemIdentifierString string: String) { - switch string { - case "medium": self = .medium; - case "large" : self = .large; - - default: return nil; - }; - }; - - init(fromString string: String) { - if let systemIdentifier = Self.init(fromSystemIdentifierString: string) { - self = systemIdentifier; - - } else { - self.init(string); - }; - }; -}; diff --git a/ios/Extensions/CAAnimation+Block.swift b/ios/Extensions/CAAnimation+Block.swift deleted file mode 100644 index 49cfbf2a..00000000 --- a/ios/Extensions/CAAnimation+Block.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// CAAnimation+Block.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/1/23. -// - -import UIKit - - -public class CAAnimationBlockDelegate: NSObject, CAAnimationDelegate { - - public typealias StartBlock = (CAAnimation) -> (); - public typealias EndBlock = (CAAnimation, Bool) -> (); - - var onStartBlock: StartBlock? - var onEndBlock: EndBlock? - - public func animationDidStart(_ anim: CAAnimation) { - self.onStartBlock?(anim); - }; - - public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { - self.onEndBlock?(anim, flag); - }; -}; - -public extension CAAnimation { - - private var multicastDelegate: CAAnimationMulticastDelegate { - guard let delegate = self.delegate else { - return CAAnimationMulticastDelegate(); - }; - - guard let multicastDelegate = delegate as? CAAnimationMulticastDelegate else { - let multicastDelegate = CAAnimationMulticastDelegate(); - multicastDelegate.emitter.add(delegate); - - self.speed = 0; - - self.delegate = multicastDelegate; - return multicastDelegate; - }; - - return multicastDelegate; - }; - - func startBlock(_ callback: @escaping CAAnimationBlockDelegate.StartBlock) { - let blockDelegate = CAAnimationBlockDelegate(); - self.multicastDelegate.emitter.add(blockDelegate); - - blockDelegate.onStartBlock = callback; - }; - - func endBlock(_ callback: @escaping CAAnimationBlockDelegate.EndBlock) { - let blockDelegate = CAAnimationBlockDelegate(); - self.multicastDelegate.emitter.add(blockDelegate); - - blockDelegate.onEndBlock = callback; - }; -}; diff --git a/ios/Extensions/CAAnimation+Helpers.swift b/ios/Extensions/CAAnimation+Helpers.swift deleted file mode 100644 index cc91ee1d..00000000 --- a/ios/Extensions/CAAnimation+Helpers.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// CAAnimation+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/1/23. -// - -import UIKit - -public extension CAAnimation { - func waitUntiEnd(_ block: @escaping () -> Void){ - DispatchQueue.main.asyncAfter( - deadline: .now() + self.duration, - execute: block - ); - }; -}; diff --git a/ios/Extensions/CGRect+Helpers.swift b/ios/Extensions/CGRect+Helpers.swift deleted file mode 100644 index ed067e30..00000000 --- a/ios/Extensions/CGRect+Helpers.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// CGSize+Helpers.swift -// swift-programmatic-modal -// -// Created by Dominic Go on 5/19/23. -// - -import UIKit - -extension CGRect { - mutating func setPoint( - minX: CGFloat? = nil, - minY: CGFloat? = nil - ){ - self.origin = CGPoint( - x: minX ?? self.minX, - y: minY ?? self.minY - ); - }; - - mutating func setPoint( - midX: CGFloat? = nil, - midY: CGFloat? = nil - ){ - let newX: CGFloat = { - guard let midX = midX else { return self.minX }; - return midX - (self.width / 2); - }(); - - let newY: CGFloat = { - guard let midY = midY else { return self.minY }; - return midY - (self.height / 2); - }(); - - self.origin = CGPoint(x: newX, y: newY); - }; - - mutating func setPoint( - maxX: CGFloat? = nil, - maxY: CGFloat? = nil - ){ - let newX: CGFloat = { - guard let maxX = maxX else { return self.minX }; - return maxX - self.width; - }(); - - let newY: CGFloat = { - guard let maxY = maxY else { return self.minY }; - return maxY - self.height; - }(); - - self.origin = CGPoint(x: newX, y: newY); - }; -}; diff --git a/ios/Extensions/Collection+Helpers.swift b/ios/Extensions/Collection+Helpers.swift deleted file mode 100644 index 177868c2..00000000 --- a/ios/Extensions/Collection+Helpers.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Collection+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/10/23. -// - -import UIKit - -extension Collection { - - public var secondToLast: Element? { - self[safeIndex: self.index(self.indices.endIndex, offsetBy: -2)]; - }; - - public func isOutOfBounds(forIndex index: Index) -> Bool { - return index < self.indices.startIndex || index >= self.indices.endIndex; - }; - - /// Returns the element at the specified index if it is within bounds, - /// otherwise nil. - public subscript(safeIndex index: Index) -> Element? { - return self.isOutOfBounds(forIndex: index) ? nil : self[index]; - }; -}; - -extension MutableCollection { - subscript(safeIndex index: Index) -> Element? { - get { - return self.isOutOfBounds(forIndex: index) ? nil : self[index]; - } - - set { - guard let newValue = newValue, - !self.isOutOfBounds(forIndex: index) - else { return }; - - self[index] = newValue; - } - }; -}; diff --git a/ios/Extensions/Encodable+Helpers.swift b/ios/Extensions/Encodable+Helpers.swift deleted file mode 100644 index b4490c5a..00000000 --- a/ios/Extensions/Encodable+Helpers.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// Encodable+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/2/23. -// - -import UIKit - - -public extension Encodable { - - var asJsonData: Data? { - let encoder = JSONEncoder(); - encoder.outputFormatting = .prettyPrinted; - encoder.dateEncodingStrategy = .iso8601; - - return try? encoder.encode(self); - }; - - var asDictionary : [String: Any]? { - guard let jsonData = self.asJsonData, - let json = try? JSONSerialization.jsonObject( - with: jsonData, - options: [] - ) - else { return nil }; - - return json as? [String: Any]; - }; -}; diff --git a/ios/Extensions/FloatingPoint+Clamping.swift b/ios/Extensions/FloatingPoint+Clamping.swift deleted file mode 100644 index c685ba9b..00000000 --- a/ios/Extensions/FloatingPoint+Clamping.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// FloatingPoint+Helpers.swift -// swift-programmatic-modal -// -// Created by Dominic Go on 5/19/23. -// - -import UIKit - -extension FloatingPoint { - public func clamped( - min lowerBound: Self? = nil, - max upperBound: Self? = nil - ) -> Self { - var clampedValue = self; - - if let upperBound = upperBound { - clampedValue = min(clampedValue, upperBound); - }; - - if let lowerBound = lowerBound { - clampedValue = max(clampedValue, lowerBound); - }; - - return clampedValue; - }; - - public func clamped(minMax: Self) -> Self { - self.clamped(min: -minMax, max: minMax); - }; -}; diff --git a/ios/Extensions/KeyWindow+Helpers.swift b/ios/Extensions/KeyWindow+Helpers.swift deleted file mode 100644 index 72933909..00000000 --- a/ios/Extensions/KeyWindow+Helpers.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// KeyWindow+Helpers.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/26/20. -// - -import UIKit - -extension UIWindow { - - /// TODO:2023-03-24-01-14-26 - Remove/Replace `UIWindow.key` - static var key: UIWindow? { - if #available(iOS 13, *) { - return UIApplication.shared.windows.first { $0.isKeyWindow }; - - } else { - return UIApplication.shared.keyWindow; - }; - }; -}; diff --git a/ios/Extensions/RNIUtilities+Helpers.swift b/ios/Extensions/RNIUtilities+Helpers.swift deleted file mode 100644 index 1fb0f17a..00000000 --- a/ios/Extensions/RNIUtilities+Helpers.swift +++ /dev/null @@ -1,158 +0,0 @@ -// -// RNIUtilities+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -/// TODO:2023-03-20-21-29-36 - Move to `RNIUtilities` -extension RNIUtilities { - - static func swizzleExchangeMethods( - defaultSelector: Selector, - newSelector: Selector, - forClass class: AnyClass - ) { - let defaultInstace = - class_getInstanceMethod(`class`.self, defaultSelector); - - let newInstance = - class_getInstanceMethod(`class`.self, newSelector); - - guard let defaultInstance = defaultInstace, - let newInstance = newInstance - else { return }; - - method_exchangeImplementations(defaultInstance, newInstance); - }; - - static func getFirstMatchingView( - forNativeID targetNativeID: String, - startingView rootView: UIView - ) -> UIView? { - - for view in rootView.subviews { - if let viewNativeID = view.nativeID, - viewNativeID == targetNativeID { - - return view; - }; - - let matchingView = Self.getFirstMatchingView( - forNativeID: targetNativeID, - startingView: view - ); - - guard let matchingView = matchingView else { continue }; - return matchingView; - }; - - return nil; - }; - - public static func getWindows() -> [UIWindow] { - var windows: [UIWindow] = []; - - #if swift(>=5.5) - // Version: Swift 5.5 and newer - iOS 15 and newer - guard #available(iOS 13.0, *) else { return [] }; - - for scene in UIApplication.shared.connectedScenes { - guard let windowScene = scene as? UIWindowScene else { continue }; - windows += windowScene.windows; - }; - - #elseif swift(>=5) - // Version: Swift 5.4 and below - iOS 14.5 and below - // Note: 'windows' was deprecated in iOS 15.0+ - - // first element is the "key window" - if let keyWindow = - UIApplication.shared.windows.first(where: { $0.isKeyWindow }) { - - windows.append(keyWindow); - }; - - UIApplication.shared.windows.forEach { - // skip if already added - guard !windows.contains($0) else { return }; - windows.append($0); - }; - - #elseif swift(>=4) - // Version: Swift 4 and below - iOS 12.4 and below - // Note: `keyWindow` was deprecated in iOS 13.0+ - - // first element is the "key window" - if let keyWindow = UIApplication.shared.keyWindow { - windows.append(keyWindow); - }; - - UIApplication.shared.windows.forEach { - // skip if already added - guard !windows.contains($0) else { return }; - windows.append($0); - }; - - #else - // Version: Swift 3.1 and below - iOS 10.3 and below - // Note: 'sharedApplication' has been renamed to 'shared' - guard let appDelegate = - UIApplication.sharedApplication().delegate as? AppDelegate, - - let window = appDelegate.window - else { return [] }; - - return windows.append(window); - #endif - - return windows; - }; - - public static func getRootViewController( - for window: UIWindow? = nil - ) -> UIViewController? { - - if let window = window { - return window.rootViewController; - }; - - return Self.getWindows().first?.rootViewController; - }; - - public static func getPresentedViewControllers( - for window: UIWindow? = nil - ) -> [UIViewController] { - guard let rootVC = Self.getRootViewController(for: window) else { - #if DEBUG - print( - "Error - RNIModalManager.getTopMostPresentedVC" - + " - arg window isNil: '\(window == nil)'" - + " - Could not get root view controller" - ); - #endif - return []; - }; - - var presentedVCList: [UIViewController] = [rootVC]; - - // climb the vc hierarchy to find the topmost presented vc - while true { - guard let topVC = presentedVCList.last, - let presentedVC = topVC.presentedViewController - else { break }; - - presentedVCList.append(presentedVC); - }; - - return presentedVCList; - }; - - public static func getTopmostPresentedViewController( - for window: UIWindow? = nil - ) -> UIViewController? { - return Self.getPresentedViewControllers(for: window).last; - }; -}; diff --git a/ios/Extensions/UIGestureRecognizer+Helpers.swift b/ios/Extensions/UIGestureRecognizer+Helpers.swift deleted file mode 100644 index 2615c673..00000000 --- a/ios/Extensions/UIGestureRecognizer+Helpers.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// UIGestureRecognizer+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/22/23. -// - -import UIKit - -extension UIGestureRecognizer.State: CustomStringConvertible { - public var description: String { - switch self { - case .possible : return "possible"; - case .began : return "began"; - case .changed : return "changed"; - case .ended : return "ended"; - case .cancelled: return "cancelled"; - case .failed : return "failed"; - - @unknown default: return ""; - }; - }; -}; diff --git a/ios/Extensions/UIModalTransitionStyle+Helpers.swift b/ios/Extensions/UIModalTransitionStyle+Helpers.swift deleted file mode 100644 index 9799d40d..00000000 --- a/ios/Extensions/UIModalTransitionStyle+Helpers.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// UIModalTransitionStyle+Helpers.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/29/20. -// - -import UIKit - -extension UIModalTransitionStyle: CaseIterable { - public static var allCases: [UIModalTransitionStyle] { - return [ - .coverVertical, - .crossDissolve, - .flipHorizontal, - .partialCurl, - ]; - }; - - public func stringDescription() -> String { - switch self { - case .coverVertical : return "coverVertical"; - case .flipHorizontal: return "flipHorizontal"; - case .crossDissolve : return "crossDissolve"; - case .partialCurl : return "partialCurl"; - - @unknown default: return ""; - }; - }; - - public static func fromString(_ string: String) -> UIModalTransitionStyle? { - return self.allCases.first{ $0.stringDescription() == string }; - }; -}; diff --git a/ios/Extensions/UIView+Helpers.swift b/ios/Extensions/UIView+Helpers.swift deleted file mode 100644 index 139cb5e2..00000000 --- a/ios/Extensions/UIView+Helpers.swift +++ /dev/null @@ -1,60 +0,0 @@ -import UIKit - -/// TODO:2023-03-24-01-14-26 - Move `UIView+Helpers` extension to -/// `react-native-utilities` -/// -extension UIView { - public var parentViewController: UIViewController? { - var parentResponder: UIResponder? = self; - - while parentResponder != nil { - parentResponder = parentResponder!.next - if let viewController = parentResponder as? UIViewController { - return viewController; - }; - }; - - return nil; - }; - - /// Remove all ancestor constraints that are affecting this view instance - /// - /// Note: 2023-03-24-00-39-51 - /// - /// * From: https://stackoverflow.com/questions/24418884/remove-all-constraints-affecting-a-uiview - /// - /// * After it's done executing, your view remains where it was because it - /// creates autoresizing constraints. - /// - /// * When I don't do this the view usually disappears. - /// - /// * Additionally, it doesn't just remove constraints from it's superview, - /// but in addition, it also climbs the view hierarchy, and removes all the - /// constraints affecting the current view instance that came from an - /// ancestor view. - /// - public func removeAllAncestorConstraints() { - var ancestorView = self.superview; - - // Climb the view hierarchy until there are no more parent views... - while ancestorView != nil { - for ancestorConstraint in ancestorView!.constraints { - - let constraintItems = [ - ancestorConstraint.firstItem, - ancestorConstraint.secondItem - ]; - - constraintItems.forEach { - guard ($0 as? UIView) === self else { return }; - ancestorView?.removeConstraint(ancestorConstraint); - }; - - ancestorView = ancestorView?.superview; - }; - }; - - self.removeConstraints(self.constraints); - self.translatesAutoresizingMaskIntoConstraints = true - }; -}; diff --git a/ios/Extensions/UIViewController+Swizzling.swift b/ios/Extensions/UIViewController+Swizzling.swift deleted file mode 100644 index 22457f33..00000000 --- a/ios/Extensions/UIViewController+Swizzling.swift +++ /dev/null @@ -1,235 +0,0 @@ -// -// RNIModalSwizzledViewController.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/11/23. -// - -import UIKit - -extension UIViewController { - - // MARK: - Static - Swizzling-Related - // ---------------------------------- - - static var isSwizzled = false; - - internal static func swizzleMethods() { - guard RNIModalFlagsShared.shouldSwizzleViewControllers else { return }; - - #if DEBUG - print( - "Log - UIViewController+Swizzling" - + " - UIViewController.swizzleMethods invoked" - ); - #endif - - RNIUtilities.swizzleExchangeMethods( - defaultSelector: #selector(Self.present(_:animated:completion:)), - newSelector: #selector(Self._swizzled_present(_:animated:completion:)), - forClass: UIViewController.self - ); - - RNIUtilities.swizzleExchangeMethods( - defaultSelector: #selector(Self.dismiss(animated:completion:)), - newSelector: #selector(Self._swizzled_dismiss(animated:completion:)), - forClass: UIViewController.self - ); - - self.isSwizzled.toggle(); - }; - - // MARK: - Helpers - Static - // ------------------------ - - @discardableResult - static private func registerIfNeeded( - forViewController vc: UIViewController - ) -> RNIModalViewControllerWrapper? { - - let shouldWrapVC = vc is RNIModalViewController - ? RNIModalFlagsShared.shouldWrapAllViewControllers - : true; - - /// If the arg `vc` is a `RNIModalViewController` instance, then we don't - /// need to wrap the current instance inside a - /// `RNIModalViewControllerWrapper` since it will already notify - /// `RNIModalManager` of modal-related events... - /// - guard shouldWrapVC else { return nil }; - - let modalWrapper: RNIModalViewControllerWrapper = { - /// A - Wrapper already exists for arg `vc`, so return the matching - /// wrapper instance. - /// - if let modalWrapper = RNIModalViewControllerWrapperRegistry.get( - forViewController: vc - ) { - return modalWrapper; - }; - - /// B - Wrapper does not exists for arg `vc`, so create a new wrapper - /// instance. - /// - let newModalWrapper = RNIModalViewControllerWrapper(viewController: vc); - - RNIModalViewControllerWrapperRegistry.set( - forViewController: vc, - newModalWrapper - ); - return newModalWrapper; - }(); - - return modalWrapper; - }; - - // MARK: - Helpers - Computed Properties - // ------------------------------------- - - /// Get the associated `RNIModalViewControllerWrapper` instance for the - /// current view controller - /// - var modalWrapper: RNIModalViewControllerWrapper? { - RNIModalViewControllerWrapperRegistry.get(forViewController: self); - }; - - // MARK: - Helpers - Functions - // --------------------------- - - private func getPresentedModalToNotify( - _ presentedVC: UIViewController? = nil - ) -> (any RNIModal)? { - - let presentedModal = RNIModalUtilities.getPresentedModal( - forPresentingViewController: self, - presentedViewController: presentedVC - ); - - return RNIModalFlagsShared.shouldSwizzledViewControllerNotifyAll - ? presentedModal - : presentedModal as? RNIModalViewControllerWrapper; - }; - - private func registerOrInitialize( - _ viewControllerToPresent: UIViewController - ){ - let presentingWrapper = Self.registerIfNeeded(forViewController: self); - - presentingWrapper?.modalViewController = viewControllerToPresent; - presentingWrapper?.presentingViewController = self; - - let presentedWrapper = - Self.registerIfNeeded(forViewController: viewControllerToPresent); - - presentedWrapper?.presentingViewController = self; - }; - - - private func notifyOnModalWillDismiss() -> (() -> Void)? { - guard let presentedModal = self.getPresentedModalToNotify() - else { return nil }; - - presentedModal.notifyWillDismiss(); - - return { - if presentedModal.computedIsModalInFocus { - presentedModal.notifyDidPresent(); - - } else { - presentedModal.notifyDidDismiss(); - }; - }; - }; - - // MARK: - Swizzled Functions - // -------------------------- - - @objc fileprivate func _swizzled_present( - _ viewControllerToPresent: UIViewController, - animated flag: Bool, - completion: (() -> Void)? = nil - ) { - #if DEBUG - print( - "Log - UIViewController+Swizzling" - + " - UIViewController._swizzled_present invoked" - + " - arg viewControllerToPresent: \(viewControllerToPresent)" - + " - arg animated: \(flag)" - ); - #endif - - self.registerOrInitialize(viewControllerToPresent); - - let presentedModal = self.getPresentedModalToNotify(viewControllerToPresent); - presentedModal?.notifyWillPresent(); - - // call original impl. - self._swizzled_present(viewControllerToPresent, animated: flag) { - #if DEBUG - print( - "Log - UIViewController+Swizzling" - + " - UIViewController._swizzled_present" - + " - completion invoked" - ); - #endif - - presentedModal?.notifyDidPresent(); - completion?(); - }; - }; - - @objc fileprivate func _swizzled_dismiss( - animated flag: Bool, - completion: (() -> Void)? = nil - ) { - #if DEBUG - print( - "Log - UIViewController+Swizzling" - + " - UIViewController._swizzled_dismiss invoked" - + " - arg animated: \(flag)" - + " - self.presentedViewController: \(String(describing: presentedViewController))" - ); - #endif - - let notifyOnModalDidDismiss = self.notifyOnModalWillDismiss(); - - // call original impl. - self._swizzled_dismiss(animated: flag) { - #if DEBUG - print( - "Log - UIViewController+Swizzling" - + " - UIViewController._swizzled_dismiss" - + " - completion invoked" - ); - #endif - - notifyOnModalDidDismiss?(); - completion?(); - }; - }; -}; - -// MARK: - Extensions - Helpers -// ---------------------------- - -fileprivate extension RNIModalPresentationNotifying where Self: RNIModal { - func notifyWillPresent() { - guard let delegate = modalPresentationNotificationDelegate else { return }; - delegate.notifyOnModalWillShow(sender: self); - }; - - func notifyDidPresent(){ - guard let delegate = modalPresentationNotificationDelegate else { return }; - delegate.notifyOnModalDidShow(sender: self); - }; - - func notifyWillDismiss(){ - guard let delegate = modalPresentationNotificationDelegate else { return }; - delegate.notifyOnModalWillHide(sender: self); - }; - - func notifyDidDismiss(){ - guard let delegate = modalPresentationNotificationDelegate else { return }; - delegate.notifyOnModalDidHide(sender: self); - }; -}; diff --git a/ios/Extensions/UIWindow+Helpers.swift b/ios/Extensions/UIWindow+Helpers.swift deleted file mode 100644 index fa261a7f..00000000 --- a/ios/Extensions/UIWindow+Helpers.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// UIWindow+WindowMetadata.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/30/23. -// - -import UIKit - -extension UIWindow: RNIObjectMetadata, RNIIdentifiable { - public static var synthesizedIdPrefix = "window-id-"; -}; diff --git a/ios/Helpers+Utilities/CGSize+Helpers.swift b/ios/Helpers+Utilities/CGSize+Helpers.swift deleted file mode 100644 index 389a0c4d..00000000 --- a/ios/Helpers+Utilities/CGSize+Helpers.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// CGSize+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/29/23. -// - -import UIKit - -public extension CGSize { - var isZero: Bool { - self == .zero || (self.width == 0 && self.height == 0); - }; -}; diff --git a/ios/Helpers+Utilities/WeakElement.swift b/ios/Helpers+Utilities/WeakElement.swift deleted file mode 100644 index d480d4f6..00000000 --- a/ios/Helpers+Utilities/WeakElement.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// WeakElement.swift -// RNSwiftReviewer -// -// Created by Dominic Go on 8/15/20. -// - -import UIKit - - -public class WeakElement { - private(set) weak var value: Element?; -}; diff --git a/ios/React Native/RNIAnimator/RNIAnimator.swift b/ios/React Native/RNIAnimator/RNIAnimator.swift deleted file mode 100644 index 599b8a93..00000000 --- a/ios/React Native/RNIAnimator/RNIAnimator.swift +++ /dev/null @@ -1,243 +0,0 @@ -// -// RNIAnimator.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/19/23. -// - -import UIKit - - -public class RNIAnimator { - - // MARK: - Embedded Types - // ---------------------- - - typealias EasingFunction = (_ timing: CGFloat) -> CGFloat; - - public class EasingFunctions { - - static func lerp( - valueStart: CGFloat, - valueEnd: CGFloat, - percent: CGFloat - ) -> CGFloat { - let valueDelta = valueEnd - valueStart; - let valueProgress = valueDelta * percent - return valueStart + valueProgress; - }; - - static func linear(_ time: CGFloat) -> CGFloat { - return time; - }; - - static func easeIn(_ time: CGFloat) -> CGFloat { - return time * time; - }; - }; - - public enum Easing: String { - case linear; - case easeIn; - - var easingFunction: EasingFunction { - switch self { - case .linear: return EasingFunctions.linear; - case .easeIn: return EasingFunctions.easeIn; - }; - }; - }; - - // MARK: - Properties - // ------------------ - - private var displayLink: CADisplayLink?; - - public var easing: Easing = .linear; - - private(set) public var timeStart: CFTimeInterval = 0; - private(set) public var timeEnd: CFTimeInterval = 0; - - private(set) public var timeCurrent: CFTimeInterval = 0; - private(set) public var timeElapsed: CFTimeInterval = 0; - - private(set) public var progress: CGFloat = 0; - private(set) public var duration: CFTimeInterval; - - public let animatedValuesSize: Int; - - private(set) public var animatedValuesStart: [CGFloat]; - private(set) public var animatedValuesEnd: [CGFloat]; - - private(set) public var animatedValuesPrev: [CGFloat] = []; - private(set) public var animatedValuesCurrent: [CGFloat] = []; - - public var allowAnimatedValueToRegress = true; - - // MARK: - Properties - Stored Functions - // ------------------------------------- - - private var applyPendingUpdates: (() -> Void)? = nil; - - public var onAnimatedValueChange: ((_ animatedValues: [CGFloat]) -> Void)?; - public var onAnimationCompletion: (() -> Void)?; - - // MARK: - Properties - Computed - // ----------------------------- - - public var isFinished: Bool { - self.animatedValuesCurrent.enumerated().allSatisfy { - self.animatedValuesStart[$0.offset] < self.animatedValuesEnd[$0.offset] - ? $0.element >= self.animatedValuesEnd[$0.offset] - : $0.element <= self.animatedValuesEnd[$0.offset] - }; - }; - - public var isAnimating: Bool { - self.displayLink != nil - }; - - // MARK: - Init - // ------------ - - public init?( - durationSeconds: CFTimeInterval, - animatedValuesStart: [CGFloat], - animatedValuesEnd: [CGFloat], - onAnimatedValueChange: ((_ animatedValues: [CGFloat]) -> Void)? = nil, - onAnimationCompletion: (() -> Void)? = nil - ) { - guard animatedValuesStart.count == animatedValuesEnd.count else { - return nil; - }; - - self.duration = durationSeconds; - - self.animatedValuesStart = animatedValuesStart; - self.animatedValuesEnd = animatedValuesEnd; - - let arraySize = animatedValuesStart.count; - self.animatedValuesSize = arraySize; - - self.animatedValuesCurrent = [CGFloat](repeating: 0, count: arraySize); - self.animatedValuesPrev = [CGFloat](repeating: 0, count: arraySize); - - self.onAnimatedValueChange = onAnimatedValueChange; - self.onAnimationCompletion = onAnimationCompletion; - }; - - // MARK: - Functions - // ----------------- - - @objc private func onDisplayLinkDidFire(_ displayLink: CADisplayLink){ - - self.timeCurrent = CACurrentMediaTime(); - self.timeElapsed = self.timeCurrent - self.timeStart; - - self.progress = self.timeElapsed / self.duration; - - var didChange = false; - - for index in 0 ..< self.animatedValuesSize { - - let animatedValueNextRaw = Self.EasingFunctions.lerp( - valueStart: self.animatedValuesStart[index], - valueEnd: self.animatedValuesEnd[index], - percent: self.easing.easingFunction(self.progress) - ); - - let animatedValuesStart = self.animatedValuesStart[index]; - let animatedValueEnd = self.animatedValuesEnd[index]; - - // clamp - let animatedValueNext: CGFloat = { - // E.g. 50 -> 100 - if animatedValuesStart <= animatedValueEnd { - return animatedValueNextRaw > animatedValueEnd - ? animatedValueEnd - : animatedValueNextRaw; - - } else { - // E.g. 100 -> 50 - return animatedValueNextRaw < animatedValueEnd - ? animatedValueEnd - : animatedValueNextRaw; - }; - }(); - - let animatedValuePrev = self.animatedValuesPrev[index]; - let animatedValueCurrent = self.animatedValuesCurrent[index]; - - let shouldUpdate = self.allowAnimatedValueToRegress - ? true - : animatedValueNext > animatedValueCurrent; - - guard shouldUpdate else { continue }; - - self.animatedValuesPrev[index] = self.animatedValuesCurrent[index]; - self.animatedValuesCurrent[index] = animatedValueNext; - - if !didChange { - didChange = animatedValuePrev != animatedValueNext; - }; - }; - - if didChange { - self.onAnimatedValueChange?(self.animatedValuesCurrent); - }; - - if self.isFinished { - self.stop(); - self.onAnimationCompletion?(); - }; - - self.applyPendingUpdates?(); - }; - - // MARK: - Functions - Public - // -------------------------- - - public func start(){ - self.stop(); - - self.timeCurrent = CACurrentMediaTime(); - self.timeStart = self.timeCurrent; - self.timeEnd = self.timeCurrent + self.duration; - - let displayLink = CADisplayLink( - target: self, - selector: #selector(Self.onDisplayLinkDidFire(_:)) - ); - - displayLink.add(to: .current, forMode:.default); - self.displayLink = displayLink; - }; - - public func stop() { - self.displayLink?.invalidate(); - self.displayLink = nil; - }; - - public func update( - animatedValuesEnd: [CGFloat], - duration: CGFloat? = nil - ){ - self.applyPendingUpdates = { [unowned self] in - self.animatedValuesStart = self.animatedValuesCurrent; - self.animatedValuesEnd = animatedValuesEnd; - - self.timeCurrent = CACurrentMediaTime(); - - if let newDuration = duration { - self.duration = newDuration; - - } else { - let timeRemaining = self.duration - self.timeElapsed; - self.duration = timeRemaining; - }; - - self.timeStart = self.timeCurrent; - self.timeEnd = self.timeCurrent + self.duration; - }; - }; -}; diff --git a/ios/React Native/RNIAnimator/RNIAnimatorSize.swift b/ios/React Native/RNIAnimator/RNIAnimatorSize.swift deleted file mode 100644 index bcef9d9c..00000000 --- a/ios/React Native/RNIAnimator/RNIAnimatorSize.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// RNIAnimatorSize.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/19/23. -// - -import UIKit - -fileprivate extension CGSize { - init(array: [CGFloat]) { - self = CGSize(width: array[0], height: array[1]); - }; - - var array: [CGFloat] { - return [ - self.width, - self.height - ]; - }; -}; - -public class RNIAnimatorSize: RNIAnimator { - - public init?( - durationSeconds: CFTimeInterval, - sizeStart: CGSize, - sizeEnd: CGSize, - onSizeDidChange: ((_ newSize: CGSize) -> Void)? = nil, - onAnimationCompletion: (() -> Void)? = nil - ) { - super.init( - durationSeconds: durationSeconds, - animatedValuesStart: sizeStart.array, - animatedValuesEnd: sizeEnd.array - ) { - onSizeDidChange?( - CGSize(array: $0) - ); - } onAnimationCompletion: { - onAnimationCompletion?(); - }; - }; - - public func update( - sizeEnd: CGSize, - duration: CGFloat? = nil - ){ - super.update( - animatedValuesEnd: sizeEnd.array, - duration: duration - ); - }; -}; diff --git a/ios/React Native/RNIComputable/RNIComputableOffset.swift b/ios/React Native/RNIComputable/RNIComputableOffset.swift deleted file mode 100644 index 04ab8f72..00000000 --- a/ios/React Native/RNIComputable/RNIComputableOffset.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// RNIComputableOffset.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/28/23. -// - -import UIKit - -public struct RNIComputableOffset { - - public enum OffsetOperation: String { - case multiply, divide, add, subtract; - - func compute(a: Double, b: Double) -> Double { - switch self { - case .add: - return a + b; - - case .divide: - return a / b; - - case .multiply: - return a * b; - - case .subtract: - return a - b; - }; - }; - }; - - public var offset: Double; - public var offsetOperation: OffsetOperation; - - public func compute( - withValue value: Double, - isValueOnRHS: Bool = false - ) -> Double { - if isValueOnRHS { - return self.offsetOperation.compute(a: value, b: self.offset); - }; - - return self.offsetOperation.compute(a: self.offset, b: value); - }; -}; - -extension RNIComputableOffset { - - public init?(fromDict dict: NSDictionary){ - guard let offset = dict["offset"] as? NSNumber else { return nil }; - self.offset = offset.doubleValue; - - self.offsetOperation = { - guard let offsetOperationRaw = dict["offsetOperation"] as? String, - let offsetOperation = OffsetOperation(rawValue: offsetOperationRaw) - else { return .add }; - - return offsetOperation; - }(); - }; -}; diff --git a/ios/React Native/RNIComputable/RNIComputableSize.swift b/ios/React Native/RNIComputable/RNIComputableSize.swift deleted file mode 100644 index 5209adcf..00000000 --- a/ios/React Native/RNIComputable/RNIComputableSize.swift +++ /dev/null @@ -1,148 +0,0 @@ -// -// RNIComputableValue.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/26/23. -// - -import UIKit - -public struct RNIComputableSize { - - // MARK: - Properties - // ------------------ - - public let mode: RNIComputableSizeMode; - - public let offsetWidth: RNIComputableOffset?; - public let offsetHeight: RNIComputableOffset?; - - public let minWidth: CGFloat?; - public let minHeight: CGFloat?; - - public let maxWidth: CGFloat?; - public let maxHeight: CGFloat?; - - // MARK: - Internal Functions - // -------------------------- - - func sizeWithOffsets(forSize size: CGSize) -> CGSize { - let offsetWidth = - self.offsetWidth?.compute(withValue: size.width); - - let offsetHeight = - self.offsetHeight?.compute(withValue: size.height); - - return CGSize( - width: offsetWidth ?? size.width, - height: offsetHeight ?? size.height - ); - }; - - func sizeWithClamp(forSize size: CGSize) -> CGSize { - return CGSize( - width: size.width.clamped( - min: self.minWidth, - max: self.maxWidth - ), - height: size.height.clamped( - min: self.minHeight, - max: self.maxHeight - ) - ); - }; - - // MARK: - Functions - // ----------------- - - public func computeRaw( - withTargetSize targetSize: CGSize, - currentSize: CGSize - ) -> CGSize { - switch self.mode { - case .current: - return currentSize; - - case .stretch: - return targetSize; - - case let .constant(constantWidth, constantHeight): - return CGSize(width: constantWidth, height: constantHeight); - - case let .percent(percentWidth, percentHeight): - return CGSize( - width: percentWidth * targetSize.width, - height: percentHeight * targetSize.height - ); - }; - }; - - public func compute( - withTargetSize targetSize: CGSize, - currentSize: CGSize - ) -> CGSize { - let rawSize = self.computeRaw( - withTargetSize: targetSize, - currentSize: currentSize - ); - - let clampedSize = self.sizeWithClamp(forSize: rawSize); - return self.sizeWithOffsets(forSize: clampedSize); - }; -}; - -extension RNIComputableSize { - public init?(fromDict dict: NSDictionary){ - guard let mode = RNIComputableSizeMode(fromDict: dict) - else { return nil }; - - self.mode = mode; - - self.offsetWidth = { - guard let offsetRaw = dict["offsetWidth"] as? NSDictionary, - let offset = RNIComputableOffset(fromDict: offsetRaw) - else { return nil }; - - return offset; - }(); - - self.offsetHeight = { - guard let offsetRaw = dict["offsetHeight"] as? NSDictionary, - let offset = RNIComputableOffset(fromDict: offsetRaw) - else { return nil }; - - return offset; - }(); - - self.minWidth = - Self.getDoubleValue(forDict: dict, withKey: "minWidth"); - - self.minHeight = - Self.getDoubleValue(forDict: dict, withKey: "minHeight"); - - self.maxWidth = - Self.getDoubleValue(forDict: dict, withKey: "maxWidth"); - - self.maxHeight = - Self.getDoubleValue(forDict: dict, withKey: "maxHeight"); - }; - - public init(mode: RNIComputableSizeMode){ - self.mode = mode; - - self.offsetWidth = nil; - self.offsetHeight = nil; - self.minWidth = nil; - self.minHeight = nil; - self.maxWidth = nil; - self.maxHeight = nil; - }; - - static private func getDoubleValue( - forDict dict: NSDictionary, - withKey key: String - ) -> CGFloat? { - guard let number = dict[key] as? NSNumber else { return nil }; - return number.doubleValue; - }; -}; diff --git a/ios/React Native/RNIComputable/RNIComputableSizeMode.swift b/ios/React Native/RNIComputable/RNIComputableSizeMode.swift deleted file mode 100644 index d2c751fb..00000000 --- a/ios/React Native/RNIComputable/RNIComputableSizeMode.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// RNIComputableSizeOffset.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/28/23. -// - -import UIKit - -public enum RNIComputableSizeMode { - case current; - case stretch; - - case constant( - constantWidth: Double, - constantHeight: Double - ); - - case percent( - percentWidth: Double, - percentHeight: Double - ); -}; - -extension RNIComputableSizeMode { - public init?(fromDict dict: NSDictionary){ - guard let mode = dict["mode"] as? String else { return nil }; - - switch mode { - case "current": - self = .current; - - case "stretch": - self = .stretch; - - case "constant": - guard let width = dict["constantWidth"] as? NSNumber, - let height = dict["constantHeight"] as? NSNumber - else { return nil }; - - self = .constant( - constantWidth: width.doubleValue, - constantHeight: height.doubleValue - ); - - case "percent": - guard let width = dict["percentWidth"] as? NSNumber, - let height = dict["percentHeight"] as? NSNumber - else { return nil }; - - self = .percent( - percentWidth: width.doubleValue, - percentHeight: height.doubleValue - ); - - default: - return nil; - }; - }; -}; diff --git a/ios/React Native/RNIComputable/RNIComputableValue.swift b/ios/React Native/RNIComputable/RNIComputableValue.swift deleted file mode 100644 index 9672b19d..00000000 --- a/ios/React Native/RNIComputable/RNIComputableValue.swift +++ /dev/null @@ -1,116 +0,0 @@ -// -// RNIComputableValue.swift -// swift-programmatic-modal -// -// Created by Dominic Go on 5/19/23. -// - -import UIKit - -public struct RNIComputableValue { - - // MARK: - Properties - // ------------------ - - public let mode: RNIComputableValueMode; - - public let offset: RNIComputableOffset?; - - public let minValue: CGFloat?; - public let maxValue: CGFloat?; - - - // MARK: - Internal Functions - // -------------------------- - - func valueWithOffsets(forValue value: CGFloat) -> CGFloat { - return self.offset?.compute(withValue: value) ?? value; - }; - - func valueWithClamp(forValue value: CGFloat) -> CGFloat { - return value.clamped( - min: self.minValue, - max: self.maxValue - ); - }; - - // MARK: - Functions - // ----------------- - - public func computeRaw( - withTargetValue targetValue: CGFloat, - currentValue: CGFloat - ) -> CGFloat { - switch self.mode { - case .current: - return currentValue; - - case .stretch: - return targetValue; - - case let .constant(constantValue): - return constantValue; - - case let .percent(percentValue): - return percentValue * targetValue; - }; - }; - - public func compute( - withTargetValue targetValue: CGFloat, - currentValue: CGFloat - ) -> CGFloat { - let rawValue = self.computeRaw( - withTargetValue: targetValue, - currentValue: currentValue - ); - - let clampedValue = self.valueWithClamp(forValue: rawValue); - return self.valueWithOffsets(forValue: clampedValue); - }; - - public init( - mode: RNIComputableValueMode, - offset: RNIComputableOffset? = nil, - minValue: CGFloat? = nil, - maxValue: CGFloat? = nil - ) { - self.mode = mode; - self.offset = offset; - self.minValue = minValue; - self.maxValue = maxValue; - }; -}; - -extension RNIComputableValue { - public init?(fromDict dict: NSDictionary){ - guard let mode = RNIComputableValueMode(fromDict: dict) - else { return nil }; - - self.mode = mode; - - self.offset = { - guard let offsetRaw = dict["offset"] as? NSDictionary, - let offset = RNIComputableOffset(fromDict: offsetRaw) - else { return nil }; - - return offset; - }(); - - self.minValue = - Self.getDoubleValue(forDict: dict, withKey: "minValue"); - - self.maxValue = - Self.getDoubleValue(forDict: dict, withKey: "maxValue"); - }; - - - - static private func getDoubleValue( - forDict dict: NSDictionary, - withKey key: String - ) -> CGFloat? { - guard let number = dict[key] as? NSNumber else { return nil }; - return number.doubleValue; - }; -}; diff --git a/ios/React Native/RNIComputable/RNIComputableValueMode.swift b/ios/React Native/RNIComputable/RNIComputableValueMode.swift deleted file mode 100644 index 3e75f8e6..00000000 --- a/ios/React Native/RNIComputable/RNIComputableValueMode.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// RNIComputableValueMode.swift -// swift-programmatic-modal -// -// Created by Dominic Go on 5/19/23. -// - -import UIKit - - -public enum RNIComputableValueMode { - case current; - case stretch; - case constant(constantValue: Double); - case percent(percentValue: Double); -}; - -extension RNIComputableValueMode { - public init?(fromDict dict: NSDictionary){ - guard let mode = dict["mode"] as? String else { return nil }; - - switch mode { - case "current": - self = .current; - - case "stretch": - self = .stretch; - - case "constant": - guard let value = dict["constantValue"] as? NSNumber - else { return nil }; - - self = .constant( - constantValue: value.doubleValue - ); - - case "percent": - guard let value = dict["percentValue"] as? NSNumber - else { return nil }; - - self = .percent(percentValue: value.doubleValue); - - default: - return nil; - }; - }; -}; - diff --git a/ios/React Native/RNIComputable/RNIViewMetadata.swift b/ios/React Native/RNIComputable/RNIViewMetadata.swift deleted file mode 100644 index a8851122..00000000 --- a/ios/React Native/RNIComputable/RNIViewMetadata.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// RNIViewMetadata.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - - -public final class RNIViewMetadata: RNIDictionarySynthesizable { - - public let tag: Int; - - public let reactTag: NSNumber?; - public let nativeID: String?; - - public let parentView: RNIViewMetadata?; - public let subviews: [RNIViewMetadata]?; - - public required init( - fromView view: UIView, - setParentView: Bool = true, - setSubViews: Bool = true - ){ - self.tag = view.tag; - - self.reactTag = { - guard let reactTag = view.reactTag else { return nil }; - return reactTag; - }(); - - self.nativeID = { - guard let nativeID = view.nativeID else { return nil }; - return nativeID; - }(); - - self.parentView = { - guard setParentView, - let parentView = view.superview - else { return nil }; - - return Self.init( - fromView: parentView, - setParentView: false, - setSubViews: false - ); - }(); - - self.subviews = { - guard setSubViews else { return nil }; - - return view.subviews.map { - return Self.init( - fromView: $0, - setParentView: false, - setSubViews: false - ); - }; - }(); - }; -}; diff --git a/ios/React Native/RNIDictionarySynthesizable/RNIDictionaryRepresentable.swift b/ios/React Native/RNIDictionarySynthesizable/RNIDictionaryRepresentable.swift deleted file mode 100644 index 0bb912a4..00000000 --- a/ios/React Native/RNIDictionarySynthesizable/RNIDictionaryRepresentable.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// RNIDictionaryRepresentable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/3/23. -// - -import UIKit - -public protocol RNIDictionaryRepresentable { - var asDictionary: [String: Any] { get }; -}; diff --git a/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable+Default.swift b/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable+Default.swift deleted file mode 100644 index acaec5dd..00000000 --- a/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable+Default.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// RNIDictionarySynthesizable+Default.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -extension RNIDictionarySynthesizable { - - // MARK: - Static Properties - // ------------------------- - - public static var synthesizedDictionaryIgnore: [String] { - []; - }; - - public static var synthesizedDictionaryInlinedProperties: [PartialKeyPath] { - []; - }; - - // MARK: - Static Functions - // ------------------------ - - fileprivate static func recursivelyParseValue( - _ value: Any, - isJSDict: Bool - ) -> Any { - - if let synthesizableDict = value as? (any RNIDictionarySynthesizable) { - return synthesizableDict.synthesizedDictionary(isJSDict: isJSDict); - }; - - if isJSDict, let rawValue = value as? any RawRepresentable { - return rawValue.rawValue; - }; - - if isJSDict, let array = value as? Array { - return array.map { - return Self.recursivelyParseValue($0, isJSDict: isJSDict); - }; - }; - - if isJSDict, let dict = value as? Dictionary { - return dict.mapValues { - return Self.recursivelyParseValue($0, isJSDict: isJSDict); - }; - }; - - if let dictRepresentable = value as? RNIDictionaryRepresentable { - let dict = dictRepresentable.asDictionary; - - guard isJSDict else { return dict }; - return Self.recursivelyParseValue(dict, isJSDict: isJSDict); - }; - - if let encodable = value as? Encodable, - let dict = encodable.asDictionary { - - return dict; - }; - - return value; - }; - - private func mergeInlinedProperties( - withDict baseDict: Dictionary, - isJSDict: Bool - ) -> Dictionary { - - var baseDict = baseDict; - - Self.synthesizedDictionaryInlinedProperties.forEach { - guard let value = self[keyPath: $0] as? (any RNIDictionarySynthesizable) - else { return }; - - let inlinedDict = value.synthesizedDictionary(isJSDict: isJSDict); - baseDict = baseDict.merging(inlinedDict){ old, _ in old }; - }; - - return baseDict; - }; - - private func synthesizedDictionaryUsingDictIgnore( - isJSDict: Bool - ) -> Dictionary { - - let mirror = Mirror(reflecting: self); - let properties = mirror.children; - - #if DEBUG - /// Runtime Check - Verify if `synthesizedDictionaryIgnore` is valid - for propertyKeyToIgnore in Self.synthesizedDictionaryIgnore { - if !properties.contains(where: { $0.label == propertyKeyToIgnore }) { - fatalError( - "Invalid value of '\(propertyKeyToIgnore)' in " - + "'synthesizedDictionaryIgnore' for '\(Self.self)' - " - + "No property named '\(propertyKeyToIgnore)' in '\(Self.self)'" - ); - }; - }; - #endif - - let propertyValueMap = properties.lazy.map { ( - propertyKey: String?, value: Any) -> (String, Any)? in - - guard let propertyKey = propertyKey, - !Self.synthesizedDictionaryIgnore.contains(propertyKey) - else { return nil }; - - let parsedValue = Self.recursivelyParseValue(value, isJSDict: isJSDict); - return (propertyKey, parsedValue); - }; - - let baseDict = Dictionary( - uniqueKeysWithValues: propertyValueMap.compactMap { $0 } - ); - - return self.mergeInlinedProperties( - withDict: baseDict, - isJSDict: isJSDict - ); - }; - - // MARK: - Public Functions - // ------------------------ - - public func synthesizedDictionary( - isJSDict: Bool - ) -> Dictionary { - - return self.synthesizedDictionaryUsingDictIgnore(isJSDict: isJSDict); - }; - - - public var synthesizedJSDictionary: Dictionary { - self.synthesizedDictionary(isJSDict: true); - }; -}; diff --git a/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable.swift b/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable.swift deleted file mode 100644 index 3deda88e..00000000 --- a/ios/React Native/RNIDictionarySynthesizable/RNIDictionarySynthesizable.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// RNIDictionarySynthesizable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/26/23. -// - -import UIKit - -/// Any type that conforms to this protocol will be able to create a dictionary -/// representing the keys and values inside that type -/// -public protocol RNIDictionarySynthesizable { - - /// The names/identifiers of the property to be ignored when - /// `synthesizedDictionary` is created. - /// - static var synthesizedDictionaryIgnore: [String] { get }; - - /// The key path to the property that will be inlined/"squashed together" - /// into `synthesizedDictionary`. - /// - static var synthesizedDictionaryInlinedProperties: - [PartialKeyPath] { get }; - - /// A map of the property names and their respective values - func synthesizedDictionary(isJSDict: Bool) -> Dictionary; -}; - diff --git a/ios/React Native/RNIError/RNIBaseError+Helpers.swift b/ios/React Native/RNIError/RNIBaseError+Helpers.swift deleted file mode 100644 index 2d0d2691..00000000 --- a/ios/React Native/RNIError/RNIBaseError+Helpers.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// RNIBaseError+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/12/23. -// - -import UIKit -import React - -extension RNIBaseError { - - public var errorMessage: String { - var message = "message: \(self.message ?? "N/A")"; - - #if DEBUG - message += " - debugMessage: \(self.debugMessage ?? "N/A")"; - #endif - - if let fileID = self.fileID { - message += "- fileID: \(fileID)"; - }; - - if let functionName = self.functionName { - message += "- functionName: \(functionName)"; - }; - - if let lineNumber = self.lineNumber { - message += "- lineNumber: \(lineNumber)"; - }; - - return message; - }; - - public init( - code: ErrorCode, - message: String? = nil, - debugMessage: String? = nil, - debugData: Dictionary? = nil, - fileID: String? = #fileID, - functionName: String? = #function, - lineNumber: Int? = #line - ) { - self.init( - code: code, - message: message, - debugMessage: debugMessage - ); - - self.fileID = fileID; - self.functionName = functionName; - self.lineNumber = lineNumber; - }; - - public init( - code: ErrorCode, - error: Error, - debugMessage: String? = nil, - debugData: Dictionary? = nil, - fileID: String? = #fileID, - functionName: String? = #function, - lineNumber: Int? = #line - ) { - self.init( - code: code, - message: error.localizedDescription, - debugMessage: debugMessage - ); - - self.fileID = fileID; - self.functionName = functionName; - self.lineNumber = lineNumber; - }; - - public mutating func setDebugValues( - fileID: String = #fileID, - functionName: String = #function, - lineNumber: Int = #line - ) { - self.fileID = fileID; - self.functionName = functionName; - self.lineNumber = lineNumber; - }; - - public mutating func addDebugData(_ nextDebugData: Dictionary){ - guard let prevDebugData = self.debugData else { - self.debugData = nextDebugData; - return; - }; - - self.debugData = prevDebugData.merging(nextDebugData) { (_, new) in new }; - }; -}; - -extension RNIBaseError where Self: RNIDictionarySynthesizable { - - public var asNSError: NSError? { - - let errorCode = self.code.errorCode ?? - RNIGenericErrorCode.unspecified.errorCode; - - guard let errorCode = errorCode else { return nil }; - - return NSError( - domain: Self.domain, - code: errorCode, - userInfo: self.synthesizedJSDictionary - ); - }; - - public func invokePromiseRejectBlock( - _ block: @escaping RCTPromiseRejectBlock - ) { - block( - /* code */ self.code.description, - /* message */ self.errorMessage, - /* error */ self.asNSError - ); - }; -}; diff --git a/ios/React Native/RNIError/RNIBaseError.swift b/ios/React Native/RNIError/RNIBaseError.swift deleted file mode 100644 index b19a9770..00000000 --- a/ios/React Native/RNIError/RNIBaseError.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// RNINavigatorError.swift -// react-native-ios-navigator -// -// Created by Dominic Go on 9/11/21. -// - -import UIKit - -/// TODO - Move to `react-native-ios-utilities` -/// * Replace older impl. of `RNIError` with this version - -public protocol RNIBaseError: Error { - - associatedtype ErrorCode: RNIErrorCode; - - static var domain: String { get }; - - var code: ErrorCode { get }; - var message: String? { get }; - - var debugMessage: String? { get }; - var debugData: Dictionary? { get set } - - var fileID : String? { get set }; - var functionName: String? { get set }; - var lineNumber : Int? { get set }; - - init( - code: ErrorCode, - message: String?, - debugMessage: String? - ); -}; diff --git a/ios/React Native/RNIError/RNIError.swift b/ios/React Native/RNIError/RNIError.swift deleted file mode 100644 index 0d96e5d1..00000000 --- a/ios/React Native/RNIError/RNIError.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// RNIError.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/12/23. -// - -import UIKit - -public typealias RNIError = - RNIBaseError & RNIDictionarySynthesizable; - -public typealias RNIErrorCode = - CustomStringConvertible - & CaseIterable - & Equatable - & RNIErrorCodeDefaultable - & RNIErrorCodeSynthesizable; diff --git a/ios/React Native/RNIError/RNIErrorCodeDefaultable.swift b/ios/React Native/RNIError/RNIErrorCodeDefaultable.swift deleted file mode 100644 index 9d5a0310..00000000 --- a/ios/React Native/RNIError/RNIErrorCodeDefaultable.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// RNIGenericErrorDefaultable.swift -// react-native-ios-utilities -// -// Created by Dominic Go on 8/28/22. -// - -import UIKit - -public protocol RNIErrorCodeDefaultable { - - static var runtimeError : Self { get }; - static var libraryError : Self { get }; - static var reactError : Self { get }; - static var unknownError : Self { get }; - static var invalidArgument: Self { get }; - static var outOfBounds : Self { get }; - static var invalidReactTag: Self { get }; - static var nilValue : Self { get }; -}; - -// MARK: - Default -// --------------- - -public extension RNIErrorCodeDefaultable { - - static var runtimeError: Self { - Self.runtimeError - }; - - static var libraryError: Self { - Self.libraryError - }; - - static var reactError: Self { - Self.reactError - }; - - static var unknownError: Self { - Self.unknownError - }; - - static var invalidArgument: Self { - Self.invalidArgument - }; - - static var outOfBounds: Self { - Self.outOfBounds - }; - - static var invalidReactTag: Self { - Self.invalidReactTag - }; - - static var nilValue: Self { - Self.nilValue - }; -}; - -// MARK: - Helpers -// --------------- - -extension RNIErrorCodeDefaultable where Self: RawRepresentable { - - public var description: String { - self.rawValue; - }; -}; - - diff --git a/ios/React Native/RNIError/RNIErrorCodeSynthesizable.swift b/ios/React Native/RNIError/RNIErrorCodeSynthesizable.swift deleted file mode 100644 index c71efffb..00000000 --- a/ios/React Native/RNIError/RNIErrorCodeSynthesizable.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// RNIErrorCodeSynthesizable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/12/23. -// - -import UIKit - -public protocol RNIErrorCodeSynthesizable { - var errorCode: Int? { get }; -} - -extension RNIErrorCodeSynthesizable where Self: CaseIterable & Equatable { - - public var errorCode: Int? { - let match = Self.allCases.enumerated().first { _, value in - value == self - } - - guard let offset = match?.offset else { return nil }; - return offset * -1; - }; -}; diff --git a/ios/React Native/RNIError/RNIGenericErrorCode.swift b/ios/React Native/RNIError/RNIGenericErrorCode.swift deleted file mode 100644 index 9689fe14..00000000 --- a/ios/React Native/RNIError/RNIGenericErrorCode.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// RNIGenericErrorCode.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/12/23. -// - -import UIKit - - -enum RNIGenericErrorCode: - String, CaseIterable, RNIErrorCodeDefaultable, RNIErrorCodeSynthesizable { - - case unspecified; -}; diff --git a/ios/React Native/RNIIdentifiable/RNIIdentifiable+Default.swift b/ios/React Native/RNIIdentifiable/RNIIdentifiable+Default.swift deleted file mode 100644 index 6b25ec6d..00000000 --- a/ios/React Native/RNIIdentifiable/RNIIdentifiable+Default.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// RNIIdentifiable+Default.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -extension RNIIdentifiable { - public static var synthesizedIdPrefix: String { - String(describing: Self.self) + "-"; - }; - - public var synthesizedIdentifier: RNIObjectIdentifier { - if let identifier = self.metadata { - return identifier; - }; - - let identifier = RNIObjectIdentifier(type: Self.self); - self.metadata = identifier; - - return identifier; - }; - - public var synthesizedID: Int { - self.synthesizedIdentifier.id; - }; - - public var synthesizedStringID: String { - Self.synthesizedIdPrefix + "\(self.synthesizedID)"; - }; - - public var synthesizedUUID: UUID { - self.synthesizedIdentifier.uuid; - }; -}; diff --git a/ios/React Native/RNIIdentifiable/RNIIdentifiable.swift b/ios/React Native/RNIIdentifiable/RNIIdentifiable.swift deleted file mode 100644 index e70d473d..00000000 --- a/ios/React Native/RNIIdentifiable/RNIIdentifiable.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// RNIIdentifiable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/31/23. -// - -import UIKit - -public protocol RNIIdentifiable: - AnyObject, RNIObjectMetadata where T == RNIObjectIdentifier { - - static var synthesizedIdPrefix: String { get }; - - var synthesizedID: Int { get }; - - var synthesizedUUID: UUID { get }; - -}; - diff --git a/ios/React Native/RNIIdentifiable/RNIObjectIdentifier.swift b/ios/React Native/RNIIdentifiable/RNIObjectIdentifier.swift deleted file mode 100644 index ed9c839a..00000000 --- a/ios/React Native/RNIIdentifiable/RNIObjectIdentifier.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// RNIObjectIdentifier.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -fileprivate class Counter { - static var typeToCounterMap: Dictionary = [:]; - - static func getTypeString(ofType _type: Any) -> String { - return String(describing: type(of: _type)); - }; - - static func set(forType type: Any, counter: Int) { - let typeString = Self.getTypeString(ofType: type); - Self.typeToCounterMap[typeString] = counter; - }; - - static func set(forType typeString: String, counter: Int) { - Self.typeToCounterMap[typeString] = counter; - }; - - static func get(forType type: Any) -> Int { - let typeString = Self.getTypeString(ofType: type); - - guard let counter = Self.typeToCounterMap[typeString] else { - Self.set(forType: typeString, counter: -1); - return -1; - }; - - return counter; - }; - - static func getAndIncrement(forType type: Any) -> Int { - let prevCount = Self.get(forType: type); - let nextCount = prevCount + 1; - - Self.set(forType: type, counter: nextCount); - return nextCount; - }; -}; - -public final class RNIObjectIdentifier { - - public let id: Int; - public let uuid = UUID(); - - public init(type: Any) { - self.id = Counter.getAndIncrement(forType: type); - }; -}; diff --git a/ios/React Native/RNIModal/RNIModal+Helpers.swift b/ios/React Native/RNIModal/RNIModal+Helpers.swift deleted file mode 100644 index 621a8979..00000000 --- a/ios/React Native/RNIModal/RNIModal+Helpers.swift +++ /dev/null @@ -1,122 +0,0 @@ -// -// RNIModal+Helpers.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/18/23. -// - -import UIKit - -extension RNIModalIdentifiable where Self: RNIIdentifiable { - public var modalNativeID: String { - self.synthesizedStringID - }; -}; - -extension RNIModalIdentifiable { - public var modalUserID: String? { - nil - }; -}; - -extension RNIModalState where Self: RNIModalPresentation { - - internal var synthesizedWindowMapData: RNIWindowMapData? { - guard let window = self.window else { return nil }; - return RNIModalWindowMapShared.get(forWindow: window); - }; - - /// Programmatically check if this instance is presented - public var computedIsModalPresented: Bool { - let listPresentedVC = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - return listPresentedVC.contains { - $0 === self.modalViewController; - }; - }; - - /// Programmatically check if this instance is in focus - public var computedIsModalInFocus: Bool { - let listPresentedVC = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - guard let topmostVC = listPresentedVC.last - else { return self.synthesizedIsModalInFocus }; - - return topmostVC === self.modalViewController; - }; - - /// Note:2023-03-31-15-41-04 - /// - /// * This is based on the view controller hierarchy - /// * So parent/child view controller that aren't modals are also counted - /// - public var computedViewControllerIndex: Int { - let listPresentedVC = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - for (index, vc) in listPresentedVC.enumerated() { - guard vc === self.modalViewController else { continue }; - return index; - }; - - return -1; - }; - - /// Programmatically get the "modal index" - public var computedModalIndex: Int { - guard let window = self.window, - let modalVC = self.modalViewController - else { return -1 }; - - return RNIModalUtilities.computeModalIndex( - forWindow: window, - forViewController: modalVC - ); - }; - - public var currentModalIndex: Int { - self.synthesizedWindowMapData?.modalIndexCurrent ?? -1; - }; - - public var computedCurrentModalIndex: Int { - RNIModalUtilities.computeModalIndex(forWindow: self.window); - }; - - public var synthesizedIsModalInFocus: Bool { - self.modalPresentationState.isPresented && - self.modalFocusState.state.isFocused; - }; -}; - -extension RNIModalState where Self: RNIModal { - - public var synthesizedModalData: RNIModalData { - let purgeCache = - RNIPresentedVCListCache.beginCaching(forWindow: self.window); - - let modalData = RNIModalData( - modalNativeID: self.modalNativeID, - - modalIndex: self.modalIndex, - modalIndexPrev: self.modalIndexPrev, - currentModalIndex: self.currentModalIndex, - - modalFocusState: self.modalFocusState, - modalPresentationState: self.modalPresentationState, - - computedIsModalInFocus: self.computedIsModalInFocus, - computedIsModalPresented: self.computedIsModalPresented, - - computedModalIndex: self.computedModalIndex, - computedViewControllerIndex: self.computedViewControllerIndex, - computedCurrentModalIndex: self.computedCurrentModalIndex, - - synthesizedWindowID: self.window?.synthesizedStringID - ); - - purgeCache(); - return modalData; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModal.swift b/ios/React Native/RNIModal/RNIModal.swift deleted file mode 100644 index 495034aa..00000000 --- a/ios/React Native/RNIModal/RNIModal.swift +++ /dev/null @@ -1,125 +0,0 @@ -// -// RNIModal.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/16/23. -// - -import UIKit - -/// A collection of protocols that the "adoptee" needs to implement in order to -/// be considered a "modal". -/// -public typealias RNIModal = - RNIIdentifiable - & RNIModalIdentifiable - & RNIModalState - & RNIModalRequestable - & RNIModalFocusNotifiable - & RNIModalPresentationNotifying - & RNIModalPresentation; - - -/// Contains modal-related properties for identifying a specific modal instance -/// -/// Specifies that the "adoptee/delegate" that conforms to this protocol must -/// have the specified modal-related properties so that it can be uniquely -/// identified amongst different modal instances. -/// -public protocol RNIModalIdentifiable: AnyObject { - - var modalNativeID: String { get }; - - var modalUserID: String? { get }; -}; - -/// Contains modal-related properties for keeping track of the state of the -/// modal. -/// -/// Specifies that the "adoptee/delegate" that conforms to this protocol must -/// have the specified modal-related properties for keeping track of state -/// -/// The "implementor/delegator" updates these properties; The delegate -/// should treat the properties declared in this protocol as read-only. -/// -public protocol RNIModalState: AnyObject { - - var modalIndexPrev: Int! { set get }; - - var modalIndex: Int! { set get }; - - var modalPresentationState: RNIModalPresentationStateMachine { set get }; - - var modalFocusState: RNIModalFocusStateMachine { set get }; -}; - -/// Contains functions that are invoked to request modal-related actions. -/// -/// The "implementer/delegator" notifies the "adoptee/delegate" of this protocol -/// of requests to perform "modal-related" actions. -/// -public protocol RNIModalRequestable: AnyObject { - - func requestModalToShow( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws; - - func requestModalToHide( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws; -}; - -/// Contains functions that get called whenever a modal-related event occurs. -/// -/// The "implementer/delegator" notifies the "adoptee/delegate" of this protocol -/// of modal focus/blur related events. -/// -/// An interface for the "adoptee/delegate" to receive and handle incoming -/// modal "focus/blur"-related notifications. -/// -public protocol RNIModalFocusNotifiable: AnyObject { - func onModalWillFocusNotification(sender: any RNIModal); - - func onModalDidFocusNotification(sender: any RNIModal); - - func onModalWillBlurNotification(sender: any RNIModal); - - func onModalDidBlurNotification(sender: any RNIModal); -}; - -/// Specifies that the "adoptee/delegate" that conforms to this protocol must -/// notify a delegate of modal presentation-related events -/// -public protocol RNIModalPresentationNotifying: AnyObject { - - /// Notify the "shared modal manager" if the current modal instance is going - /// to be shown or hidden. - /// - /// That focus notification will then be relayed to the other modal instances. - /// - var modalPresentationNotificationDelegate: - RNIModalPresentationNotifiable! { get set }; -}; - -/// Properties related to modal presentation. -/// -/// Specifies that the "adoptee/delegate" that conforms to this protocol must -/// implement this so that the "delegator" understands how the delegate presents -/// the modal. -/// -public protocol RNIModalPresentation: AnyObject { - - /// Returns the modal view controller that is to be presented - var modalViewController: UIViewController? { get }; - - /// Returns the view controller that presented the `modalViewController` - /// instance. - var presentingViewController: UIViewController? { get }; - - /// The "main" window for this instance - var window: UIWindow? { get }; -}; diff --git a/ios/React Native/RNIModal/RNIModalCustomSheetDetent.swift b/ios/React Native/RNIModal/RNIModalCustomSheetDetent.swift deleted file mode 100644 index be772298..00000000 --- a/ios/React Native/RNIModal/RNIModalCustomSheetDetent.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// RNIModalCustomSheetDetent.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/21/23. -// - -import UIKit - -enum RNIModalCustomSheetDetentMode { - - case relative(value: Double); - case constant(value: Double); - - var rawValueString: String { - switch self { - case .constant: return "constant"; - case .relative: return "relative"; - }; - }; -}; - -struct RNIModalCustomSheetDetent { - - typealias OnDetentDidCreate = ( - _ containerTraitCollection: UITraitCollection, - _ maximumDetentValue: CGFloat, - _ computedDetentValue: CGFloat, - _ sender: RNIModalCustomSheetDetent - ) -> Void; - - let mode: RNIModalCustomSheetDetentMode; - let key: String; - - let offset: RNIComputableOffset?; - - let onDetentDidCreate: OnDetentDidCreate?; - - init?( - forDict dict: Dictionary, - onDetentDidCreate: OnDetentDidCreate? = nil - ) { - guard let rawMode = dict["mode"] as? String, - let rawKey = dict["key"] as? String - else { return nil }; - - self.key = rawKey; - self.onDetentDidCreate = onDetentDidCreate; - - let mode: RNIModalCustomSheetDetentMode? = { - switch rawMode { - case "relative": - guard let rawValue = dict["sizeMultiplier"] as? NSNumber - else { return nil }; - - return .relative(value: rawValue.doubleValue); - - case "constant": - guard let rawValue = dict["sizeConstant"] as? NSNumber - else { return nil }; - - return .constant(value: rawValue.doubleValue); - - default: - return nil; - }; - }(); - - guard let mode = mode else { return nil }; - self.mode = mode; - - self.offset = RNIComputableOffset(fromDict: dict as NSDictionary); - }; - - @available(iOS 15.0, *) - var synthesizedDetentIdentifier: - UISheetPresentationController.Detent.Identifier { - - UISheetPresentationController.Detent.Identifier(self.key); - }; - - @available(iOS 16.0, *) - var synthesizedDetent: UISheetPresentationController.Detent { - return .custom(identifier: self.synthesizedDetentIdentifier) { context in - - let computedValueBase: Double = { - switch self.mode { - case let .relative(value): - return value * context.maximumDetentValue; - - case let .constant(value): - return value; - }; - }(); - - let computedValueWithOffset = - self.offset?.compute(withValue: computedValueBase); - - let computedValue = computedValueWithOffset ?? computedValueBase; - - self.onDetentDidCreate?( - context.containerTraitCollection, - context.maximumDetentValue, - computedValue, - self - ); - - return computedValue; - }; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalData.swift b/ios/React Native/RNIModal/RNIModalData.swift deleted file mode 100644 index d8ec76ae..00000000 --- a/ios/React Native/RNIModal/RNIModalData.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// RNIModalData.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/26/23. -// - -import UIKit - -public struct RNIModalData: RNIDictionarySynthesizable { - public let modalNativeID: String; - - public let modalIndex: Int; - public let modalIndexPrev: Int; - public let currentModalIndex: Int; - - public let modalFocusState: RNIModalFocusStateMachine; - public let modalPresentationState: RNIModalPresentationStateMachine; - - public let computedIsModalInFocus: Bool; - public let computedIsModalPresented: Bool; - - public let computedModalIndex: Int; - public let computedViewControllerIndex: Int; - public let computedCurrentModalIndex: Int; - - public let synthesizedWindowID: String?; -}; diff --git a/ios/React Native/RNIModal/RNIModalError.swift b/ios/React Native/RNIModal/RNIModalError.swift deleted file mode 100644 index 3f5e2a85..00000000 --- a/ios/React Native/RNIModal/RNIModalError.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// RNIModalError.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/10/23. -// - -import UIKit - -public enum RNIModalErrorCode: String, RNIErrorCode { - case modalAlreadyVisible, - modalAlreadyHidden, - dismissRejected; -}; - -public struct RNIModalError: RNIError { - - public typealias ErrorCode = RNIModalErrorCode; - - public static var domain = "react-native-ios-modal"; - - public var code: RNIModalErrorCode; - public var message: String?; - - public var debugMessage: String?; - public var debugData: Dictionary?; - - public var fileID: String?; - public var functionName: String?; - public var lineNumber: Int?; - - public init( - code: ErrorCode, - message: String?, - debugMessage: String? - ) { - self.code = code; - self.message = message; - self.debugMessage = debugMessage; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalEventData.swift b/ios/React Native/RNIModal/RNIModalEventData.swift deleted file mode 100644 index 2d2b5189..00000000 --- a/ios/React Native/RNIModal/RNIModalEventData.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// RNIModalEvents.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/26/23. -// - -import UIKit - -public struct RNIModalBaseEventData: RNIDictionarySynthesizable { - - public static var synthesizedDictionaryIgnore: [String] { - ["modalData"] - }; - - public static var synthesizedDictionaryInlinedProperties: [ - PartialKeyPath - ] { - [\.modalData]; - }; - - public let reactTag: Int; - public let modalID: String?; - - public let modalData: RNIModalData; -}; - -public struct RNIOnModalFocusEventData: RNIDictionarySynthesizable { - - public static var synthesizedDictionaryIgnore: [String] { - ["modalData"] - }; - - public static var synthesizedDictionaryInlinedProperties: [ - PartialKeyPath - ] { - [\.modalData]; - }; - - public let modalData: RNIModalBaseEventData; - public let senderInfo: RNIModalData; - - public let isInitial: Bool; -}; - -public struct RNIModalDidChangeSelectedDetentIdentifierEventData: RNIDictionarySynthesizable { - public let sheetDetentStringPrevious: String?; - public let sheetDetentStringCurrent: String?; -}; - -public struct RNIModalDetentDidComputeEventData: RNIDictionarySynthesizable { - public let maximumDetentValue: CGFloat; - public let computedDetentValue: CGFloat; - public let key: String; -}; - -public struct RNIModalSwipeGestureEventData: RNIDictionarySynthesizable { - public let position: CGPoint; -}; - -public struct RNIModalDidSnapEventData: RNIDictionarySynthesizable { - public let selectedDetentIdentifier: String?; - public let modalContentSize: CGSize; -}; diff --git a/ios/React Native/RNIModal/RNIModalFlags.swift b/ios/React Native/RNIModal/RNIModalFlags.swift deleted file mode 100644 index 80491857..00000000 --- a/ios/React Native/RNIModal/RNIModalFlags.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// RNIModalFlags.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -public var RNIModalFlagsShared = RNIModalFlags.sharedInstance; - -public class RNIModalFlags { - static let sharedInstance = RNIModalFlags(); - - var isModalViewPresentationNotificationEnabled = true; - - var shouldSwizzleViewControllers = true; - var shouldSwizzledViewControllerNotifyAll = false; - var shouldWrapAllViewControllers = false; - -}; diff --git a/ios/React Native/RNIModal/RNIModalFocusState.swift b/ios/React Native/RNIModal/RNIModalFocusState.swift deleted file mode 100644 index 003df259..00000000 --- a/ios/React Native/RNIModal/RNIModalFocusState.swift +++ /dev/null @@ -1,142 +0,0 @@ -// -// RNIModalFocusState.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/8/23. -// - -import UIKit - - -public enum RNIModalFocusState: String { - case INITIAL; - - case FOCUSING - case FOCUSED; - - case BLURRING; - case BLURRED; - - // MARK: - Properties - Computed - // ----------------------------- - - public var isInitialized: Bool { - self != .INITIAL - }; - - public var isFocused: Bool { - self == .FOCUSED; - }; - - public var isBlurred: Bool { - self == .BLURRED || self == .INITIAL; - }; - - public var isFocusing: Bool { - self == .FOCUSING; - }; - - public var isBlurring: Bool { - self == .BLURRING; - }; - - public var isTransitioning: Bool { - self.isBlurring || self.isFocusing; - }; - - public var isBlurredOrBlurring: Bool { - self.isBlurred || self.isBlurring; - }; - - public var isFocusedOrFocusing: Bool { - self.isFocused || self.isFocusing; - }; -}; - -public struct RNIModalFocusStateMachine: RNIDictionaryRepresentable { - - // MARK: - Properties - // ------------------ - - private(set) public var state: RNIModalFocusState = .INITIAL; - private(set) public var statePrev: RNIModalFocusState = .INITIAL; - - public var wasBlurCancelled: Bool = false; - public var wasFocusCancelled: Bool = false; - - public var didChange: Bool { - self.statePrev != self.state; - }; - - // MARK: - RNIDictionaryRepresentable - // ---------------------------------- - - public var asDictionary: [String : Any] {[ - "state": self.state, - "statePrev": self.statePrev, - "isFocused": self.state.isFocused, - "isBlurred": self.state.isBlurred, - "isTransitioning": self.state.isTransitioning, - "wasBlurCancelled": self.wasBlurCancelled, - "wasFocusCancelled": self.wasFocusCancelled, - ]}; - - // MARK: - Functions - // ------------------ - - public mutating func set(state nextState: RNIModalFocusState){ - let prevState = self.state; - - // early exit if no change - guard prevState != nextState else { - #if DEBUG - print( - "Error - RNIModalFocusStateMachine.set" - + " - arg nextState: \(nextState)" - + " - prevState: \(prevState)" - + " - No changes, ignoring..." - ); - #endif - return; - }; - - if prevState.isInitialized && !nextState.isInitialized { - /// Going from "initialized state" (e.g. `FOCUSED`, `FOCUSING`, etc), to - /// an "uninitialized state" (i.e. `INITIAL`) is not allowed - return; - - } else { - self.state = nextState; - self.statePrev = prevState; - }; - - if prevState.isBlurring && nextState.isFocusing { - self.wasBlurCancelled = true; - - } else if prevState.isFocusing && nextState.isBlurring { - self.wasFocusCancelled = true; - }; - - #if DEBUG - print( - "Log - RNIModalFocusState.set" - + " - prevState: \(prevState)" - + " - nextState: \(nextState)" - + " - self.wasBlurCancelled: \(self.wasBlurCancelled)" - + " - self.wasFocusCancelled: \(self.wasFocusCancelled)" - ); - #endif - - self.resetIfNeeded(); - }; - - mutating func resetIfNeeded(){ - if self.state.isBlurred { - self.wasBlurCancelled = false; - }; - - if self.state.isFocused { - self.wasFocusCancelled = false; - }; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalManager.swift b/ios/React Native/RNIModal/RNIModalManager.swift deleted file mode 100644 index 9adfe8b7..00000000 --- a/ios/React Native/RNIModal/RNIModalManager.swift +++ /dev/null @@ -1,448 +0,0 @@ -// -// RNIModalManager.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/9/23. -// - -import UIKit - -public let RNIModalManagerShared = RNIModalManager.sharedInstance; - - -/// Archived/Old Notes -/// * `Note:2023-04-07-03-22-48` -/// * `Note:2023-03-30-19-36-33` -/// -public class RNIModalManager { - - // MARK: - Static Properties - // ------------------------- - - public static let sharedInstance = RNIModalManager(); - - // MARK: - Properties - // ------------------ - - private(set) public var modalInstanceDict = - RNIWeakDictionary(); - - private(set) public var windowToCurrentModalIndexMap: - Dictionary = [:]; - - // MARK: - Properties - Computed - // ----------------------------- - - public var modalInstances: [any RNIModal] { - self.modalInstanceDict.dict.compactMap { - $0.value.synthesizedRef; - }; - }; - - public var presentedModals: [any RNIModal] { - self.modalInstances.compactMap { - $0.modalPresentationState.isPresented ? $0 : nil; - }; - }; - - // MARK: - Methods - // --------------- - - public func register(modal: any RNIModal) { - modal.modalIndex = -1; - modal.modalIndexPrev = -1; - - modal.modalPresentationNotificationDelegate = self; - - self.modalInstanceDict[modal.modalNativeID] = modal; - }; - - public func isRegistered(modal: any RNIModal) -> Bool { - self.modalInstances.contains { - $0.modalNativeID == modal.modalNativeID; - }; - }; - - public func isRegistered(viewController: UIViewController) -> Bool { - self.modalInstances.contains { - $0.presentingViewController === viewController - }; - }; - - public func getModalInstance( - forPresentingViewController viewController: UIViewController - ) -> (any RNIModal)? { - self.modalInstances.first { - $0.presentingViewController === viewController; - }; - }; - - public func getModalInstance( - forPresentedViewController viewController: UIViewController - ) -> (any RNIModal)? { - let presentingModal = self.modalInstances.first { - $0.modalViewController === viewController; - }; - - guard let presentingVC = presentingModal?.modalViewController - else { return nil }; - - return self.getModalInstance(forPresentingViewController: presentingVC); - }; - - public func getModalInstances( - forWindow window: UIWindow - ) -> [any RNIModal] { - - return self.modalInstances.filter { - $0.window === window - }; - }; -}; - -// MARK: RNIModalPresentationNotifiable -// ------------------------------------ - -/// The modal instances will notify the manager when they're about to show/hide -/// a modal. -/// -extension RNIModalManager: RNIModalPresentationNotifiable { - - public func notifyOnModalWillShow(sender: any RNIModal) { - guard let senderWindow = sender.window else { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalWillShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - Unable to send event because sender.window is nil" - ); - #endif - return; - }; - - let windowData = RNIModalWindowMapShared.get(forWindow: senderWindow); - guard windowData.nextModalToFocus !== sender else { - #if DEBUG - let nextModalToFocus = windowData.nextModalToFocus!; - print( - "Error - RNIModalManager.notifyOnModalWillShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToFocus.modalNativeID: \(nextModalToFocus.modalNativeID)" - + " - possible multiple invokation" - + " - sender is already about to be in focus" - ); - #endif - return; - }; - - let purgeCache = - RNIPresentedVCListCache.beginCaching(forWindow: senderWindow); - - /// `Note:2023-04-10-20-47-52` - /// * The sender will already be in `presentedModalList` despite it being - /// not fully presented yet. - /// - let presentedModalList = - RNIModalUtilities.getPresentedModals(forWindow: senderWindow); - - #if DEBUG - if windowData.nextModalToFocus != nil { - print( - "Warning - RNIModalManager.notifyOnModalWillShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToFocus is not nil" - + " - a different modal is about to be focused" - ); - }; - #endif - - windowData.set(nextModalToFocus: sender); - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalWillShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - prevModalIndex: \(windowData.modalIndexPrev)" - + " - windowData.modalIndexNext: \(windowData.modalIndexNext_)" - + " - sender.modalIndexPrev: \(sender.modalIndexPrev!)" - + " - sender.modalIndex: \(sender.modalIndex!)" - + " - presentedModalList.count: \(presentedModalList.count)" - ); - #endif - - sender.modalFocusState.set(state: .FOCUSING); - sender.modalPresentationState.set(state: .PRESENTING_UNKNOWN); - - sender.onModalWillFocusNotification(sender: sender); - - presentedModalList.forEach { - guard $0 !== sender, - $0.modalFocusState.state.isFocusedOrFocusing || - $0.modalFocusState.state.isBlurring - else { return }; - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalWillShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - notify BLURRING" - + " - for modal.modalNativeID:\($0.modalNativeID)" - + " - for modal.modalIndex:\($0.modalIndex ?? -1)" - ); - #endif - - $0.modalFocusState.set(state: .BLURRING); - $0.onModalWillBlurNotification(sender: sender); - }; - - if let modalToBlur = presentedModalList.secondToLast { - windowData.nextModalToBlur = modalToBlur; - }; - - purgeCache(); - }; - - public func notifyOnModalDidShow(sender: any RNIModal) { - guard let senderWindow = sender.window else { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalDidShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - Unable to send event because sender.window is nil" - ); - #endif - return; - }; - - let windowData = RNIModalWindowMapShared.get(forWindow: senderWindow); - let nextModalToFocus = windowData.nextModalToFocus - - if nextModalToFocus == nil { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalDidShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToFocus: nil" - + " - possible notifyOnModalWillShow not invoked for sender" - ); - #endif - }; - - #if DEBUG - if nextModalToFocus !== sender { - print( - "Warning - RNIModalManager.notifyOnModalDidShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToFocus.modalNativeID: \(nextModalToFocus?.modalNativeID ?? "N/A")" - + " - nextModalToFocus !== sender" - + " - a different modal is about to focused" - ); - }; - #endif - - let purgeCache = - RNIPresentedVCListCache.beginCaching(forWindow: senderWindow); - - let presentedModalList = - RNIModalUtilities.getPresentedModals(forWindow: senderWindow); - - windowData.apply(forFocusedModal: sender); - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalDidShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - sender.modalIndexPrev: \(sender.modalIndexPrev!)" - + " - sender.modalIndex: \(sender.modalIndex!)" - ); - #endif - - sender.modalFocusState.set(state: .FOCUSED); - sender.modalPresentationState.set(state: .PRESENTED_UNKNOWN); - - sender.onModalDidFocusNotification(sender: sender); - - presentedModalList.forEach { - guard $0 !== sender, - $0.modalFocusState.state.isBlurring - else { return }; - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalDidShow" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - notify BLURRED" - + " - for modal.modalNativeID:\($0.modalNativeID)" - + " - for modal.modalIndex:\($0.modalIndex ?? -1)" - ); - #endif - - $0.modalFocusState.set(state: .BLURRED); - $0.onModalDidBlurNotification(sender: sender); - }; - - // Reset - windowData.nextModalToBlur = nil; - purgeCache(); - }; - - public func notifyOnModalWillHide(sender: any RNIModal) { - guard let senderWindow = sender.window else { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalWillHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - Unable to send event because sender.window is nil" - ); - #endif - return; - }; - - let windowData = RNIModalWindowMapShared.get(forWindow: senderWindow); - guard windowData.nextModalToBlur !== sender else { - #if DEBUG - let nextModalToBlur = windowData.nextModalToBlur!; - print( - "Error - RNIModalManager.notifyOnModalWillHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToBlur.modalNativeID: \(nextModalToBlur.modalNativeID)" - + " - possible multiple invokation" - + " - sender is already about to be blurred" - ); - #endif - return; - }; - - #if DEBUG - if windowData.nextModalToBlur != nil { - print( - "Warning - RNIModalManager.notifyOnModalWillHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToBlur is not nil" - + " - a different modal is about to blur" - ); - }; - #endif - - let purgeCache = - RNIPresentedVCListCache.beginCaching(forWindow: senderWindow); - - let presentedModalList = - RNIModalUtilities.getPresentedModals(forWindow: senderWindow); - - windowData.set(nextModalToBlur: sender); - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalWillHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - prevModalIndex: \(windowData.modalIndexPrev)" - + " - windowData.modalIndexNext: \(windowData.modalIndexNext_)" - + " - sender.modalIndexPrev: \(sender.modalIndexPrev!)" - + " - sender.modalIndex: \(sender.modalIndex!)" - ); - #endif - - sender.modalFocusState.set(state: .BLURRING); - sender.modalPresentationState.set(state: .DISMISSING_UNKNOWN); - - sender.onModalWillBlurNotification(sender: sender); - - guard let modalToFocus = presentedModalList.secondToLast else { - purgeCache(); - return; - }; - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalWillHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - notify FOCUSING" - + " - for modalToFocus.modalNativeID:\(modalToFocus.modalNativeID)" - + " - for modalToFocus.modalIndex:\(modalToFocus.modalIndex ?? -1)" - ); - #endif - - modalToFocus.modalFocusState.set(state: .FOCUSING); - modalToFocus.onModalWillFocusNotification(sender: sender); - - windowData.nextModalToFocus = modalToFocus; - purgeCache(); - }; - - public func notifyOnModalDidHide(sender: any RNIModal) { - guard let senderWindow = sender.window else { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalDidHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - Unable to send event because sender.window is nil" - ); - #endif - return; - }; - - let windowData = RNIModalWindowMapShared.get(forWindow: senderWindow); - guard let nextModalToBlur = windowData.nextModalToBlur else { - #if DEBUG - print( - "Error - RNIModalManager.notifyOnModalDidHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToBlur: nil" - + " - possible notifyOnModalWillHide not invoked for sender" - ); - #endif - return; - }; - - #if DEBUG - if nextModalToBlur !== sender { - print( - "Warning - RNIModalManager.notifyOnModalDidHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - nextModalToBlur.modalNativeID: \(nextModalToBlur.modalNativeID)" - + " - nextModalToBlur !== sender" - + " - a different modal is about to be blurred" - ); - }; - #endif - - let purgeCache = - RNIPresentedVCListCache.beginCaching(forWindow: senderWindow); - - windowData.apply(forBlurredModal: sender); - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalDidHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - sender.modalIndexPrev: \(sender.modalIndexPrev!)" - + " - sender.modalIndex: \(sender.modalIndex!)" - ); - #endif - - sender.modalFocusState.set(state: .BLURRED); - sender.modalPresentationState.set(state: .DISMISSED); - - sender.onModalDidBlurNotification(sender: sender); - - guard let modalToFocus = windowData.nextModalToFocus else { return }; - - #if DEBUG - print( - "Log - RNIModalManager.notifyOnModalDidHide" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - notify FOCUSED" - + " - for modal.modalNativeID:\(modalToFocus.modalNativeID)" - + " - for modal.modalIndex:\(modalToFocus.modalIndex ?? -1)" - ); - #endif - - modalToFocus.modalFocusState.set(state: .FOCUSED); - modalToFocus.onModalDidFocusNotification(sender: sender); - - // reset - windowData.nextModalToFocus = nil; - purgeCache(); - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalPresentationNotifiable.swift b/ios/React Native/RNIModal/RNIModalPresentationNotifiable.swift deleted file mode 100644 index 2287b353..00000000 --- a/ios/React Native/RNIModal/RNIModalPresentationNotifiable.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// RNIModalPresentationNotifiable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/10/23. -// - -import UIKit - -public protocol RNIModalPresentationNotifiable: AnyObject { - - func notifyOnModalWillShow(sender: any RNIModal); - - func notifyOnModalDidShow(sender: any RNIModal); - - func notifyOnModalWillHide(sender: any RNIModal); - - func notifyOnModalDidHide(sender: any RNIModal); -}; diff --git a/ios/React Native/RNIModal/RNIModalPresentationState.swift b/ios/React Native/RNIModal/RNIModalPresentationState.swift deleted file mode 100644 index 8217fe6c..00000000 --- a/ios/React Native/RNIModal/RNIModalPresentationState.swift +++ /dev/null @@ -1,303 +0,0 @@ -// -// RNIModalPresentationState.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/7/23. -// - -import UIKit - - -public enum RNIModalPresentationState: String, CaseIterable { - - // MARK: - Enum Cases - // ------------------ - - case INITIAL; - - case PRESENTING_PROGRAMMATIC; - case PRESENTING_UNKNOWN; - - case PRESENTED; - case PRESENTED_UNKNOWN; - - case DISMISSING_GESTURE; - case DISMISSING_PROGRAMMATIC; - case DISMISSING_UNKNOWN; - - case DISMISS_GESTURE_CANCELLING; - - case DISMISSED; - - // MARK: - Computed Properties - Private - // ------------------------------------- - - fileprivate var step: Int { - switch self { - case .INITIAL: - return 0; - - case .PRESENTING_PROGRAMMATIC: fallthrough; - case .PRESENTING_UNKNOWN : - return 1; - - case .PRESENTED : fallthrough - case .PRESENTED_UNKNOWN: - return 2; - - case .DISMISSING_GESTURE : fallthrough; - case .DISMISSING_PROGRAMMATIC: fallthrough; - case .DISMISSING_UNKNOWN : - return 3; - - case .DISMISS_GESTURE_CANCELLING: - return 4; - - case .DISMISSED: - return 5; - }; - }; - - // MARK: - Computed Properties - Public - // ------------------------------------ - - public var isDismissing: Bool { - switch self { - case .DISMISSING_UNKNOWN, - .DISMISSING_GESTURE, - .DISMISSING_PROGRAMMATIC: - return true; - - default: - return false; - }; - }; - - public var isDismissingKnown: Bool { - self.isDismissing && self != .DISMISSING_UNKNOWN; - }; - - public var isPresenting: Bool { - switch self { - case .PRESENTING_PROGRAMMATIC, - .PRESENTING_UNKNOWN, - .DISMISS_GESTURE_CANCELLING: - return true; - - default: - return false; - }; - }; - - public var isPresented: Bool { - switch self { - case .PRESENTED, - .PRESENTED_UNKNOWN: - return true; - - default: - return false; - }; - }; - - public var isNotSpecific: Bool { - switch self { - case .PRESENTED_UNKNOWN, - .PRESENTING_UNKNOWN, - .DISMISSING_UNKNOWN: - return true; - - default: - return false; - }; - }; - - // MARK: - Computed Properties - Alias - // ----------------------------------- - - public var isDismissViaGestureCancelling: Bool { - self == .DISMISS_GESTURE_CANCELLING; - }; - - public var isDismissingViaGesture: Bool { - self == .DISMISSING_GESTURE - }; - - public var isDismissed: Bool { - self == .DISMISSED || self == .INITIAL; - }; - - // MARK: - Computed Properties - Composite - // --------------------------------------- - - public var isDismissedOrDismissing: Bool { - self.isDismissed || self.isDismissing; - }; - - public var isPresentedOrPresenting: Bool { - self.isPresented || self.isPresenting; - }; -}; - -public struct RNIModalPresentationStateMachine: RNIDictionaryRepresentable { - - // MARK: - Properties - // ------------------ - - private(set) public var state: RNIModalPresentationState = .INITIAL; - private(set) public var statePrev: RNIModalPresentationState = .INITIAL; - - // MARK: - Properties - Completion Handlers - // ---------------------------------------- - - public var onDismissWillCancel: (() -> Void)?; - public var onDismissDidCancel: (() -> Void)?; - - // MARK: - Properties - // ------------------ - - private var _isInitialPresent: Bool? = nil; - private var _wasCancelledDismiss: Bool = false; - - public var wasCancelledPresent: Bool = false; - public var wasCancelledDismissViaGesture: Bool = false; - - // MARK: - Computed Properties - // --------------------------- - - public var isInitialPresent: Bool { - self._isInitialPresent ?? true; - }; - - public var isPresented: Bool { - self.state.isPresented - }; - - public var wasCancelledDismiss: Bool { - self._wasCancelledDismiss || self.wasCancelledDismissViaGesture; - }; - - public var didChange: Bool { - self.statePrev != self.state; - }; - - // MARK: RNIDictionaryRepresentable - // -------------------------------- - - public var asDictionary: [String : Any] {[ - "state": self.state, - "statePrev": self.statePrev, - "isInitialPresent": self.isInitialPresent, - "isPresented": self.isPresented, - "isDismissed": self.state.isDismissed, - "wasCancelledDismiss": self.wasCancelledDismiss, - "wasCancelledPresent": self.wasCancelledPresent, - "wasCancelledDismissViaGesture": self.wasCancelledDismissViaGesture, - ]}; - - // MARK: - Functions - // ----------------- - - init( - onDismissWillCancel: ( () -> Void)? = nil, - onDismissDidCancel: ( () -> Void)? = nil - ) { - self.onDismissWillCancel = onDismissWillCancel; - self.onDismissDidCancel = onDismissDidCancel; - } - - public mutating func set(state nextState: RNIModalPresentationState){ - let prevState = self.state; - - guard prevState != nextState else { - // early exit if no change - return - }; - - let isBecomingUnknown = !prevState.isNotSpecific && nextState.isNotSpecific; - let isSameStep = prevState.step == nextState.step; - - /// Do not over-write specific/"known state", with non-specific/"unknown - /// state", e.g. - /// - /// * ✅: `PRESENTING_UNKNOWN` -> `PRESENTING_PROGRAMMATIC` - /// * ❌: `DISMISSING_GESTURE` -> `DISMISSING_UNKNOWN` - /// - if isSameStep { - if !isBecomingUnknown { - self.state = nextState; - }; - - #if DEBUG - print( - "Warning - RNIModalPresentationStateMachine.set" - + " - prevState: \(prevState)" - + " - nextState: \(nextState)" - ); - #endif - return; - }; - - self.statePrev = prevState; - - if prevState.isDismissingViaGesture && nextState.isPresenting { - self.wasCancelledDismissViaGesture = true; - self.state = .DISMISS_GESTURE_CANCELLING; - self.onDismissWillCancel?(); - - } else if prevState.isDismissViaGestureCancelling && nextState.isPresented { - self.state = nextState; - self.onDismissDidCancel?(); - - } else { - self.state = nextState; - }; - - self.updateProperties(); - self.resetIfNeeded(); - - #if DEBUG - print( - "Log - RNIModalPresentationStateMachine.set" - + " - statePrev: \(self.statePrev)" - + " - nextState: \(self.state)" - + " - isInitialPresent: \(self.isInitialPresent)" - + " - wasCancelledPresent: \(self.wasCancelledPresent)" - + " - wasCancelledDismiss: \(self.wasCancelledDismiss)" - + " - wasCancelledDismissViaGesture: \(self.wasCancelledDismissViaGesture)" - ); - #endif - }; - - private mutating func updateProperties(){ - let nextState = self.state; - let prevState = self.statePrev; - - if nextState.isPresenting && self._isInitialPresent == nil { - self._isInitialPresent = true; - - } else if nextState.isPresenting && self._isInitialPresent == true { - self._isInitialPresent = false; - }; - - if prevState.isPresenting && nextState.isDismissedOrDismissing { - self.wasCancelledPresent = true; - - } else if prevState.isDismissing && nextState.isPresentedOrPresenting { - self._wasCancelledDismiss = true; - }; - }; - - private mutating func resetIfNeeded(){ - if self.state.isPresented { - self.wasCancelledPresent = false; - - } else if self.state == .DISMISSED { - // reset - self.wasCancelledDismissViaGesture = false; - self.wasCancelledPresent = false; - self._isInitialPresent = nil; - self._wasCancelledDismiss = false; - }; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalPresentationTrigger.swift b/ios/React Native/RNIModal/RNIModalPresentationTrigger.swift deleted file mode 100644 index c66c3b3d..00000000 --- a/ios/React Native/RNIModal/RNIModalPresentationTrigger.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// RNIModalPresentationTrigger.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/7/23. -// - -import UIKit - -public enum RNIModalPresentationTrigger: String { - case programmatic; - case gesture; - case request; - case reordering; - case unknown; -}; diff --git a/ios/React Native/RNIModal/RNIModalUtilities.swift b/ios/React Native/RNIModal/RNIModalUtilities.swift deleted file mode 100644 index 79335fb8..00000000 --- a/ios/React Native/RNIModal/RNIModalUtilities.swift +++ /dev/null @@ -1,121 +0,0 @@ -// -// RNIModalUtilities.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/1/23. -// - -import UIKit - -public class RNIModalUtilities { - - static func getPresentedModals( - forWindow window: UIWindow - ) -> [any RNIModal] { - - let vcItems = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - return vcItems.compactMap { - guard let modalVC = $0 as? RNIModalViewController else { return nil }; - return modalVC.modalViewRef; - }; - }; - - static func computeModalIndex( - forWindow window: UIWindow, - forViewController viewController: UIViewController? = nil - ) -> Int { - - let listPresentedVC = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - var index = -1; - - for vc in listPresentedVC { - if vc.presentingViewController != nil { - index += 1; - }; - - /// A - no `viewController` arg., keep counting until all items in - /// `listPresentedVC` have been exhausted. - guard viewController == nil else { continue }; - - /// B - `viewController` arg. specified, stop counting if found matching - /// instance of `viewController` in `listPresentedVC`. - guard viewController !== vc - else { break }; - }; - - return index; - }; - - static func computeModalIndex( - forWindow window: UIWindow?, - forViewController viewController: UIViewController? = nil - ) -> Int { - guard let window = window else { return -1 }; - - return Self.computeModalIndex( - forWindow: window, - forViewController: viewController - ); - }; - - static func getPresentedModal( - forPresentingViewController presentingVC: UIViewController, - presentedViewController presentedVC: UIViewController? = nil - ) -> (any RNIModal)? { - - let presentedVC = presentedVC ?? presentingVC.presentedViewController; - - /// A - `presentedVC` is a `RNIModalViewController`. - if let presentedModalVC = presentedVC as? RNIModalViewController { - return presentedModalVC.modalViewRef; - }; - - /// B - `presentingVC` is a `RNIModalViewController`. - if let presentingModalVC = presentingVC as? RNIModalViewController, - let presentingModal = presentingModalVC.modalViewRef, - let presentedModalVC = presentingModal.modalVC, - let presentedModal = presentedModalVC.modalViewRef { - - return presentedModal; - }; - - /// C - `presentedVC` has a corresponding `RNIModalViewControllerWrapper` - /// instance associated to it. - if let presentedVC = presentedVC, - let presentedModalWrapper = RNIModalViewControllerWrapperRegistry.get( - forViewController: presentedVC - ) { - - return presentedModalWrapper; - }; - - /// D - `presentingVC` has a `RNIModalViewControllerWrapper` instance - /// associated to it. - if let presentingModalWrapper = RNIModalViewControllerWrapperRegistry.get( - forViewController: presentingVC - ), - let presentedVC = presentingModalWrapper.modalViewController, - let presentedModalWrapper = RNIModalViewControllerWrapperRegistry.get( - forViewController: presentedVC - ) { - - return presentedModalWrapper; - }; - - let topmostVC = RNIUtilities.getTopmostPresentedViewController( - for: presentingVC.view.window - ); - - if let topmostModalVC = topmostVC as? RNIModalViewController, - let topmostModal = topmostModalVC.modalViewRef { - - return topmostModal; - }; - - return nil; - }; -}; diff --git a/ios/React Native/RNIModal/RNIModalWindowMap.swift b/ios/React Native/RNIModal/RNIModalWindowMap.swift deleted file mode 100644 index 437c4ed4..00000000 --- a/ios/React Native/RNIModal/RNIModalWindowMap.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// RNIModalWindowMap.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/8/23. -// - -import UIKit - - -internal class RNIWindowMapData { - - // MARK: - Properties - // ------------------ - - weak var window: UIWindow?; - - private(set) var modalIndexCurrent: Int = -1; - private(set) var modalIndexPrev: Int = -1; - private(set) var modalIndexNext: Int?; - - weak var nextModalToFocus: (any RNIModal)?; - weak var nextModalToBlur: (any RNIModal)?; - - #if DEBUG - var modalIndexNext_: String { - self.modalIndexNext == nil ? "N/A" : "\(self.modalIndexNext!)" - }; - #endif - - // MARK: - Functions - // ----------------- - - init(window: UIWindow){ - self.window = window; - }; - - func set(nextModalToFocus modalToFocus: any RNIModal) { - self.nextModalToFocus = modalToFocus; - - let modalIndexCurrent = - RNIModalUtilities.computeModalIndex(forWindow: modalToFocus.window); - - let modalIndexPrev = self.modalIndexCurrent; - - self.modalIndexCurrent = modalIndexCurrent; - self.modalIndexNext = modalIndexCurrent + 1; - self.modalIndexPrev = modalIndexPrev; - }; - - func apply(forFocusedModal focusedModal: any RNIModal) { - self.nextModalToFocus = nil; - - let modalIndexCurrent = - RNIModalUtilities.computeModalIndex(forWindow: focusedModal.window); - - let modalIndexPrev = self.modalIndexCurrent; - - self.modalIndexCurrent = modalIndexCurrent; - self.modalIndexNext = nil; - self.modalIndexPrev = modalIndexPrev; - - focusedModal.modalIndexPrev = modalIndexPrev; - focusedModal.modalIndex = modalIndexCurrent; - }; - - func set(nextModalToBlur modalToBlur: any RNIModal) { - self.nextModalToBlur = modalToBlur; - - let modalIndexCurrent = - RNIModalUtilities.computeModalIndex(forWindow: modalToBlur.window); - - let modalIndexPrev = self.modalIndexCurrent; - - self.modalIndexCurrent = modalIndexCurrent; - self.modalIndexNext = modalIndexCurrent - 1; - self.modalIndexPrev = modalIndexPrev; - }; - - func apply(forBlurredModal blurredModal: any RNIModal) { - self.nextModalToBlur = nil; - - let modalIndexCurrent = - RNIModalUtilities.computeModalIndex(forWindow: blurredModal.window); - - let modalIndexPrev = self.modalIndexCurrent; - - self.modalIndexCurrent = modalIndexCurrent; - self.modalIndexNext = nil; - self.modalIndexPrev = modalIndexPrev; - - blurredModal.modalIndexPrev = modalIndexPrev; - blurredModal.modalIndex = modalIndexCurrent; - }; - - // MARK: - Properties - Computed - // ----------------------------- - - var windowID: String? { - self.window?.synthesizedStringID; - }; -}; - -// MARK: - RNIModalWindowMap -// ------------------------- - -internal let RNIModalWindowMapShared = RNIModalWindowMap.sharedInstance; - -internal class RNIModalWindowMap { - - // MARK: - Properties - Static - // --------------------------- - - static var sharedInstance = RNIModalWindowMap(); - - // MARK: - Properties - // ------------------ - - private(set) var windowDataMap: Dictionary = [:]; - - // MARK: - Functions - // ----------------- - - func set(forWindow window: UIWindow, data: RNIWindowMapData){ - self.windowDataMap[window.synthesizedStringID] = data; - }; - - func get(forWindow window: UIWindow) -> RNIWindowMapData { - guard let windowData = self.windowDataMap[window.synthesizedStringID] else { - // No corresponding "modal index" for window yet, so initialize - // with value - let windowDataNew = RNIWindowMapData(window: window); - self.set(forWindow: window, data: windowDataNew); - - return windowDataNew; - }; - - return windowData; - }; -}; diff --git a/ios/React Native/RNIModal/RNIPresentedViewControllerCache.swift b/ios/React Native/RNIModal/RNIPresentedViewControllerCache.swift deleted file mode 100644 index 915190b2..00000000 --- a/ios/React Native/RNIModal/RNIPresentedViewControllerCache.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// RNIPresentedViewControllerCache.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/1/23. -// - -import UIKit - -let RNIPresentedVCListCache = RNIPresentedViewControllerCache.shared; - -class RNIPresentedViewControllerCache { - class Cache { - weak var targetWindow: UIWindow? = nil; - - var cacheRequestCount = 0; - - // note: this retains the vc instances... - var cache: [UIViewController]?; - - func clear(){ - self.targetWindow = nil; - self.cache = nil; - }; - }; - - static let shared = RNIPresentedViewControllerCache(); - - var map: Dictionary = [:]; - - func beginCaching(forWindow window: UIWindow?) -> () -> Void { - guard let window = window else { return {} }; - let windowID = window.synthesizedStringID; - - let cache: Cache = { - if let cache = self.map[windowID] { - return cache; - }; - - let newCache = Cache(); - newCache.targetWindow = window; - newCache.cache = RNIUtilities.getPresentedViewControllers(for: window); - - self.map[windowID] = newCache; - return newCache; - }(); - - cache.cacheRequestCount += 1; - - return { - cache.cacheRequestCount -= 1; - - guard cache.cacheRequestCount <= 0 else { return }; - - cache.clear(); - self.map.removeValue(forKey: windowID); - }; - }; - - func getPresentedViewControllers( - forWindow window: UIWindow? - ) -> [UIViewController] { - guard let windowID = window?.synthesizedStringID, - let cacheContainer = self.map[windowID], - let vcItemsCached = cacheContainer.cache - else { - return RNIUtilities.getPresentedViewControllers(for: window); - }; - - return vcItemsCached; - }; -}; diff --git a/ios/React Native/RNIModalView/RNIModalView.swift b/ios/React Native/RNIModalView/RNIModalView.swift deleted file mode 100644 index 4de3acc8..00000000 --- a/ios/React Native/RNIModalView/RNIModalView.swift +++ /dev/null @@ -1,1285 +0,0 @@ -// -// RNIModalView.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/9/20. -// Copyright © 2020 Facebook. All rights reserved. -// - -import Foundation -import React - -public class RNIModalView: - UIView, RNIIdentifiable, RNIModalIdentifiable, RNIModalPresentationNotifying, - RNIModalState, RNIModalPresentation { - - public typealias CompletionHandler = () -> Void; - - enum NativeIDKey: String { - case modalViewContent; - }; - - // MARK: - Properties - RNIIdentifiable - // ------------------------------------ - - public static var synthesizedIdPrefix: String = "modal-id-"; - - // MARK: - Properties - // ------------------ - - weak var bridge: RCTBridge?; - - var modalContentWrapper: RNIWrapperView?; - public var modalVC: RNIModalViewController?; - - public var sheetDetentStringCurrent: String?; - public var sheetDetentStringPrevious: String?; - - // MARK: - Properties - RNIModalPresentationNotifying - // -------------------------------------------------- - - public weak var modalPresentationNotificationDelegate: - RNIModalPresentationNotifiable!; - - // MARK: - Properties - RNIModalIdentifiable - // ----------------------------------------- - - public var modalUserID: String? { - self.modalID as? String - }; - - // MARK: - Properties - RNIModalState - // ---------------------------------- - - public var modalIndex: Int!; - public var modalIndexPrev: Int!; - - public lazy var modalPresentationState = RNIModalPresentationStateMachine( - onDismissWillCancel: { [unowned self] in - let eventData = self.synthesizedBaseEventData; - self.onModalDismissWillCancel?( - eventData.synthesizedJSDictionary - ); - }, - - onDismissDidCancel: { [unowned self] in - let eventData = self.synthesizedBaseEventData; - self.onModalDismissDidCancel?( - eventData.synthesizedJSDictionary - ); - } - ); - - public var modalFocusState = RNIModalFocusStateMachine(); - - // MARK: - Properties - RNIModalPresentation - // ----------------------------------------- - - public var modalViewController: UIViewController? { - self.modalVC; - }; - - public weak var presentingViewController: UIViewController?; - - // MARK: - Properties: React Props - Events - // ---------------------------------------- - - @objc var onModalWillPresent: RCTBubblingEventBlock?; - @objc var onModalDidPresent: RCTBubblingEventBlock?; - - @objc var onModalWillDismiss: RCTBubblingEventBlock?; - @objc var onModalDidDismiss: RCTBubblingEventBlock?; - - @objc var onModalWillShow: RCTBubblingEventBlock?; - @objc var onModalDidShow: RCTBubblingEventBlock?; - - @objc var onModalWillHide: RCTBubblingEventBlock?; - @objc var onModalDidHide: RCTBubblingEventBlock?; - - @objc var onModalWillFocus: RCTBubblingEventBlock?; - @objc var onModalDidFocus: RCTBubblingEventBlock?; - - @objc var onModalWillBlur: RCTBubblingEventBlock?; - @objc var onModalDidBlur: RCTBubblingEventBlock?; - - @objc var onPresentationControllerWillDismiss: RCTBubblingEventBlock?; - @objc var onPresentationControllerDidDismiss: RCTBubblingEventBlock?; - @objc var onPresentationControllerDidAttemptToDismiss: RCTBubblingEventBlock?; - - @objc var onModalDetentDidCompute: RCTBubblingEventBlock?; - @objc var onModalDidChangeSelectedDetentIdentifier: RCTBubblingEventBlock?; - - @objc var onModalDidSnap: RCTBubblingEventBlock?; - - @objc var onModalSwipeGestureStart: RCTBubblingEventBlock?; - @objc var onModalSwipeGestureDidEnd: RCTBubblingEventBlock?; - - @objc var onModalDismissWillCancel: RCTBubblingEventBlock?; - @objc var onModalDismissDidCancel: RCTBubblingEventBlock?; - - // MARK: - Properties: React Props - General - // ----------------------------------------- - - /// user-provided identifier for this modal - @objc var modalID: NSString? = nil; - - @objc var modalContentPreferredContentSize: NSDictionary? { - didSet { - self.modalVC?.setPreferredContentSize(withWindow: self.window); - } - }; - - // MARK: - Properties: React Props - BG-Related - // -------------------------------------------- - - @objc var isModalBGBlurred: Bool = true { - didSet { - guard oldValue != self.isModalBGBlurred else { return }; - self.modalVC?.isBGBlurred = self.isModalBGBlurred; - } - }; - - @objc var isModalBGTransparent: Bool = true { - didSet { - guard oldValue != self.isModalBGTransparent else { return }; - self.modalVC?.isBGTransparent = self.isModalBGTransparent; - } - }; - - @objc var modalBGBlurEffectStyle: NSString = "" { - didSet { - guard oldValue != self.modalBGBlurEffectStyle - else { return }; - - self.modalVC?.blurEffectStyle = self.synthesizedModalBGBlurEffectStyle; - } - }; - - // MARK: - Properties: React Props - Presentation/Transition - // --------------------------------------------------------- - - @objc var modalPresentationStyle: NSString = ""; - - @objc var modalTransitionStyle: NSString = ""; - - @objc var hideNonVisibleModals: Bool = false; - - /// control modal present/dismiss by mounting/un-mounting the react subview - /// * `true`: the modal is presented/dismissed when the view is mounted - /// or unmounted - /// - /// * `false`: the modal is presented/dismissed by calling the functions from - /// js/react - /// - @objc var presentViaMount: Bool = false; - - /// disable swipe gesture recognizer for this modal - @objc var enableSwipeGesture: Bool = true { - didSet { - let newValue = self.enableSwipeGesture; - guard newValue != oldValue else { return }; - - self.modalGestureRecognizer?.isEnabled = newValue; - } - }; - - /// allow modal to be programmatically closed even when not current focused - /// * `true`: the modal can be dismissed even when it's not the topmost - /// presented modal. - /// - /// * `false`: the modal can only be dismissed if it's in focus, otherwise - /// error. - /// - @objc var allowModalForceDismiss: Bool = true; - - @objc var isModalInPresentation: Bool = false { - willSet { - guard #available(iOS 13.0, *), - let vc = self.modalVC - else { return }; - - vc.isModalInPresentation = newValue - } - }; - - // MARK: - Properties: React Props - Sheet-Related - // ----------------------------------------------- - - @objc var modalSheetDetents: NSArray?; - - @objc var sheetPrefersScrollingExpandsWhenScrolledToEdge: Bool = true { - willSet { - guard #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - sheetController.prefersScrollingExpandsWhenScrolledToEdge = newValue; - } - }; - - @objc var sheetPrefersEdgeAttachedInCompactHeight: Bool = false { - willSet { - guard #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - self.sheetAnimateChangesIfNeeded { - sheetController.prefersEdgeAttachedInCompactHeight = newValue; - }; - } - }; - - @objc var sheetWidthFollowsPreferredContentSizeWhenEdgeAttached: Bool = false { - willSet { - guard #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - sheetController - .widthFollowsPreferredContentSizeWhenEdgeAttached = newValue; - } - }; - - @objc var sheetPrefersGrabberVisible: Bool = false { - willSet { - guard #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - self.sheetAnimateChangesIfNeeded { - sheetController.prefersGrabberVisible = newValue; - }; - } - }; - - @objc var sheetShouldAnimateChanges: Bool = true; - - @objc var sheetLargestUndimmedDetentIdentifier: String? { - didSet { - guard #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - self.sheetAnimateChangesIfNeeded { - sheetController.largestUndimmedDetentIdentifier = - self.synthesizedSheetLargestUndimmedDetentIdentifier; - }; - } - }; - - @objc var sheetPreferredCornerRadius: NSNumber? { - didSet { - let newValue = self.sheetPreferredCornerRadius; - - guard #available(iOS 15.0, *), - oldValue != newValue, - let sheetController = self.sheetPresentationController, - let cornerRadius = newValue?.doubleValue - else { return }; - - self.sheetAnimateChangesIfNeeded { - sheetController.preferredCornerRadius = cornerRadius; - }; - } - }; - - @objc var sheetSelectedDetentIdentifier: String? { - didSet { - let newValue = self.sheetSelectedDetentIdentifier; - - guard oldValue != newValue, - #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController - else { return }; - - let nextDetentID = self.synthesizedSheetSelectedDetentIdentifier; - - self.sheetAnimateChangesIfNeeded { - sheetController.selectedDetentIdentifier = nextDetentID; - }; - - /// Delegate function does not get called when detent is changed via - /// setting `selectedDetentIdentifier`, so invoke manually... - /// - self.sheetPresentationControllerDidChangeSelectedDetentIdentifier( - sheetController - ); - } - }; - - // MARK: - Properties: Synthesized From Props - // ------------------------------------------ - - public var synthesizedModalContentPreferredContentSize: RNIComputableSize? { - guard let dict = self.modalContentPreferredContentSize, - let computableSize = RNIComputableSize(fromDict: dict) - else { return nil }; - - return computableSize; - }; - - public var synthesizedModalPresentationStyle: UIModalPresentationStyle { - let defaultStyle: UIModalPresentationStyle = { - guard #available(iOS 13.0, *) else { return .overFullScreen }; - return .automatic; - }(); - - guard let style = UIModalPresentationStyle( - string: self.modalPresentationStyle as String - ) else { - #if DEBUG - print( - "Error - RNIModalView.synthesizedModalPresentationStyle" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Unable to parse presentation style string" - + " - modalPresentationStyle: '\(self.modalPresentationStyle)'" - + " - using default style: '\(defaultStyle)'" - ); - #endif - return defaultStyle; - }; - - switch style { - case .automatic, - .pageSheet, - .formSheet, - .fullScreen, - .overFullScreen: - - return style; - - default: - #if DEBUG - print( - "Error - RNIModalView.synthesizedModalPresentationStyle" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Unsupported presentation style string value" - + " - modalPresentationStyle: '\(self.modalPresentationStyle)'" - + " - Using default style: '\(defaultStyle)'" - ); - #endif - return defaultStyle; - }; - }; - - public var synthesizedModalTransitionStyle: UIModalTransitionStyle { - let defaultStyle: UIModalTransitionStyle = .coverVertical ; - - // TODO:2023-03-22-13-18-14 - Refactor: Move `fromString` to enum init - guard let style = - UIModalTransitionStyle.fromString(self.modalTransitionStyle as String) - else { - #if DEBUG - print( - "Error - RNIModalView.synthesizedModalTransitionStyle " - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Unable to parse string value" - + " - modalPresentationStyle: '\(self.modalPresentationStyle)'" - + " - Using default style: '\(defaultStyle)'" - ); - #endif - return defaultStyle; - }; - - return style; - }; - - public var synthesizedModalBGBlurEffectStyle: UIBlurEffect.Style { - // Provide default value - let defaultStyle: UIBlurEffect.Style = { - guard #available(iOS 13.0, *) else { return .light }; - return .systemThinMaterial; - }(); - - guard let blurStyle = UIBlurEffect.Style( - string: self.modalBGBlurEffectStyle as String - ) else { - #if DEBUG - print( - "Error - RNIModalView.synthesizedModalBGBlurEffectStyle" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Unable to parse string value" - + " - modalPresentationStyle: '\(self.modalPresentationStyle)'" - + " - Using default style: '\(defaultStyle)'" - ); - #endif - return defaultStyle; - }; - - return blurStyle; - }; - - @available(iOS 15.0, *) - public var synthesizedModalSheetDetents: [UISheetPresentationController.Detent]? { - self.modalSheetDetents?.compactMap { - if let string = $0 as? String, - let detent = UISheetPresentationController.Detent.fromString(string) { - - return detent; - - } else if #available(iOS 16.0, *), - let dict = $0 as? Dictionary { - - let customDetent = RNIModalCustomSheetDetent(forDict: dict) { - _, maximumDetentValue, computedDetentValue, sender in - - let eventData = RNIModalDetentDidComputeEventData( - maximumDetentValue: maximumDetentValue, - computedDetentValue: computedDetentValue, - key: sender.key - ); - - self.onModalDetentDidCompute?( - eventData.synthesizedJSDictionary - ); - }; - - return customDetent?.synthesizedDetent; - }; - - return nil; - }; - }; - - @available(iOS 15.0, *) - public var synthesizedSheetLargestUndimmedDetentIdentifier: - UISheetPresentationController.Detent.Identifier? { - - guard let identifierString = self.sheetLargestUndimmedDetentIdentifier - else { return nil }; - - return UISheetPresentationController.Detent.Identifier( - fromString: identifierString - ); - }; - - @available(iOS 15.0, *) - public var synthesizedSheetSelectedDetentIdentifier: - UISheetPresentationController.Detent.Identifier? { - - guard let identifierString = self.sheetSelectedDetentIdentifier - else { return nil }; - - return UISheetPresentationController.Detent.Identifier( - fromString: identifierString - ); - }; - - // MARK: - Properties: Synthesized - // ------------------------------- - - public var synthesizedBaseEventData: RNIModalBaseEventData { - RNIModalBaseEventData( - reactTag: self.reactTag.intValue, - modalID: self.modalID as? String, - modalData: self.synthesizedModalData - ); - }; - - // MARK: - Properties: Computed - // ---------------------------- - - // TODO: Move to `RNIModal+Helpers` - @available(iOS 15.0, *) - var sheetPresentationController: UISheetPresentationController? { - guard let presentedVC = self.modalViewController else { return nil }; - - switch presentedVC.modalPresentationStyle { - case .popover: - return presentedVC.popoverPresentationController? - .adaptiveSheetPresentationController; - - case .automatic, - .formSheet, - .pageSheet: - return presentedVC.sheetPresentationController; - - default: - return nil; - }; - }; - - @available(iOS 15.0, *) - var currentSheetDetentID: UISheetPresentationController.Detent.Identifier? { - guard let sheetController = self.sheetPresentationController - else { return nil }; - - let detents = sheetController.detents; - - if let selectedDetent = sheetController.selectedDetentIdentifier { - return selectedDetent; - - } else if #available(iOS 16.0, *), - let firstDetent = detents.first { - - /// The default value of `selectedDetentIdentifier` is nil, which means - /// the sheet displays at the smallest detent you specify in detents. - return firstDetent.identifier; - }; - - return nil; - }; - - var currentSheetDetentString: String? { - guard #available(iOS 15.0, *) else { return nil }; - return currentSheetDetentID?.rawValue; - }; - - var isModalViewPresentationNotificationEnabled: Bool { - RNIModalFlagsShared.isModalViewPresentationNotificationEnabled - }; - - var modalGestureRecognizer: UIGestureRecognizer? { - guard let modalVC = self.modalVC, - let controller = modalVC.presentationController, - let gestureRecognizers = controller.presentedView?.gestureRecognizers - else { return nil }; - - return gestureRecognizers.first; - }; - - var debugData: Dictionary { - self.synthesizedModalData.synthesizedJSDictionary - }; - - // MARK: - Init - // ------------ - - init(bridge: RCTBridge) { - super.init(frame: CGRect()); - - self.bridge = bridge; - RNIModalManagerShared.register(modal: self); - }; - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder); - fatalError("Not implemented"); - }; - - // MARK: - UIKit Lifecycle - // ----------------------- - - public override func didMoveToWindow() { - super.didMoveToWindow(); - - if self.presentViaMount { - try? self.dismissModal(); - }; - }; - - public override func didMoveToSuperview() { - super.didMoveToSuperview(); - - if self.presentViaMount { - try? self.presentModal(); - }; - }; - - // MARK: - React-Native Lifecycle - // ------------------------------ - - public override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { - super.insertReactSubview(subview, at: atIndex); - - guard let wrapperView = subview as? RNIWrapperView, - let nativeID = subview.nativeID, - let nativeIDKey = NativeIDKey(rawValue: nativeID) - else { return }; - - self.initControllers(); - wrapperView.isMovingToParent = true; - - switch nativeIDKey { - case .modalViewContent: - guard self.modalContentWrapper !== wrapperView, - self.modalContentWrapper?.reactTag != wrapperView.reactTag - else { return }; - - if let oldModalContentWrapper = self.modalContentWrapper { - - oldModalContentWrapper.cleanup(); - self.modalContentWrapper = nil; - self.deinitControllers(); - }; - - self.modalContentWrapper = wrapperView; - self.initControllers(); - }; - - wrapperView.removeFromSuperview(); - wrapperView.isMovingToParent = false; - }; - - public override func removeReactSubview(_ subview: UIView!) { - super.removeReactSubview(subview); - }; - - // MARK: - Functions - Private - // ---------------------------- - - private func initControllers(){ - #if DEBUG - print( - "Log - RNIModalView.initControllers" - + " - self.modalNativeID: '\(self.modalNativeID)'" - ); - #endif - - self.modalVC = { - let vc = RNIModalViewController(); - - vc.modalViewRef = self; - vc.lifecycleDelegate = self; - - vc.isBGBlurred = self.isModalBGBlurred; - vc.isBGTransparent = self.isModalBGTransparent; - - vc.blurEffectStyle = self.synthesizedModalBGBlurEffectStyle; - - return vc; - }(); - }; - - private func deinitControllers(){ - #if DEBUG - print( - "Log - RNIModalView.deinitControllers" - + " - self.modalNativeID: '\(self.modalNativeID)'" - ); - #endif - - self.modalVC = nil; - self.presentingViewController = nil; - }; - - private func setupOnModalInitialPresent(){ - guard let panGesture = self.modalGestureRecognizer else { return }; - - panGesture.addTarget(self, - action: #selector(Self.handleGestureRecognizer(_:)) - ); - }; - - private func notifyIfModalDismissCancelled(){ - guard let modalVC = self.modalVC, - let transitionCoordinator = modalVC.transitionCoordinator - else { return }; - - transitionCoordinator.notifyWhenInteractionChanges { - guard $0.isCancelled else { return }; - - self.modalPresentationState.set(state: .DISMISS_GESTURE_CANCELLING); - self.modalPresentationState.wasCancelledDismissViaGesture = true; - - self.modalPresentationNotificationDelegate - .notifyOnModalWillShow(sender: self); - }; - - self.modalVC?.transitionCoordinator?.animate(alongsideTransition: nil) { - guard $0.isCancelled else { return }; - - self.modalPresentationNotificationDelegate - .notifyOnModalDidShow(sender: self); - }; - }; - - @objc private func handleGestureRecognizer(_ sender: UIGestureRecognizer) { - guard let window = self.window else { return }; - - switch sender.state { - case .began: - let gestureEventData = RNIModalSwipeGestureEventData( - position: sender.location(in: window) - ); - - self.onModalSwipeGestureStart?( - gestureEventData.synthesizedJSDictionary - ); - - case .ended: - let gestureEventData = RNIModalSwipeGestureEventData( - position: sender.location(in: window) - ); - - self.onModalSwipeGestureDidEnd?( - gestureEventData.synthesizedJSDictionary - ); - - guard let presentationController = self.modalVC?.presentationController, - let presentedView = presentationController.presentedView, - let positionAnimation = - presentedView.layer.animation(forKey: "position") - else { break }; - - positionAnimation.waitUntiEnd { - let eventData = RNIModalDidSnapEventData( - selectedDetentIdentifier: self.currentSheetDetentString, - modalContentSize: presentedView.bounds.size - ); - - self.onModalDidSnap?( - eventData.synthesizedJSDictionary - ); - }; - - default: break; - }; - }; - - /// `TODO:2023-03-22-12-07-54` - /// * Refactor: Move to `RNIModalManager` - /// - /// helper func to hide/show the other modals that are below level - private func setIsHiddenForViewBelowLevel(_ level: Int, isHidden: Bool){ - let presentedVCList = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - for (index, vc) in presentedVCList.enumerated() { - if index < level { - vc.view.isHidden = isHidden; - }; - }; - }; - - @available(iOS 15.0, *) - private func sheetAnimateChangesIfNeeded(_ block: () -> Void){ - guard let sheetController = self.sheetPresentationController - else { return }; - - if self.sheetShouldAnimateChanges { - sheetController.animateChanges { - block(); - }; - - } else { - block(); - }; - }; - - @available(iOS 15.0, *) - private func applyModalSheetProps( - to sheetController: UISheetPresentationController - ){ - - if let detents = self.synthesizedModalSheetDetents, detents.count >= 1 { - sheetController.detents = detents; - }; - - sheetController.prefersScrollingExpandsWhenScrolledToEdge = - self.sheetPrefersScrollingExpandsWhenScrolledToEdge; - - sheetController.prefersEdgeAttachedInCompactHeight = - self.sheetPrefersEdgeAttachedInCompactHeight; - - sheetController.widthFollowsPreferredContentSizeWhenEdgeAttached = - self.sheetWidthFollowsPreferredContentSizeWhenEdgeAttached; - - sheetController.prefersGrabberVisible = self.sheetPrefersGrabberVisible; - - sheetController.largestUndimmedDetentIdentifier = - self.synthesizedSheetLargestUndimmedDetentIdentifier; - - if let cornerRadius = self.sheetPreferredCornerRadius?.doubleValue { - sheetController.preferredCornerRadius = cornerRadius; - }; - - sheetController.selectedDetentIdentifier = - self.synthesizedSheetSelectedDetentIdentifier; - }; - - // MARK: - Functions - Public - // -------------------------- - - public func presentModal( - animated: Bool = true, - completion: CompletionHandler? = nil - ) throws { - guard self.window != nil else { - throw RNIModalError( - code: .runtimeError, - message: "Guard check failed, window is nil", - debugData: self.debugData - ); - }; - - guard !self.computedIsModalPresented else { - throw RNIModalError( - code: .modalAlreadyVisible, - message: "Guard check failed, modal already presented", - debugData: self.debugData - ); - }; - - let presentedViewControllers = - RNIPresentedVCListCache.getPresentedViewControllers(forWindow: window); - - guard let topMostPresentedVC = presentedViewControllers.last else { - throw RNIModalError( - code: .runtimeError, - message: "Guard check failed, could not get topMostPresentedVC", - debugData: self.debugData - ); - }; - - guard let modalVC = self.modalVC else { - throw RNIModalError( - code: .runtimeError, - message: "Guard check failed, could not get modalVC", - debugData: self.debugData - ); - }; - - modalVC.modalTransitionStyle = self.synthesizedModalTransitionStyle; - modalVC.modalPresentationStyle = self.synthesizedModalPresentationStyle; - - if #available(iOS 15.0, *), - let sheetController = self.sheetPresentationController { - - sheetController.delegate = self; - self.applyModalSheetProps(to: sheetController); - }; - - #if DEBUG - print( - "Log - RNIModalView.presentModal - Start presenting" - + " - self.reactTag: \(self.reactTag ?? -1)" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - + " - self.modalID: \(self.modalID ?? "N/A")" - + " - self.presentationStyle: \(self.synthesizedModalPresentationStyle)" - + " - self.transitionStyle: \(self.synthesizedModalTransitionStyle)" - ); - #endif - - // Temporarily disable swipe gesture while it's being presented - self.modalGestureRecognizer?.isEnabled = false; - - self.presentingViewController = topMostPresentedVC; - - /// set specific "presenting" state - self.modalPresentationState.set(state: .PRESENTING_PROGRAMMATIC); - - self.onModalWillPresent?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - - topMostPresentedVC.present(modalVC, animated: animated) { [unowned self] in - - // Become the modal's presentation delegate after it has been presented - // in order to not override system-defined default modal behavior - modalVC.presentationController?.delegate = self; - - // Reset swipe gesture before it was temporarily disabled - self.modalGestureRecognizer?.isEnabled = self.enableSwipeGesture; - - self.modalPresentationState.set(state: .PRESENTED); - - self.onModalDidPresent?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - - completion?(); - - #if DEBUG - print( - "Log - RNIModalView.presentModal - Present modal finished" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - + " - self.modalID: \(self.modalID ?? "N/A")" - ); - #endif - }; - }; - - public func dismissModal( - animated: Bool = true, - completion: CompletionHandler? = nil - ) throws { - guard self.computedIsModalPresented else { - throw RNIModalError( - code: .modalAlreadyHidden, - message: "Guard check failed, modal already dismissed", - debugData: self.debugData - ); - }; - - guard let modalVC = self.modalVC else { - throw RNIModalError( - code: .runtimeError, - message: "Guard check failed, Unable to get modalVC", - debugData: self.debugData - ); - }; - - let isModalInFocus = self.computedIsModalInFocus; - - let shouldDismiss = isModalInFocus - ? true - : self.allowModalForceDismiss; - - guard shouldDismiss else { - throw RNIModalError( - code: .dismissRejected, - message: "Guard check failed, shouldDismiss prop is false", - debugData: self.debugData - ); - }; - - /// TODO:2023-03-22-12-12-05 - Remove? - let presentedVC: UIViewController = isModalInFocus - ? modalVC - : modalVC.presentingViewController! - - - #if DEBUG - print( - "Log - RNIModalView.dismissModal" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Start dismissing modal" - ); - #endif - - self.modalGestureRecognizer?.isEnabled = false; - - /// set specific "dismissing" state - self.modalPresentationState.set(state: .DISMISSING_PROGRAMMATIC); - - self.onModalWillDismiss?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - - presentedVC.dismiss(animated: animated){ - self.modalPresentationState.set(state: .DISMISSED); - - self.onModalDidDismiss?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - - completion?(); - - #if DEBUG - print( - "Log - RNIModalView.dismissModal" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - Dismiss modal finished" - ); - #endif - }; - }; -}; - -// MARK: - UIAdaptivePresentationControllerDelegate -// ------------------------------------------------ - -/// `Note:2023-03-31-16-48-10` -/// -/// * The "blur/focus"-related events in -/// `UIAdaptivePresentationControllerDelegate` only fire in response to user -/// gestures (i.e. if the user swiped the modal away). -/// -/// * In other words, if the modal was closed programmatically, the -/// `UIAdaptivePresentationControllerDelegate`-related events will not get -/// invoked. -/// -extension RNIModalView: UIAdaptivePresentationControllerDelegate { - - /// `Note:2023-03-31-17-01-57` - /// - /// * This gets called whenever the user starts swiping the modal down, - /// regardless of whether or not the swipe action was cancelled half-way - /// through. - /// - /// * Only called when the sheet is dismissed by DRAGGING. - /// - /// - /// `Note:2023-04-01-14-52-05` - /// - /// * Invocation history when a modal is dismissed via a swipe gesture, but - /// was cancelled half-way - /// - /// * A - Swipe dismiss gesture begin... - /// * 1 - `presentationControllerWillDismiss - /// * 2 - `viewWillDisappear` - /// * B - Swipe dismiss gesture cancelled... - /// * 3 - `viewWillAppear` - /// * 4 - `viewDidAppear` - /// - public func presentationControllerWillDismiss( - _ presentationController: UIPresentationController - ) { - self.modalPresentationState.set(state: .DISMISSING_GESTURE); - - #if DEBUG - print( - "Log - RNIModalView+UIAdaptivePresentationControllerDelegate" - + " - RNIModalView.presentationControllerWillDismiss" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - ); - #endif - }; - - public func presentationControllerDidDismiss( - _ presentationController: UIPresentationController - ) { - self.modalPresentationNotificationDelegate - .notifyOnModalDidHide(sender: self); - - #if DEBUG - print( - "Log - RNIModalView+UIAdaptivePresentationControllerDelegate" - + " - RNIModalView.presentationControllerDidDismiss" - + " - self.modalNativeID: \(self.modalNativeID)" - ); - #endif - }; - - /// `Note:2023-04-07-01-28-57` - /// No other "view controller"-related lifecycle method was trigger in - /// response to this event being invoked. - /// - public func presentationControllerDidAttemptToDismiss( - _ presentationController: UIPresentationController - ) { - - #if DEBUG - print( - "Log - RNIModalView+UIAdaptivePresentationControllerDelegate" - + " - RNIModalView.presentationControllerDidAttemptToDismiss" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - ); - #endif - }; -}; - -// MARK: - UISheetPresentationControllerDelegate -// --------------------------------------------- - -@available(iOS 15.0, *) -extension RNIModalView: UISheetPresentationControllerDelegate { - - /// `Note:2023-04-22-03-50-59` - /// - /// * This function gets invoked when the sheet has snapped into a detent - /// - /// * However, we don't get notified whenever the user is currently dragging - /// the sheet. - /// - /// * The `presentedViewController.transitionCoordinator` is only available - /// during modal presentation and dismissal. - /// - /// - public func sheetPresentationControllerDidChangeSelectedDetentIdentifier( - _ sheetPresentationController: UISheetPresentationController - ) { - let currentDetentID = self.currentSheetDetentID; - - self.sheetDetentStringPrevious = self.sheetDetentStringCurrent; - self.sheetDetentStringCurrent = currentDetentID?.description; - - #if DEBUG - print( - "Log - RNIModalView+UISheetPresentationControllerDelegate" - + " - sheetPresentationControllerDidChangeSelectedDetentIdentifier" - + " - sheetDetentStringPrevious: \(self.sheetDetentStringPrevious ?? "N/A")" - + " - sheetDetentStringCurrent: \(self.sheetDetentStringCurrent ?? "N/A")" - ); - #endif - - let eventData = RNIModalDidChangeSelectedDetentIdentifierEventData( - sheetDetentStringPrevious: self.sheetDetentStringPrevious, - sheetDetentStringCurrent: self.sheetDetentStringCurrent - ); - - self.onModalDidChangeSelectedDetentIdentifier?( - eventData.synthesizedJSDictionary - ); - }; -}; - -// MARK: Extension: RNIModalRequestable -// ------------------------------------ - -extension RNIModalView: RNIModalRequestable { - - public func requestModalToShow( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws { - try self.presentModal(animated: animated, completion: completion); - }; - - public func requestModalToHide( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws { - try self.dismissModal(animated: animated, completion: completion); - }; -}; - -// MARK: - RNIViewControllerLifeCycleNotifiable -// -------------------------------------------- - -extension RNIModalView: RNIViewControllerLifeCycleNotifiable { - - public func viewWillAppear(sender: UIViewController, animated: Bool) { - guard sender.isBeingPresented else { return }; - self.modalPresentationState.set(state: .PRESENTING_UNKNOWN); - - if self.modalPresentationState.didChange { - self.onModalWillShow?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - }; - - if self.isModalViewPresentationNotificationEnabled { - self.modalPresentationNotificationDelegate - .notifyOnModalWillShow(sender: self); - }; - - if self.modalPresentationState.isInitialPresent { - self.setupOnModalInitialPresent(); - }; - }; - - public func viewDidAppear(sender: UIViewController, animated: Bool) { - guard sender.isBeingPresented else { return }; - self.modalPresentationState.set(state: .PRESENTED_UNKNOWN); - - if self.modalPresentationState.didChange { - self.onModalDidShow?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - }; - - if self.isModalViewPresentationNotificationEnabled { - self.modalPresentationNotificationDelegate - .notifyOnModalDidShow(sender: self); - }; - }; - - public func viewWillDisappear(sender: UIViewController, animated: Bool) { - guard sender.isBeingDismissed else { return }; - self.modalPresentationState.set(state: .DISMISSING_UNKNOWN); - - if self.modalPresentationState.didChange { - self.onModalWillHide?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - }; - - if self.isModalViewPresentationNotificationEnabled { - self.modalPresentationNotificationDelegate - .notifyOnModalWillHide(sender: self); - }; - - self.notifyIfModalDismissCancelled(); - }; - - public func viewDidDisappear(sender: UIViewController, animated: Bool) { - guard sender.isBeingDismissed else { return }; - self.modalPresentationState.set(state: .DISMISSED); - - if self.modalPresentationState.didChange { - self.onModalDidHide?( - self.synthesizedBaseEventData.synthesizedJSDictionary - ); - }; - - if self.isModalViewPresentationNotificationEnabled { - self.modalPresentationNotificationDelegate - .notifyOnModalDidHide(sender: self); - }; - - self.deinitControllers(); - }; -}; - - -// MARK: Extension: RNIModalFocusNotifiable -// ---------------------------------------- - -/// `Note:2023-03-31-17-51-56` -extension RNIModalView: RNIModalFocusNotifiable { - - public func onModalWillFocusNotification(sender: any RNIModal) { - guard self.modalFocusState.didChange else { return }; - - let eventData = RNIOnModalFocusEventData( - modalData: self.synthesizedBaseEventData, - senderInfo: sender.synthesizedModalData, - isInitial: sender === self - ); - - self.onModalWillFocus?( - eventData.synthesizedJSDictionary - ); - }; - - public func onModalDidFocusNotification(sender: any RNIModal) { - guard self.modalFocusState.didChange else { return }; - - let eventData = RNIOnModalFocusEventData( - modalData: self.synthesizedBaseEventData, - senderInfo: sender.synthesizedModalData, - isInitial: sender === self - ); - - self.onModalDidFocus?( - eventData.synthesizedJSDictionary - ); - - #if DEBUG - print( - "Log - RNIModalView.onModalDidFocusNotification" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - arg sender.modalIndex: \(sender.modalIndex!)" - ); - #endif - - }; - - public func onModalWillBlurNotification(sender: any RNIModal) { - guard self.modalFocusState.didChange else { return }; - - let eventData = RNIOnModalFocusEventData( - modalData: self.synthesizedBaseEventData, - senderInfo: sender.synthesizedModalData, - isInitial: sender === self - ); - - self.onModalWillBlur?( - eventData.synthesizedJSDictionary - ); - }; - - public func onModalDidBlurNotification(sender: any RNIModal) { - guard self.modalFocusState.didChange else { return }; - - let eventData = RNIOnModalFocusEventData( - modalData: self.synthesizedBaseEventData, - senderInfo: sender.synthesizedModalData, - isInitial: sender === self - ); - - self.onModalDidBlur?( - eventData.synthesizedJSDictionary - ); - - #if DEBUG - print( - "Log - RNIModalView.onModalDidBlurNotification" - + " - self.modalNativeID: \(self.modalNativeID)" - + " - self.modalIndex: \(self.modalIndex!)" - + " - arg sender.modalNativeID: \(sender.modalNativeID)" - + " - arg sender.modalIndex: \(sender.modalIndex!)" - ); - #endif - }; -}; diff --git a/ios/React Native/RNIModalView/RNIModalViewController.swift b/ios/React Native/RNIModalView/RNIModalViewController.swift deleted file mode 100644 index 941f1640..00000000 --- a/ios/React Native/RNIModalView/RNIModalViewController.swift +++ /dev/null @@ -1,369 +0,0 @@ -// -// RNIModalViewController.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/9/20. -// Copyright © 2020 Facebook. All rights reserved. -// - -import Foundation - -public class RNIModalViewController: UIViewController { - - // MARK: - Properties - // ------------------ - - weak var modalViewRef: RNIModalView?; - weak var lifecycleDelegate: RNIViewControllerLifeCycleNotifiable?; - - var isBGTransparent: Bool = true { - didSet { - guard oldValue != self.isBGTransparent else { return }; - self.updateBackgroundTransparency(); - self.updateBackgroundBlur(); - } - }; - var isBGBlurred: Bool = true { - didSet { - guard oldValue != self.isBGBlurred else { return }; - self.updateBackgroundBlur(); - } - }; - - private(set) public var prevBounds: CGRect?; - - private var initialSize: CGSize?; - - // MARK: - Properties - Computed - // ----------------------------- - - var modalID: String? { - self.modalViewRef?.modalID as? String - }; - - var modalContentWrapper: RNIWrapperView? { - self.modalViewRef?.modalContentWrapper; - }; - - var computablePreferredContentSize: RNIComputableSize? { - self.modalViewRef?.synthesizedModalContentPreferredContentSize; - }; - - var shouldUpdateContentSize: Bool { - guard let computableSize = self.computablePreferredContentSize, - case .current = computableSize.mode - else { return true }; - - return false; - }; - - // MARK: - Properties - // ------------------ - - var blurEffectView: UIVisualEffectView? = nil; - - var blurEffectStyle: UIBlurEffect.Style? { - didSet { - let didChange = oldValue != blurEffectStyle; - let isPresented = self.presentingViewController != nil; - - guard didChange && isPresented, - let blurEffectStyle = self.blurEffectStyle else { return }; - - #if DEBUG - print( - "Log - RNIModalViewController.blurEffectStyle - didSet" - + " - modalNativeID: '\(self.modalViewRef?.modalNativeID ?? "N/A")'" - + " - oldValue: '\(oldValue!.description)'" - + " - newValue: '\(blurEffectStyle.description)'" - ); - #endif - - self.updateBackgroundBlur(); - } - }; - - // MARK: - View Controller Lifecycle - // --------------------------------- - - public override func viewDidLoad() { - super.viewDidLoad(); - - self.view = { - let view = UIView(); - view.autoresizingMask = [.flexibleHeight, .flexibleWidth]; - - return view; - }(); - - if let modalContentWrapper = self.modalContentWrapper { - self.view.addSubview(modalContentWrapper); - modalContentWrapper.notifyForBoundsChange(size: self.view.bounds.size); - }; - - self.updateBackgroundTransparency(); - self.updateBackgroundBlur(); - - self.lifecycleDelegate?.viewDidLoad(sender: self); - }; - - public override func viewDidLayoutSubviews(){ - super.viewDidLayoutSubviews(); - - let didChangeBounds: Bool = { - guard let prevBounds = self.prevBounds else { return true }; - return !prevBounds.equalTo(self.view.bounds); - }(); - - guard didChangeBounds, - let modalContentWrapper = self.modalContentWrapper - else { return }; - - let nextBounds = self.view.bounds; - - let prevBounds = self.prevBounds; - self.prevBounds = nextBounds; - - #if DEBUG - print( - "Log - RNIModalViewController.viewDidLayoutSubviews" - + " - modalNativeID: '\(self.modalViewRef?.modalNativeID ?? "N/A")'" - + " - self.prevBounds: \(String(describing: prevBounds))" - + " - nextBounds: \(nextBounds)" - ); - #endif - - if self.shouldUpdateContentSize { - modalContentWrapper.notifyForBoundsChange(size: nextBounds.size); - modalContentWrapper.center = self.view.center; - }; - - self.lifecycleDelegate?.viewDidLayoutSubviews(sender: self); - }; - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated); - - self.lifecycleDelegate? - .viewWillAppear(sender: self, animated: animated); - - self.setPreferredContentSize(); - - #if DEBUG - print( - "Log - RNIModalViewController.viewWillAppear" - + " - arg animated: \(animated)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isBeingPresented: \(self.isBeingPresented)" - ); - #endif - }; - - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated); - - self.lifecycleDelegate? - .viewDidAppear(sender: self, animated: animated); - - #if DEBUG - print( - "Log - RNIModalViewController.viewDidAppear" - + " - arg animated: \(animated)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isBeingPresented: \(self.isBeingPresented)" - ); - #endif - }; - - public override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated); - - self.lifecycleDelegate? - .viewWillDisappear(sender: self, animated: animated); - - #if DEBUG - print( - "Log - RNIModalViewController.viewWillDisappear" - + " - arg animated: \(animated)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isBeingDismissed: \(self.isBeingDismissed)" - + " - self.transitionCoordinator: \(String(describing: self.transitionCoordinator))" - + " - self.transitioningDelegate: \(String(describing: self.transitioningDelegate))" - ); - #endif - }; - - public override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated); - - self.lifecycleDelegate? - .viewDidDisappear(sender: self, animated: animated); - - #if DEBUG - print( - "Log - RNIModalViewController.viewDidDisappear" - + " - arg animated: \(animated)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isBeingDismissed: \(self.isBeingDismissed)" - ); - #endif - }; - - public override func willMove(toParent parent: UIViewController?) { - super.willMove(toParent: parent); - - self.lifecycleDelegate?.willMove(sender: self, toParent: parent); - - #if DEBUG - print( - "Log - RNIModalViewController.willMove" - + " - arg parent == nil: \(parent == nil)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isMovingFromParent: \(self.isMovingFromParent)" - + " - self.isMovingToParent: \(self.isMovingToParent)" - ); - #endif - }; - - public override func didMove(toParent parent: UIViewController?) { - super.didMove(toParent: parent); - - self.lifecycleDelegate?.didMove(sender: self, toParent: parent); - - #if DEBUG - print( - "Log - RNIModalViewController.willMove" - + " - arg parent == nil: \(parent == nil)" - + " - self.modalNativeID: \(self.modalViewRef?.modalNativeID ?? "N/A")" - + " - self.isMovingFromParent: \(self.isMovingFromParent)" - + " - self.isMovingToParent: \(self.isMovingToParent)" - ); - #endif - }; - - // MARK: - Functions - // ----------------- - - func setPreferredContentSize(withWindow window: UIWindow? = nil){ - guard let computableSize = self.computablePreferredContentSize - else { return }; - - if self.initialSize == nil || self.initialSize!.isZero { - self.initialSize = self.view.bounds.size; - }; - - let targetSize: CGSize = { - let viewSize = self.initialSize!; - let screenSize = window?.bounds.size; - - let size = viewSize.isZero ? screenSize : viewSize; - return size ?? viewSize; - }(); - - switch computableSize.mode { - case .current: - guard let modalContentWrapper = self.modalContentWrapper - else { return }; - - self.preferredContentSize = self.view.systemLayoutSizeFitting( - modalContentWrapper.bounds.size - ); - - default: - self.preferredContentSize = computableSize.compute( - withTargetSize: targetSize, currentSize: .zero - ); - }; - }; - - // MARK: - Private Functions - // ------------------------- - - private func updateBackgroundTransparency(){ - self.view.backgroundColor = { - if self.isBGTransparent { - return .none; - }; - - guard #available(iOS 13, *) else { return .white }; - return .systemBackground; - }(); - - #if DEBUG - print( - "Log - RNIModalViewController.updateBackgroundTransparency" - + " - modalNativeID: '\(self.modalViewRef?.modalNativeID ?? "N/A")'" - + " - self.isBGTransparent: \(self.isBGTransparent)" - ); - #endif - }; - - private func initBackgroundBlur(){ - guard let blurEffectStyle = self.blurEffectStyle else { return }; - - let blurEffect = UIBlurEffect(style: blurEffectStyle); - - let blurEffectView = UIVisualEffectView(effect: blurEffect); - self.blurEffectView = blurEffectView; - - blurEffectView.frame = self.view.bounds; - blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]; - - self.view.insertSubview(blurEffectView, at: 0); - - #if DEBUG - print( - "Log - RNIModalViewController.initBackgroundBlur" - + " - modalNativeID: '\(self.modalViewRef?.modalNativeID ?? "N/A")'" - + " - self.blurEffectStyle: \(blurEffect)" - ); - #endif - }; - - private func removeBackgroundBlur(){ - self.blurEffectView?.removeFromSuperview(); - self.blurEffectView = nil; - }; - - private func updateBackgroundBlur(){ - guard self.isViewLoaded, - let blurEffectStyle = self.blurEffectStyle - else { return }; - - /// bg is transparent, and blur is enabled - let shouldUpdateBackgroundBlur = - self.isBGTransparent && self.isBGBlurred ; - - /// bg is not transparent or blurred - let shouldRemoveBackgroundBlur = - !self.isBGTransparent || !self.isBGBlurred; - - let shouldInitBackgroundBlur = - self.blurEffectView == nil && shouldUpdateBackgroundBlur; - - // 01 - Init background blur first if needed - if shouldInitBackgroundBlur { - self.initBackgroundBlur(); - }; - - if shouldUpdateBackgroundBlur, - let blurEffectView = self.blurEffectView { - - // 02-A - Update background blur - blurEffectView.effect = UIBlurEffect(style: blurEffectStyle); - - #if DEBUG - print( - "Log - RNIModalViewController.updateBackgroundBlur" - + " - modalNativeID: '\(self.modalViewRef?.modalNativeID ?? "N/A")'" - + " - blurEffectStyle: \(blurEffectStyle)" - ); - #endif - - } else if shouldRemoveBackgroundBlur { - // 02-B - background is not transparent or blurred so remove - // background blur - self.removeBackgroundBlur(); - }; - }; -}; diff --git a/ios/React Native/RNIModalView/RNIModalViewError.swift b/ios/React Native/RNIModalView/RNIModalViewError.swift deleted file mode 100644 index 0fedb90b..00000000 --- a/ios/React Native/RNIModalView/RNIModalViewError.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// RNIModalViewError.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/26/20. -// - -import Foundation - -public enum RNIModalViewError: String, CaseIterable { - case modalAlreadyPresented; - case modalAlreadyDismissed; - case modalDismissFailedNotInFocus; - - var errorMessage: String { - RNIModalViewError.getErrorMessage(for: self); - }; - - static func withLabel(_ label: String) -> RNIModalViewError? { - return self.allCases.first{ $0.rawValue == label }; - }; - - static func getErrorMessage(for errorCase: RNIModalViewError) -> String { - switch errorCase { - case .modalAlreadyDismissed: - return "Cannot dismiss modal because it's currently not presented"; - - case .modalAlreadyPresented: - return "Cannot present modal because it's already presented"; - - case .modalDismissFailedNotInFocus: - return "Cannot dismiss modal because it's not in focus. Enable allowModalForceDismiss to dismiss."; - }; - }; -}; diff --git a/ios/React Native/RNIModalView/RNIModalViewManager.m b/ios/React Native/RNIModalView/RNIModalViewManager.m deleted file mode 100644 index c073147e..00000000 --- a/ios/React Native/RNIModalView/RNIModalViewManager.m +++ /dev/null @@ -1,83 +0,0 @@ - -#import - -@interface RCT_EXTERN_MODULE(RNIModalViewManager, RCTViewManager) - -// MARK: - Props - Callbacks/Events -// -------------------------------- - -RCT_EXPORT_VIEW_PROPERTY(onModalWillPresent, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDidPresent, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalWillDismiss, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDidDismiss, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalWillShow, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDidShow, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalWillHide, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDidHide, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalWillFocus, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDidFocus, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalWillBlur, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onModalDidBlur, RCTBubblingEventBlock) - -RCT_EXPORT_VIEW_PROPERTY(onPresentationControllerWillDismiss, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onPresentationControllerDidDismiss, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onPresentationControllerDidAttemptToDismiss, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalDetentDidCompute, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onModalDidChangeSelectedDetentIdentifier, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalDidSnap, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalSwipeGestureStart, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalSwipeGestureDidEnd, RCTBubblingEventBlock); - -RCT_EXPORT_VIEW_PROPERTY(onModalDismissWillCancel, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onModalDismissDidCancel, RCTBubblingEventBlock); - -// MARK: - Value Props - General -// ----------------------------- - -RCT_EXPORT_VIEW_PROPERTY(modalID, NSString); -RCT_EXPORT_VIEW_PROPERTY(modalContentPreferredContentSize, NSDictionary); - -// MARK: - Value Props - BG-Related -// -------------------------------- - -RCT_EXPORT_VIEW_PROPERTY(isModalBGBlurred, BOOL); -RCT_EXPORT_VIEW_PROPERTY(isModalBGTransparent, BOOL); -RCT_EXPORT_VIEW_PROPERTY(modalBGBlurEffectStyle, NSString); - -// MARK: - Value Props - Presentation/Transition -// --------------------------------------------- - -RCT_EXPORT_VIEW_PROPERTY(modalPresentationStyle, NSString); -RCT_EXPORT_VIEW_PROPERTY(modalTransitionStyle, NSString); - -RCT_EXPORT_VIEW_PROPERTY(hideNonVisibleModals, BOOL); -RCT_EXPORT_VIEW_PROPERTY(presentViaMount, BOOL); -RCT_EXPORT_VIEW_PROPERTY(enableSwipeGesture, BOOL); -RCT_EXPORT_VIEW_PROPERTY(allowModalForceDismiss, BOOL); -RCT_EXPORT_VIEW_PROPERTY(isModalInPresentation, BOOL); - -// MARK: - Value Props - Sheet-Related -// ----------------------------------- - -RCT_EXPORT_VIEW_PROPERTY(modalSheetDetents, NSArray); - -RCT_EXPORT_VIEW_PROPERTY(sheetPrefersScrollingExpandsWhenScrolledToEdge, BOOL); -RCT_EXPORT_VIEW_PROPERTY(sheetPrefersEdgeAttachedInCompactHeight, BOOL); -RCT_EXPORT_VIEW_PROPERTY(sheetWidthFollowsPreferredContentSizeWhenEdgeAttached, BOOL); -RCT_EXPORT_VIEW_PROPERTY(sheetPrefersGrabberVisible, BOOL); -RCT_EXPORT_VIEW_PROPERTY(sheetShouldAnimateChanges, BOOL); - -RCT_EXPORT_VIEW_PROPERTY(sheetLargestUndimmedDetentIdentifier, NSString); -RCT_EXPORT_VIEW_PROPERTY(sheetSelectedDetentIdentifier, NSString); -RCT_EXPORT_VIEW_PROPERTY(sheetPreferredCornerRadius, NSNumber); - -@end - diff --git a/ios/React Native/RNIModalView/RNIModalViewManager.swift b/ios/React Native/RNIModalView/RNIModalViewManager.swift deleted file mode 100644 index b9c79d6d..00000000 --- a/ios/React Native/RNIModalView/RNIModalViewManager.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// RNIModalViewManager.swift -// nativeUIModulesTest -// -// Created by Dominic Go on 6/9/20. -// Copyright © 2020 Facebook. All rights reserved. -// - -import Foundation -import React - - -@objc (RNIModalViewManager) -class RNIModalViewManager: RCTViewManager { - static var sharedInstance: RNIModalViewManager!; - - override static func requiresMainQueueSetup() -> Bool { - return true; - }; - - override func view() -> UIView! { - let view = RNIModalView(bridge: self.bridge); - return view; - }; - - override init() { - super.init(); - RNIModalViewManager.sharedInstance = self; - - if !UIViewController.isSwizzled { - UIViewController.swizzleMethods(); - }; - }; - - @objc override func constantsToExport() -> [AnyHashable : Any]! { - return [ - "availableBlurEffectStyles": UIBlurEffect.Style - .availableStyles.map { $0.description }, - - "availablePresentationStyles": UIModalPresentationStyle - .availableStyles.map { $0.description }, - ]; - }; -}; diff --git a/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapper.swift b/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapper.swift deleted file mode 100644 index 1bc9df37..00000000 --- a/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapper.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// RNIModalViewControllerWrapper.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/13/23. -// - -import UIKit - -/// Wraps a `UIViewController` so it can be used w/ `RNIModalManager` -/// -public class RNIModalViewControllerWrapper: - RNIIdentifiable, RNIModalIdentifiable, RNIModalPresentationNotifying, - RNIModalState, RNIModalPresentation { - - // MARK: - Properties - RNIIdentifiable - // ------------------------------------ - - public static var synthesizedIdPrefix: String = "modal-wrapper-"; - - // MARK: - Properties - // ------------------ - - /// The view controller that this instance is wrapping/managing - public var viewController: UIViewController; - - // MARK: - Properties - RNIModalPresentationNotifying - // -------------------------------------------------- - - public var modalPresentationNotificationDelegate: RNIModalPresentationNotifiable! - - // MARK: - Properties - RNIModalState - // ---------------------------------- - - public var modalIndexPrev: Int! - public var modalIndex: Int! - - public lazy var modalPresentationState = RNIModalPresentationStateMachine(); - - public var modalFocusState = RNIModalFocusStateMachine(); - - // MARK: - Properties - RNIModalPresentation - // ----------------------------------------- - - /// The modal that is being presented, or to be presented (i.e. - /// `UIViewController.presentedViewController`). - /// - public weak var modalViewController: UIViewController?; - - /// The view controller that presented the modal (i.e. - /// `UIViewController.presentingViewController` - /// - public weak var presentingViewController: UIViewController?; - - public var window: UIWindow? { - self.viewController.view.window ?? - self.presentingViewController?.view.window - }; - - var focusDelegate: RNIModalFocusNotifiable? { - return self.viewController as? RNIModalFocusNotifiable - }; - - // MARK: - Functions - // ----------------- - - public init(viewController: UIViewController){ - self.viewController = viewController; - RNIModalManagerShared.register(modal: self); - }; -}; - -// MARK: - RNIModalRequestable -// --------------------------- - -extension RNIModalViewControllerWrapper: RNIModalRequestable { - - public func requestModalToShow( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws { - throw RNIModalError( - code: .runtimeError, - message: "presenting is not supported" - ); - }; - - public func requestModalToHide( - sender: Any, - animated: Bool, - completion: @escaping () -> Void - ) throws { - guard let modalVC = self.modalViewController else { - throw RNIModalError( - code: .runtimeError, - message: "Guard check failed, modalViewController is nil" - ); - }; - - modalVC.dismiss(animated: animated) { - completion(); - }; - }; -}; - -// MARK: - RNIModalFocusNotifiable -// ------------------------------- - -extension RNIModalViewControllerWrapper: RNIModalFocusNotifiable { - public func onModalWillFocusNotification(sender: any RNIModal) { - guard let focusDelegate = self.focusDelegate else { return }; - focusDelegate.onModalWillFocusNotification(sender: sender); - }; - - public func onModalDidFocusNotification(sender: any RNIModal) { - guard let focusDelegate = self.focusDelegate else { return }; - focusDelegate.onModalDidFocusNotification(sender: sender); - }; - - public func onModalWillBlurNotification(sender: any RNIModal) { - guard let focusDelegate = self.focusDelegate else { return }; - focusDelegate.onModalWillBlurNotification(sender: sender); - }; - - public func onModalDidBlurNotification(sender: any RNIModal) { - guard let focusDelegate = self.focusDelegate else { return }; - focusDelegate.onModalDidBlurNotification(sender: sender); - }; -}; - - diff --git a/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapperRegistry.swift b/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapperRegistry.swift deleted file mode 100644 index cbbb9099..00000000 --- a/ios/React Native/RNIModalViewControllerWrapper/RNIModalViewControllerWrapperRegistry.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// RNIModalViewControllerWrapperRegistry.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -class RNIModalViewControllerWrapperRegistry { - static let instanceMap = NSMapTable< - UIViewController, - RNIModalViewControllerWrapper - >( - keyOptions: .weakMemory, - valueOptions: .weakMemory - ); - - static func get( - forViewController viewController: UIViewController - ) -> RNIModalViewControllerWrapper? { - - Self.instanceMap.object(forKey: viewController); - }; - - static func set( - forViewController viewController: UIViewController, - _ modalWrapper: RNIModalViewControllerWrapper - ){ - - Self.instanceMap.setObject(modalWrapper, forKey: viewController); - }; - - static func isRegistered( - forViewController viewController: UIViewController - ) -> Bool { - Self.get(forViewController: viewController) != nil; - }; -}; diff --git a/ios/React Native/RNIModalViewModule/RNIModalViewModule.m b/ios/React Native/RNIModalViewModule/RNIModalViewModule.m deleted file mode 100644 index e37b151d..00000000 --- a/ios/React Native/RNIModalViewModule/RNIModalViewModule.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// RNIModalViewModule.m -// RNSwiftReviewer -// -// Created by Dominic Go on 7/11/20. -// - -#import "React/RCTBridgeModule.h" -#import "React/RCTEventEmitter.h" - - -@interface RCT_EXTERN_MODULE(RNIModalViewModule, RCTEventEmitter) - -// MARK: - Standalone Functions -// ---------------------------- - -RCT_EXTERN_METHOD(setModalVisibilityByID: (NSString)modalID - visibility: (BOOL)visibility - animated: (BOOL)visibility - // promise blocks ----------------------- - resolve: (RCTPromiseResolveBlock *)resolve - reject : (RCTPromiseRejectBlock *)reject); - -RCT_EXTERN_METHOD(dismissAllModals: (BOOL)animated - // promise blocks ------------------------ - resolve: (RCTPromiseResolveBlock *)resolve - reject : (RCTPromiseRejectBlock *)reject); - -// MARK: - View-Related Functions -// ------------------------------ - -RCT_EXTERN_METHOD(setModalVisibility: (nonnull NSNumber)node - visibility: (BOOL)visibility - // promise blocks ----------------------- - resolve: (RCTPromiseResolveBlock *)resolve - reject : (RCTPromiseRejectBlock *)reject); - -RCT_EXTERN_METHOD(requestModalInfo: (nonnull NSNumber) node - // promise blocks ----------------------- - resolve: (RCTPromiseResolveBlock *)resolve - reject : (RCTPromiseRejectBlock *)reject); - -@end diff --git a/ios/React Native/RNIModalViewModule/RNIModalViewModule.swift b/ios/React Native/RNIModalViewModule/RNIModalViewModule.swift deleted file mode 100644 index 939c11a7..00000000 --- a/ios/React Native/RNIModalViewModule/RNIModalViewModule.swift +++ /dev/null @@ -1,223 +0,0 @@ -// -// RNIModalViewModule.swift -// RNSwiftReviewer -// -// Created by Dominic Go on 7/11/20. -// - -import Foundation -import React - -@objc(RNIModalViewModule) -class RNIModalViewModule: RCTEventEmitter { - - enum Events: String, CaseIterable { - case placeholderEvent; - }; - - @objc override static func requiresMainQueueSetup() -> Bool { - return false; - }; - - func getModalViewInstance(for node: NSNumber) -> RNIModalView? { - return RNIUtilities.getView( - forNode: node, - type : RNIModalView.self, - bridge : self.bridge - ); - }; - - // MARK: - Event-Related - // ---------------------- - - private var hasListeners = false; - - override func supportedEvents() -> [String]! { - return Self.Events.allCases.map { $0.rawValue }; - }; - - // called when first listener is added - override func startObserving() { - self.hasListeners = true; - }; - - // called when this module's last listener is removed, or dealloc - override func stopObserving() { - self.hasListeners = false; - }; - - func sendModalEvent(event: Events, params: Dictionary) { - guard self.hasListeners else { return }; - self.sendEvent(withName: event.rawValue, body: params); - }; - - // MARK: - Module Functions - // ------------------------ - - @objc func setModalVisibilityByID( - _ modalID: String, - visibility: Bool, - animated: Bool, - // promise blocks ------------------------ - resolve: @escaping RCTPromiseResolveBlock, - reject : @escaping RCTPromiseRejectBlock - ) { - DispatchQueue.main.async { - let modalInstances = RNIModalManagerShared.modalInstances; - - let debugData: Dictionary = [ - "modalID": modalID, - "visibility": visibility, - ]; - - do { - guard modalInstances.count > 0 else { - throw RNIModalError( - code: .runtimeError, - message: "The list of modalInstances is empty", - debugData: debugData - ); - }; - - let targetModal = modalInstances.first { - $0.modalUserID == modalID || $0.modalNativeID == modalID - }; - - guard let targetModal = targetModal else { - let errorMessage = - "Unable to get the matching RNIModalView instance for" - + " modalID: \(modalID)"; - - throw RNIModalError( - code: .runtimeError, - message: errorMessage, - debugData: debugData - ); - }; - - let modalAction = visibility - ? targetModal.requestModalToShow - : targetModal.requestModalToHide; - - try modalAction(animated, visibility) { - // modal dismissed - resolve([:]); - }; - - } catch let error as RNIModalError { - error.invokePromiseRejectBlock(reject); - - } catch { - var errorWrapper = RNIModalError( - code: .unknownError, - error: error - ); - - errorWrapper.addDebugData(debugData); - errorWrapper.invokePromiseRejectBlock(reject); - }; - }; - }; - - @objc func dismissAllModals( - _ animated: Bool, - // promise blocks ------------------------ - resolve: @escaping RCTPromiseResolveBlock, - reject : @escaping RCTPromiseRejectBlock - ) { - DispatchQueue.main.async { - let windows = RNIUtilities.getWindows(); - let rootViewControllers = windows.map { $0.rootViewController }; - - guard rootViewControllers.isEmpty else { - let error = RNIModalError( - code: .runtimeError, - message: "Could not get root view controllers" - ); - - error.invokePromiseRejectBlock(reject); - return; - }; - - rootViewControllers.enumerated().forEach { - let isLast = $0.offset == rootViewControllers.count - 1; - - $0.element?.dismiss(animated: animated) { - guard isLast else { return }; - resolve([:]); - }; - }; - }; - }; - - // MARK: - View-Related Functions - // ------------------------------ - - @objc func setModalVisibility( - _ node: NSNumber, - visibility: Bool, - // promise blocks ------------------------ - resolve: @escaping RCTPromiseResolveBlock, - reject : @escaping RCTPromiseRejectBlock - ){ - DispatchQueue.main.async { - guard let modalView = self.getModalViewInstance(for: node) else { - let error = RNIModalError( - code: .runtimeError, - message: "Unable to get the matching RNIModalView instance for node", - debugData: [ - "node": node, - "visibility": visibility - ] - ); - - error.invokePromiseRejectBlock(reject); - return; - }; - - let modalAction = visibility - ? modalView.presentModal - : modalView.dismissModal; - - do { - try modalAction(true) { - resolve([:]); - }; - - } catch let error as RNIModalError { - error.invokePromiseRejectBlock(reject) - - } catch { - let errorWrapper = RNIModalError( - code: .unknownError, - error: error - ); - - errorWrapper.invokePromiseRejectBlock(reject); - }; - }; - }; - - @objc func requestModalInfo( - _ node: NSNumber, - // promise blocks ------------------------ - resolve: @escaping RCTPromiseResolveBlock, - reject : @escaping RCTPromiseRejectBlock - ){ - DispatchQueue.main.async { - guard let modalView = self.getModalViewInstance(for: node) else { - let errorMessage = - "Unable to get the corresponding RNIModalView instance" - + " for node: \(node)" - - let error = RNIModalError(code: .runtimeError, message: errorMessage); - error.invokePromiseRejectBlock(reject); - return; - }; - - resolve( - modalView.synthesizedBaseEventData.synthesizedJSDictionary - ); - }; - }; -}; diff --git a/ios/React Native/RNIMulticastDelegate/CAAnimationMulticastDelegate.swift b/ios/React Native/RNIMulticastDelegate/CAAnimationMulticastDelegate.swift deleted file mode 100644 index a4993b9a..00000000 --- a/ios/React Native/RNIMulticastDelegate/CAAnimationMulticastDelegate.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// CAAnimationMulticastDelegate.swift -// react-native-ios-modal -// -// Created by Dominic Go on 5/1/23. -// - -import UIKit - - -public class CAAnimationMulticastDelegate: NSObject, CAAnimationDelegate { - - public var emitter: RNIMulticastDelegate = - RNIMulticastDelegate(); - - - public func animationDidStart(_ anim: CAAnimation) { - self.emitter.invoke { - $0.animationDidStart?(anim); - }; - }; - - public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { - self.emitter.invoke { - $0.animationDidStop?(anim, finished: flag); - }; - }; -}; diff --git a/ios/React Native/RNIMulticastDelegate/RNIMulticastDelegate.swift b/ios/React Native/RNIMulticastDelegate/RNIMulticastDelegate.swift deleted file mode 100644 index 05a4d1f6..00000000 --- a/ios/React Native/RNIMulticastDelegate/RNIMulticastDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// MulticastDelegate.swift -// RNSwiftReviewer -// -// Created by Dominic Go on 8/15/20. -// - -import UIKit - - -public class RNIMulticastDelegate { - private let delegates: NSHashTable = NSHashTable.weakObjects(); - - public func add(_ delegate: T) { - delegates.add(delegate); - }; - - public func remove(_ delegate: T) { - self.delegates.remove(delegate); - }; - - public func invoke (_ invocation: @escaping (T) -> Void) { - for delegate in delegates.allObjects { - invocation(delegate) - }; - }; -}; diff --git a/ios/React Native/RNIObjectMetadata/RNIObjectMetadata+Default.swift b/ios/React Native/RNIObjectMetadata/RNIObjectMetadata+Default.swift deleted file mode 100644 index ae8eb150..00000000 --- a/ios/React Native/RNIObjectMetadata/RNIObjectMetadata+Default.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// RNIObjectMetadata+Default.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -fileprivate let RNIObjectMetadataMap = NSMapTable( - keyOptions: .weakMemory, - valueOptions: .strongMemory -); - -public extension RNIObjectMetadata { - var metadata: T? { - set { - if let newValue = newValue { - RNIObjectMetadataMap.setObject(newValue, forKey: self); - - } else { - RNIObjectMetadataMap.removeObject(forKey: self); - }; - } - get { - RNIObjectMetadataMap.object(forKey: self) as? T - } - }; -}; diff --git a/ios/React Native/RNIObjectMetadata/RNIObjectMetadata.swift b/ios/React Native/RNIObjectMetadata/RNIObjectMetadata.swift deleted file mode 100644 index db5040aa..00000000 --- a/ios/React Native/RNIObjectMetadata/RNIObjectMetadata.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// RNIObjectMetadata.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/31/23. -// - -import UIKit - -public protocol RNIObjectMetadata: AnyObject { - associatedtype T: AnyObject; - - var metadata: T? { get set }; -}; diff --git a/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable+Default.swift b/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable+Default.swift deleted file mode 100644 index f7f8e79c..00000000 --- a/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable+Default.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// RNIViewControllerLifeCycleNotifiable+Default.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/27/23. -// - -import UIKit - -extension RNIViewControllerLifeCycleNotifiable { - public func viewDidLoad(sender: UIViewController) { - // no-op - }; - - public func viewDidLayoutSubviews(sender: UIViewController) { - // no-op - }; - - public func viewWillAppear(sender: UIViewController, animated: Bool) { - // no-op - }; - - public func viewDidAppear(sender: UIViewController, animated: Bool) { - // no-op - }; - - public func viewWillDisappear(sender: UIViewController, animated: Bool) { - // no-op - }; - - public func viewDidDisappear(sender: UIViewController, animated: Bool) { - // no-op - }; - - public func willMove(sender: UIViewController, toParent parent: UIViewController?) { - // no-op - }; - - public func didMove(sender: UIViewController, toParent parent: UIViewController?) { - // no-op - }; -}; diff --git a/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable.swift b/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable.swift deleted file mode 100644 index 17be9e41..00000000 --- a/ios/React Native/RNIViewControllerLifeCycleNotifiable/RNIViewControllerLifeCycleNotifiable.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// RNIViewControllerLifeCycleNotifiable.swift -// react-native-ios-modal -// -// Created by Dominic Go on 4/1/23. -// - -import UIKit - -public protocol RNIViewControllerLifeCycleNotifiable: AnyObject { - - func viewDidLoad(sender: UIViewController); - - func viewDidLayoutSubviews(sender: UIViewController); - - func viewWillAppear(sender: UIViewController, animated: Bool); - - func viewDidAppear(sender: UIViewController, animated: Bool); - - /// `Note:2023-04-01-14-39-23` - /// - /// * `UIViewController.isBeingDismissed` or - /// `UIViewController.isMovingFromParent` are `true` during - /// `viewWillDisappear`, whenever a modal is about to be dismissed. - /// - func viewWillDisappear(sender: UIViewController, animated: Bool); - - func viewDidDisappear(sender: UIViewController, animated: Bool); - - func willMove(sender: UIViewController, toParent parent: UIViewController?); - - func didMove(sender: UIViewController, toParent parent: UIViewController?); - -}; - diff --git a/ios/React Native/RNIWeak/RNIWeakArray.swift b/ios/React Native/RNIWeak/RNIWeakArray.swift deleted file mode 100644 index 9dd4dfe8..00000000 --- a/ios/React Native/RNIWeak/RNIWeakArray.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// RNIWeakArray.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/15/23. -// - -import UIKit - - -public class RNIWeakArray { - - public var rawArray: [RNIWeakRef] = []; - - public var purgedArray: [RNIWeakRef] { - self.rawArray.compactMap { - $0.synthesizedRef == nil ? nil : $0; - }; - }; - - public var array: [T] { - let purgedArray = self.purgedArray; - self.rawArray = purgedArray; - - return purgedArray.compactMap { - $0.synthesizedRef; - }; - }; - - public init(initialItems: [T] = []){ - self.rawArray = initialItems.compactMap { - RNIWeakRef(with: $0) - }; - }; - - public func get(index: Int) -> T? { - guard self.rawArray.count < index else { - return nil - }; - - guard let ref = self.rawArray[index].synthesizedRef else { - self.rawArray.remove(at: index); - return nil; - }; - - return ref; - }; - - public func set(index: Int, element: T) { - guard self.rawArray.count < index else { - return; - }; - - self.rawArray[index] = RNIWeakRef(with: element); - }; - - - public func append(element: T){ - self.rawArray.append( - RNIWeakRef(with: element) - ); - }; -}; - diff --git a/ios/React Native/RNIWeak/RNIWeakDictionary.swift b/ios/React Native/RNIWeak/RNIWeakDictionary.swift deleted file mode 100644 index a445684d..00000000 --- a/ios/React Native/RNIWeak/RNIWeakDictionary.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// RNIWeakDictionary.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/15/23. -// - -import UIKit - - -public class RNIWeakDictionary { - - public var rawDict: [K: RNIWeakRef] = [:]; - - public var purgedDict: [K: RNIWeakRef] { - get { - self.rawDict.compactMapValues { - $0.rawRef != nil ? $0 : nil; - } - } - }; - - public var dict: [K: RNIWeakRef] { - get { - let purgedDict = self.purgedDict; - self.rawDict = purgedDict; - - return purgedDict; - } - } - - public func set(for key: K, with value: T){ - self.rawDict[key] = RNIWeakRef(with: value); - }; - - public func get(for key: K) -> T? { - guard let ref = self.rawDict[key]?.synthesizedRef else { - self.rawDict.removeValue(forKey: key); - return nil; - }; - - return ref; - }; - - public subscript(key: K) -> T? { - get { - self.get(for: key); - } - set { - guard let ref = newValue else { return }; - self.set(for: key, with: ref); - } - } -}; - diff --git a/ios/React Native/RNIWeak/RNIWeakRef.swift b/ios/React Native/RNIWeak/RNIWeakRef.swift deleted file mode 100644 index e73462a8..00000000 --- a/ios/React Native/RNIWeak/RNIWeakRef.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// RNIWeakRef.swift -// react-native-ios-modal -// -// Created by Dominic Go on 3/11/23. -// - -import UIKit - - -public class RNIWeakRef { - public weak var rawRef: AnyObject?; - - public var synthesizedRef: T? { - self.rawRef as? T; - }; - - public init(with ref: T) { - self.rawRef = ref as AnyObject; - }; - - public init?(with ref: T?) { - guard let unwrappedRef = ref else { return nil }; - self.rawRef = unwrappedRef as AnyObject; - }; -}; diff --git a/ios/Temp/Extensions+Init/CAGradientLayerType+Init.swift b/ios/Temp/Extensions+Init/CAGradientLayerType+Init.swift deleted file mode 100644 index ea63e8b9..00000000 --- a/ios/Temp/Extensions+Init/CAGradientLayerType+Init.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// CAGradientLayerType+Init.swift -// react-native-ios-navigator -// -// Created by Dominic Go on 4/12/21. -// - -import UIKit - -internal extension CAGradientLayerType { - init?(string: String){ - switch string { - case "axial" : self = .axial; - case "radial": self = .radial; - - case "conic" : - if #available(iOS 12.0, *) { - self = .conic; - - } else { - return nil; - }; - - default: return nil; - } - }; -}; diff --git a/ios/Temp/Extensions+Init/UIImage+Init.swift b/ios/Temp/Extensions+Init/UIImage+Init.swift deleted file mode 100644 index 95772b06..00000000 --- a/ios/Temp/Extensions+Init/UIImage+Init.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// UIImage+Init.swift -// react-native-ios-navigator -// -// Created by Dominic Go on 10/2/21. -// - -import UIKit -import UIKit - -internal extension UIImage.RenderingMode { - init?(string: String){ - switch string { - case "automatic" : self = .automatic; - case "alwaysOriginal": self = .alwaysOriginal; - case "alwaysTemplate": self = .alwaysTemplate; - - default: return nil; - }; - }; -}; - -@available(iOS 13.0, *) -internal extension UIImage.SymbolWeight { - init?(string: String){ - switch string { - case "unspecified": self = .unspecified; - case "ultraLight" : self = .ultraLight; - case "thin" : self = .thin; - case "light" : self = .light; - case "regular" : self = .regular; - case "medium" : self = .medium; - case "semibold" : self = .semibold; - case "bold" : self = .bold; - case "heavy" : self = .heavy; - case "black" : self = .black; - - default: return nil; - }; - }; -}; - -@available(iOS 13.0, *) -internal extension UIImage.SymbolScale { - init?(string: String){ - switch string { - case "default" : self = .`default`; - case "unspecified" : self = .unspecified; - case "small" : self = .small; - case "medium" : self = .medium; - case "large" : self = .large; - - default: return nil; - }; - }; -}; diff --git a/ios/Temp/Extensions/UIColor+Helpers.swift b/ios/Temp/Extensions/UIColor+Helpers.swift deleted file mode 100644 index 89334241..00000000 --- a/ios/Temp/Extensions/UIColor+Helpers.swift +++ /dev/null @@ -1,446 +0,0 @@ -// -// UIColor+Helpers.swift -// IosContextMenuExample -// -// Created by Dominic Go on 11/12/20. -// Copyright © 2020 Facebook. All rights reserved. -// -import UIKit; - - -fileprivate class UIColorHelpers { - struct RGBColor { - var r: CGFloat; - var g: CGFloat; - var b: CGFloat; - - init(r: Int, g: Int, b: Int) { - self.r = CGFloat(r) / 255; - self.g = CGFloat(g) / 255; - self.b = CGFloat(b) / 255; - } - }; - - // css colors strings to UIColor - static let cssColorsToRGB: [String: RGBColor] = [ - // colors red --------------------------------- - "lightsalmon": RGBColor(r: 255, g: 160, b: 122), - "salmon" : RGBColor(r: 250, g: 128, b: 114), - "darksalmon" : RGBColor(r: 233, g: 150, b: 122), - "lightcoral" : RGBColor(r: 240, g: 128, b: 128), - "indianred" : RGBColor(r: 205, g: 92 , b: 92 ), - "crimson" : RGBColor(r: 220, g: 20 , b: 60 ), - "firebrick" : RGBColor(r: 178, g: 34 , b: 34 ), - "red" : RGBColor(r: 255, g: 0 , b: 0 ), - "darkred" : RGBColor(r: 139, g: 0 , b: 0 ), - // colors orange ---------------------------- - "coral" : RGBColor(r: 255, g: 127, b: 80), - "tomato" : RGBColor(r: 255, g: 99 , b: 71), - "orangered" : RGBColor(r: 255, g: 69 , b: 0 ), - "gold" : RGBColor(r: 255, g: 215, b: 0 ), - "orange" : RGBColor(r: 255, g: 165, b: 0 ), - "darkorange": RGBColor(r: 255, g: 140, b: 0 ), - // colors green ---------------------------------------- - "lightyellow" : RGBColor(r: 255, g: 255, b: 224), - "lemonchiffon" : RGBColor(r: 255, g: 250, b: 205), - "lightgoldenrodyellow": RGBColor(r: 250, g: 250, b: 210), - "papayawhip" : RGBColor(r: 255, g: 239, b: 213), - "moccasin" : RGBColor(r: 255, g: 228, b: 181), - "peachpuff" : RGBColor(r: 255, g: 218, b: 185), - "palegoldenrod" : RGBColor(r: 238, g: 232, b: 170), - "khaki" : RGBColor(r: 240, g: 230, b: 140), - "darkkhaki" : RGBColor(r: 189, g: 183, b: 107), - "yellow" : RGBColor(r: 255, g: 255, b: 0 ), - // colors green ------------------------------------- - "lawngreen" : RGBColor(r: 124, g: 252, b: 0 ), - "chartreuse" : RGBColor(r: 127, g: 255, b: 0 ), - "limegreen" : RGBColor(r: 50 , g: 205, b: 50 ), - "lime" : RGBColor(r: 0 , g: 255, b: 0 ), - "forestgreen" : RGBColor(r: 34 , g: 139, b: 34 ), - "green" : RGBColor(r: 0 , g: 128, b: 0 ), - "darkgreen" : RGBColor(r: 0 , g: 100, b: 0 ), - "greenyellow" : RGBColor(r: 173, g: 255, b: 47 ), - "yellowgreen" : RGBColor(r: 154, g: 205, b: 50 ), - "springgreen" : RGBColor(r: 0 , g: 255, b: 127), - "mediumspringgreen": RGBColor(r: 0 , g: 250, b: 154), - "lightgreen" : RGBColor(r: 144, g: 238, b: 144), - "palegreen" : RGBColor(r: 152, g: 251, b: 152), - "darkseagreen" : RGBColor(r: 143, g: 188, b: 143), - "mediumseagreen" : RGBColor(r: 60 , g: 179, b: 113), - "seagreen" : RGBColor(r: 46 , g: 139, b: 87 ), - "olive" : RGBColor(r: 128, g: 128, b: 0 ), - "darkolivegreen" : RGBColor(r: 85 , g: 107, b: 47 ), - "olivedrab" : RGBColor(r: 107, g: 142, b: 35 ), - // colors cyan ------------------------------------- - "lightcyan" : RGBColor(r: 224, g: 255, b: 255), - "cyan" : RGBColor(r: 0 , g: 255, b: 255), - "aqua" : RGBColor(r: 0 , g: 255, b: 255), - "aquamarine" : RGBColor(r: 127, g: 255, b: 212), - "mediumaquamarine": RGBColor(r: 102, g: 205, b: 170), - "paleturquoise" : RGBColor(r: 175, g: 238, b: 238), - "turquoise" : RGBColor(r: 64 , g: 224, b: 208), - "mediumturquoise" : RGBColor(r: 72 , g: 209, b: 204), - "darkturquoise" : RGBColor(r: 0 , g: 206, b: 209), - "lightseagreen" : RGBColor(r: 32 , g: 178, b: 170), - "cadetblue" : RGBColor(r: 95 , g: 158, b: 160), - "darkcyan" : RGBColor(r: 0 , g: 139, b: 139), - "teal" : RGBColor(r: 0 , g: 128, b: 128), - // colors blue ------------------------------------ - "powderblue" : RGBColor(r: 176, g: 224, b: 230), - "lightblue" : RGBColor(r: 173, g: 216, b: 230), - "lightskyblue" : RGBColor(r: 135, g: 206, b: 250), - "skyblue" : RGBColor(r: 135, g: 206, b: 235), - "deepskyblue" : RGBColor(r: 0 , g: 191, b: 255), - "lightsteelblue" : RGBColor(r: 176, g: 196, b: 222), - "dodgerblue" : RGBColor(r: 30 , g: 144, b: 255), - "cornflowerblue" : RGBColor(r: 100, g: 149, b: 237), - "steelblue" : RGBColor(r: 70 , g: 130, b: 180), - "royalblue" : RGBColor(r: 65 , g: 105, b: 225), - "blue" : RGBColor(r: 0 , g: 0 , b: 255), - "mediumblue" : RGBColor(r: 0 , g: 0 , b: 205), - "darkblue" : RGBColor(r: 0 , g: 0 , b: 139), - "navy" : RGBColor(r: 0 , g: 0 , b: 128), - "midnightblue" : RGBColor(r: 25 , g: 25 , b: 112), - "mediumslateblue": RGBColor(r: 123, g: 104, b: 238), - "slateblue" : RGBColor(r: 106, g: 90 , b: 205), - "darkslateblue" : RGBColor(r: 72 , g: 61 , b: 139), - // colors purple ------------------------------- - "lavender" : RGBColor(r: 230, g: 230, b: 250), - "thistle" : RGBColor(r: 216, g: 191, b: 216), - "plum" : RGBColor(r: 221, g: 160, b: 221), - "violet" : RGBColor(r: 238, g: 130, b: 238), - "orchid" : RGBColor(r: 218, g: 112, b: 214), - "fuchsia" : RGBColor(r: 255, g: 0 , b: 255), - "magenta" : RGBColor(r: 255, g: 0 , b: 255), - "mediumorchid": RGBColor(r: 186, g: 85 , b: 211), - "mediumpurple": RGBColor(r: 147, g: 112, b: 219), - "blueviolet" : RGBColor(r: 138, g: 43 , b: 226), - "darkviolet" : RGBColor(r: 148, g: 0 , b: 211), - "darkorchid" : RGBColor(r: 153, g: 50 , b: 204), - "darkmagenta" : RGBColor(r: 139, g: 0 , b: 139), - "purple" : RGBColor(r: 128, g: 0 , b: 128), - "indigo" : RGBColor(r: 75 , g: 0 , b: 130), - // colors pink ------------------------------------ - "pink" : RGBColor(r: 255, g: 192, b: 203), - "lightpink" : RGBColor(r: 255, g: 182, b: 193), - "hotpink" : RGBColor(r: 255, g: 105, b: 180), - "deeppink" : RGBColor(r: 255, g: 20 , b: 147), - "palevioletred" : RGBColor(r: 219, g: 112, b: 147), - "mediumvioletred": RGBColor(r: 199, g: 21 , b: 133), - // colors white --------------------------------- - "white" : RGBColor(r: 255, g: 255, b: 255), - "snow" : RGBColor(r: 255, g: 250, b: 250), - "honeydew" : RGBColor(r: 240, g: 255, b: 240), - "mintcream" : RGBColor(r: 245, g: 255, b: 250), - "azure" : RGBColor(r: 240, g: 255, b: 255), - "aliceblue" : RGBColor(r: 240, g: 248, b: 255), - "ghostwhite" : RGBColor(r: 248, g: 248, b: 255), - "whitesmoke" : RGBColor(r: 245, g: 245, b: 245), - "seashell" : RGBColor(r: 255, g: 245, b: 238), - "beige" : RGBColor(r: 245, g: 245, b: 220), - "oldlace" : RGBColor(r: 253, g: 245, b: 230), - "floralwhite" : RGBColor(r: 255, g: 250, b: 240), - "ivory" : RGBColor(r: 255, g: 255, b: 240), - "antiquewhite" : RGBColor(r: 250, g: 235, b: 215), - "linen" : RGBColor(r: 250, g: 240, b: 230), - "lavenderblush": RGBColor(r: 255, g: 240, b: 245), - "mistyrose" : RGBColor(r: 255, g: 228, b: 225), - // colors gray ----------------------------------- - "gainsboro" : RGBColor(r: 220, g: 220, b: 220), - "lightgray" : RGBColor(r: 211, g: 211, b: 211), - "silver" : RGBColor(r: 192, g: 192, b: 192), - "darkgray" : RGBColor(r: 169, g: 169, b: 169), - "gray" : RGBColor(r: 128, g: 128, b: 128), - "dimgray" : RGBColor(r: 105, g: 105, b: 105), - "lightslategray": RGBColor(r: 119, g: 136, b: 153), - "slategray" : RGBColor(r: 112, g: 128, b: 144), - "darkslategray" : RGBColor(r: 47 , g: 79 , b: 79 ), - "black" : RGBColor(r: 0 , g: 0 , b: 0 ), - // colors brown ---------------------------------- - "cornsilk" : RGBColor(r: 255, g: 248, b: 220), - "blanchedalmond": RGBColor(r: 255, g: 235, b: 205), - "bisque" : RGBColor(r: 255, g: 228, b: 196), - "navajowhite" : RGBColor(r: 255, g: 222, b: 173), - "wheat" : RGBColor(r: 245, g: 222, b: 179), - "burlywood" : RGBColor(r: 222, g: 184, b: 135), - "tan" : RGBColor(r: 210, g: 180, b: 140), - "rosybrown" : RGBColor(r: 188, g: 143, b: 143), - "sandybrown" : RGBColor(r: 244, g: 164, b: 96 ), - "goldenrod" : RGBColor(r: 218, g: 165, b: 32 ), - "peru" : RGBColor(r: 205, g: 133, b: 63 ), - "chocolate" : RGBColor(r: 210, g: 105, b: 30 ), - "saddlebrown" : RGBColor(r: 139, g: 69 , b: 19 ), - "sienna" : RGBColor(r: 160, g: 82 , b: 45 ), - "brown" : RGBColor(r: 165, g: 42 , b: 42 ), - "maroon" : RGBColor(r: 128, g: 0 , b: 0 ) - ]; - - static func normalizeHexString(_ hex: String?) -> String { - guard var hexString = hex else { - return "00000000"; - }; - - if hexString.hasPrefix("#") { - hexString = String(hexString.dropFirst()); - }; - - if hexString.count == 3 || hexString.count == 4 { - hexString = hexString.map { "\($0)\($0)" }.joined(); - }; - - let hasAlpha = hexString.count > 7; - if !hasAlpha { - hexString += "ff"; - }; - - return hexString; - }; -}; - -internal extension UIColor { - - var rgba: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { - var red : CGFloat = 0; - var green: CGFloat = 0; - var blue : CGFloat = 0; - var alpha: CGFloat = 0; - - getRed(&red, green: &green, blue: &blue, alpha: &alpha); - return (red, green, blue, alpha); - }; - - @available(iOS 13.0, *) - static func elementColorFromString(_ string: String) -> UIColor? { - switch string { - // Label Colors - case "label": return .label; - case "secondaryLabel": return .secondaryLabel; - case "tertiaryLabel": return .tertiaryLabel; - case "quaternaryLabel": return .quaternaryLabel; - - // Fill Colors - case "systemFill": return .systemFill; - case "secondarySystemFill": return .secondarySystemFill; - case "tertiarySystemFill": return .tertiarySystemFill; - case "quaternarySystemFill": return .quaternarySystemFill; - - // Text Colors - case "placeholderText": return .placeholderText; - - // Standard Content Background Colors - case "systemBackground": return .systemBackground; - case "secondarySystemBackground": return .secondarySystemBackground; - case "tertiarySystemBackground": return .tertiarySystemBackground; - - // Grouped Content Background Colors - case "systemGroupedBackground": return .systemGroupedBackground; - case "secondarySystemGroupedBackground": return .secondarySystemGroupedBackground; - case "tertiarySystemGroupedBackground": return .tertiarySystemGroupedBackground; - - // Separator Colors - case "separator": return .separator; - case "opaqueSeparator": return .opaqueSeparator; - - // Link Color - case "link": return .link; - - // Non-adaptable Colors - case "darkText": return .darkText; - case "lightText": return .lightText; - - default: return nil; - }; - }; - - static func systemColorFromString(_ string: String) -> UIColor? { - switch string { - // Adaptable Colors - case "systemBlue" : return .systemBlue; - case "systemGreen" : return .systemGreen; - case "systemOrange": return .systemOrange; - case "systemPink" : return .systemPink; - case "systemPurple": return .systemPurple; - case "systemRed" : return .systemRed; - case "systemTeal" : return .systemTeal; - case "systemYellow": return .systemYellow; - - default: break; - }; - - if #available(iOS 13.0, *) { - switch string { - case "systemIndigo" : return .systemIndigo; - - //Adaptable Gray Colors - case "systemGray" : return .systemGray; - case "systemGray2": return .systemGray2; - case "systemGray3": return .systemGray3; - case "systemGray4": return .systemGray4; - case "systemGray5": return .systemGray5; - case "systemGray6": return .systemGray6; - - default: break; - }; - }; - - return nil; - }; - - /// Parse "react native" color to `UIColor` - /// Swift impl. `RCTConvert` color - static func parseColor(value: Any) -> UIColor? { - if let string = value as? String { - if #available(iOS 13.0, *), - let color = Self.elementColorFromString(string) { - - // a: iOS 13+ ui enum colors - return color; - - } else if let color = Self.systemColorFromString(string) { - // b: iOS system enum colors - return color; - - } else { - // c: react-native color string - return UIColor(cssColor: string); - }; - - } else if let dict = value as? NSDictionary { - // d: react-native DynamicColor object - return UIColor(dynamicDict: dict); - }; - - return nil; - }; - - /// create color from css color code string - convenience init?(cssColorCode: String) { - guard let color = UIColorHelpers.cssColorsToRGB[cssColorCode.lowercased()] - else { return nil }; - - self.init(red: color.r, green: color.g, blue: color.b, alpha: 1); - }; - - /// create color from hex color string - convenience init?(hexString: String) { - guard hexString.hasPrefix("#") else { return nil }; - let hexColor: String = UIColorHelpers.normalizeHexString(hexString); - - // invalid hex string - guard hexColor.count == 8 else { return nil }; - - var hexNumber: UInt64 = 0; - let scanner = Scanner(string: hexColor); - - // failed to convert hex string - guard scanner.scanHexInt64(&hexNumber) else { return nil }; - - self.init( - red : CGFloat((hexNumber & 0xff000000) >> 24) / 255, - green: CGFloat((hexNumber & 0x00ff0000) >> 16) / 255, - blue : CGFloat((hexNumber & 0x0000ff00) >> 8 ) / 255, - alpha: CGFloat( hexNumber & 0x000000ff) / 255 - ); - }; - - /// create color from rgb/rgba string - convenience init?(rgbString: String){ - // create mutable copy... - var rgbString = rgbString; - - // check if rgba() string - let hasAlpha = rgbString.hasPrefix("rgba"); - - // remove "rgb(" or "rgba" prefix - rgbString = rgbString.replacingOccurrences( - of: hasAlpha ? "rgba(" : "rgb(", - with: "", - options: [.caseInsensitive] - ); - - // remove ")" suffix - rgbString = rgbString.replacingOccurrences( - of: ")", with: "", options: [.backwards] - ); - - // split up the rgb values seperated by "," - let split = rgbString.components(separatedBy: ","); - - // convert to array of float - let colors = split.compactMap { - NumberFormatter().number(from: $0) as? CGFloat; - }; - - if(colors.count == 3) { - // create UIColor from rgb(...) string - self.init( - red : colors[0] / 255, - green: colors[1] / 255, - blue : colors[2] / 255, - alpha: 1 - ); - - } else if(colors.count == 4) { - // create UIColor from rgba(...) string - self.init( - red : colors[0] / 255, - green: colors[1] / 255, - blue : colors[2] / 255, - alpha: colors[3] - ); - - } else { - // invalid rgb color string - // color array is < 3 or > 4 - return nil; - }; - }; - - /// create color from rgb/rgba/hex/csscolor strings - convenience init?(cssColor: String){ - // remove whitespace characters - let colorString = cssColor.trimmingCharacters(in: .whitespacesAndNewlines); - - if colorString.hasPrefix("#"){ - self.init(hexString: colorString); - return; - - } else if colorString.hasPrefix("rgb") { - self.init(rgbString: colorString); - - } else if let color = UIColorHelpers.cssColorsToRGB[colorString.lowercased()] { - self.init(red: color.r, green: color.g, blue: color.b, alpha: 1); - return; - - } else { - return nil; - }; - }; - - /// create color from `DynamicColorIOS` dictionary - convenience init?(dynamicDict: NSDictionary) { - guard let dict = dynamicDict["dynamic"] as? NSDictionary, - let stringDark = dict["dark" ] as? String, - let stringLight = dict["light"] as? String - else { return nil }; - - if #available(iOS 13.0, *), - let colorDark = UIColor(cssColor: stringDark ), - let colorLight = UIColor(cssColor: stringLight) { - - self.init(dynamicProvider: { traitCollection in - switch traitCollection.userInterfaceStyle { - case .dark : return colorDark; - case .light: return colorLight; - - case .unspecified: fallthrough; - @unknown default : return .clear; - }; - }); - - } else { - self.init(cssColor: stringLight); - }; - }; - -}; diff --git a/ios/Temp/Extensions/UIViewController+Helpers.swift b/ios/Temp/Extensions/UIViewController+Helpers.swift deleted file mode 100644 index 16598e75..00000000 --- a/ios/Temp/Extensions/UIViewController+Helpers.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// UIViewController+Helpers.swift -// react-native-ios-utilities -// -// Created by Dominic Go on 8/26/22. -// - -import UIKit - -internal extension UIViewController { - func attachChildVC(_ child: UIViewController) { - self.addChild(child); - self.view.addSubview(child.view); - child.didMove(toParent: self); - }; - - func detachFromParentVC() { - guard self.parent != nil else { return }; - - self.willMove(toParent: nil); - self.view.removeFromSuperview(); - self.removeFromParent(); - }; -}; diff --git a/ios/Temp/IosUtilities-Bridging-Header.h b/ios/Temp/IosUtilities-Bridging-Header.h deleted file mode 100644 index 2ab2b743..00000000 --- a/ios/Temp/IosUtilities-Bridging-Header.h +++ /dev/null @@ -1,16 +0,0 @@ -#if DEBUG -#import -#endif - -#import -#import - -#import -#import - -#import -#import - -#import -#import -#import diff --git a/ios/Temp/Protocols/RNIJSComponentWillUnmountNotifiable.swift b/ios/Temp/Protocols/RNIJSComponentWillUnmountNotifiable.swift deleted file mode 100644 index 946c4415..00000000 --- a/ios/Temp/Protocols/RNIJSComponentWillUnmountNotifiable.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// RNIJSComponentWillUnmountNotifiable.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/25/22. -// - -import UIKit - - -/// -/// When a class implements this protocol, it means that it receives a notification from JS-side whenever -/// the component's `componentWillUnmount` lifecycle is triggered. -internal protocol RNIJSComponentWillUnmountNotifiable { - - func notifyOnJSComponentWillUnmount(); - -}; diff --git a/ios/Temp/RNICleanup/RNICleanable.swift b/ios/Temp/RNICleanup/RNICleanable.swift deleted file mode 100644 index 0a0f1243..00000000 --- a/ios/Temp/RNICleanup/RNICleanable.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// RNICleanable.swift -// react-native-ios-popover -// -// Created by Dominic Go on 3/13/22. -// - -import UIKit - -/// -/// When a class implements this protocol, it means that the class has "clean-up" related code. -/// This is usually for `UIView` subclasses, and a -internal protocol RNICleanable: AnyObject { - - func cleanup(); - -}; diff --git a/ios/Temp/RNICleanup/RNICleanupMode.swift b/ios/Temp/RNICleanup/RNICleanupMode.swift deleted file mode 100644 index eef47e01..00000000 --- a/ios/Temp/RNICleanup/RNICleanupMode.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// RNICleanupMode.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/20/22. -// - -import UIKit - - -/// If a class conforms to `RNICleanable`, this enum determines how the cleanup routine is triggered. -internal enum RNICleanupMode: String { - - case automatic; - - /// Trigger cleanup via view controller lifecycle - case viewController; - - /// Trigger cleanup via react lifecycle `componentWillUnmount` event sent from js - /// I.e. via `RNIJSComponentWillUnmountNotifiable` - case reactComponentWillUnmount; - - case disabled; - -}; diff --git a/ios/Temp/RNICleanup/RNIInternalCleanupMode.swift b/ios/Temp/RNICleanup/RNIInternalCleanupMode.swift deleted file mode 100644 index a238bcd9..00000000 --- a/ios/Temp/RNICleanup/RNIInternalCleanupMode.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// RNIInternalCleanupMode.swift -// react-native-ios-utilities -// -// Created by Dominic Go on 10/29/22. -// - -import UIKit - - -internal protocol RNIInternalCleanupMode { - /// shadow variable for react prop - var synthesizedInternalCleanupMode: RNICleanupMode { get }; - - /// exported react prop - var internalCleanupMode: String? { get }; - - /// computed property - override behavior for `.automatic` - var cleanupMode: RNICleanupMode { get }; -}; - -// provide default implementation -internal extension RNIInternalCleanupMode { - var shouldEnableAttachToParentVC: Bool { - self.cleanupMode == .viewController - }; - - var shouldEnableCleanup: Bool { - self.cleanupMode != .disabled - }; - - var cleanupMode: RNICleanupMode { - get { - switch self.synthesizedInternalCleanupMode { - case .automatic: return .reactComponentWillUnmount; - default: return self.synthesizedInternalCleanupMode; - }; - } - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageGradientMaker.swift b/ios/Temp/RNIImage/RNIImageGradientMaker.swift deleted file mode 100644 index f04245e2..00000000 --- a/ios/Temp/RNIImage/RNIImageGradientMaker.swift +++ /dev/null @@ -1,181 +0,0 @@ -// -// RNIImageGradientMaker.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/26/22. -// - -import UIKit -import UIKit - - -internal struct RNIImageGradientMaker { - internal enum PointPresets: String { - case top, bottom, left, right; - case bottomLeft, bottomRight, topLeft, topRight; - - internal var cgPoint: CGPoint { - switch self { - case .top : return CGPoint(x: 0.5, y: 0.0); - case .bottom: return CGPoint(x: 0.5, y: 1.0); - - case .left : return CGPoint(x: 0.0, y: 0.5); - case .right: return CGPoint(x: 1.0, y: 0.5); - - case .bottomLeft : return CGPoint(x: 0.0, y: 1.0); - case .bottomRight: return CGPoint(x: 1.0, y: 1.0); - - case .topLeft : return CGPoint(x: 0.0, y: 0.0); - case .topRight: return CGPoint(x: 1.0, y: 0.0); - }; - }; - }; - - internal enum DirectionPresets: String { - // horizontal - case leftToRight, rightToLeft; - // vertical - case topToBottom, bottomToTop; - // diagonal - case topLeftToBottomRight, topRightToBottomLeft; - case bottomLeftToTopRight, bottomRightToTopLeft; - - internal var point: (start: CGPoint, end: CGPoint) { - switch self { - case .leftToRight: - return (CGPoint(x: 0.0, y: 0.5), CGPoint(x: 1.0, y: 1.5)); - - case .rightToLeft: - return (CGPoint(x: 1.0, y: 0.5), CGPoint(x: 0.0, y: 0.5)); - - case .topToBottom: - return (CGPoint(x: 0.5, y: 1.0), CGPoint(x: 0.5, y: 0.0)); - - case .bottomToTop: - return (CGPoint(x: 0.5, y: 1.0), CGPoint(x: 0.5, y: 0.0)); - - case .topLeftToBottomRight: - return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1.0, y: 1.0)); - - case .topRightToBottomLeft: - return (CGPoint(x: 1.0, y: 0.0), CGPoint(x: 0.0, y: 1.0)); - - case .bottomLeftToTopRight: - return (CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 0.0)); - - case .bottomRightToTopLeft: - return (CGPoint(x: 1.0, y: 1.0), CGPoint(x: 0.0, y: 0.0)); - }; - }; - }; - - static private func extractCGPoint(dict: NSDictionary) -> CGPoint? { - guard let x = dict["x"] as? CGFloat, - let y = dict["y"] as? CGFloat - else { return nil }; - - return CGPoint(x: x, y: y); - }; - - static private func extractPoint(dict: NSDictionary, key: String) -> CGPoint? { - if let pointDict = dict[key] as? NSDictionary, - let point = Self.extractCGPoint(dict: pointDict) { - - return point; - - } else if let pointString = dict[key] as? String, - let point = PointPresets(rawValue: pointString) { - - return point.cgPoint; - - } else { - return nil; - }; - } - - internal let type: CAGradientLayerType; - - internal let colors : [CGColor]; - internal let locations : [NSNumber]?; - internal let startPoint: CGPoint; - internal let endPoint : CGPoint; - - internal var size: CGSize; - internal let borderRadius: CGFloat; - - internal var gradientLayer: CALayer { - let layer = CAGradientLayer(); - - layer.type = self.type; - layer.colors = self.colors; - layer.locations = self.locations; - layer.startPoint = self.startPoint; - layer.endPoint = self.endPoint; - layer.cornerRadius = self.borderRadius; - - return layer; - }; - - internal init?(dict: NSDictionary) { - guard let colors = dict["colors"] as? NSArray - else { return nil }; - - self.colors = colors.compactMap { - guard let string = $0 as? String, - let color = UIColor(cssColor: string) - else { return nil }; - - return color.cgColor; - }; - - self.type = { - guard let string = dict["type"] as? String, - let type = CAGradientLayerType(string: string) - else { return .axial }; - - return type; - }(); - - self.locations = { - guard let locations = dict["locations"] as? NSArray else { return nil }; - return locations.compactMap { $0 as? NSNumber }; - }(); - - self.startPoint = Self.extractPoint(dict: dict, key: "startPoint") - ?? PointPresets.top.cgPoint; - - self.endPoint = Self.extractPoint(dict: dict, key: "endPoint") - ?? PointPresets.bottom.cgPoint; - - self.size = CGSize( - width : (dict["width" ] as? CGFloat) ?? 0, - height: (dict["height"] as? CGFloat) ?? 0 - ); - - self.borderRadius = dict["borderRadius"] as? CGFloat ?? 0; - }; - - internal mutating func setSizeIfNotSet(_ newSize: CGSize){ - self.size = CGSize( - width : self.size.width <= 0 ? newSize.width : self.size.width, - height: self.size.height <= 0 ? newSize.height : self.size.height - ); - }; - - internal func makeImage() -> UIImage { - return UIGraphicsImageRenderer(size: self.size).image { context in - let rect = CGRect(origin: .zero, size: self.size); - - let gradient = self.gradientLayer; - gradient.frame = rect; - gradient.render(in: context.cgContext); - - let clipPath = UIBezierPath( - roundedRect : rect, - cornerRadius: self.borderRadius - ); - - clipPath.addClip(); - }; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageItem.swift b/ios/Temp/RNIImage/RNIImageItem.swift deleted file mode 100644 index 0e500540..00000000 --- a/ios/Temp/RNIImage/RNIImageItem.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -// RNIImageItem.swift -// IosNavigatorExample -// -// Created by Dominic Go on 1/29/21. -// - -import UIKit - - -internal class RNIImageItem { - - // MARK: - Properties - Config - // --------------------------- - - internal let type: RNIImageType; - internal let imageValue: Any?; - internal let imageOptions: RNIImageOptions; - - internal var defaultSize: CGSize; - - // MARK: Properties - Misc - // ----------------------- - - internal let imageConfig: RNIImageConfig; - internal var loadedImage: UIImage?; - - // MARK: Properties - Computed - // --------------------------- - - internal var baseImage: UIImage? { - switch self.imageConfig { - case let .IMAGE_ASSET(assetName): - return UIImage(named: assetName); - - case let .IMAGE_SYSTEM(imageConfig): - guard #available(iOS 13.0, *) else { return nil }; - return imageConfig.image; - - case let .IMAGE_REQUIRE(imageConfig): - return imageConfig.image; - - case .IMAGE_EMPTY: - return UIImage(); - - case let .IMAGE_RECT(imageConfig): - return imageConfig.makeImage(); - - case let .IMAGE_GRADIENT(imageConfig): - return imageConfig.makeImage(); - - case let .IMAGE_REMOTE_URL(imageConfig): - return imageConfig.image; - }; - }; - - internal var imageWithTint: UIImage? { - guard var image = self.baseImage else { return nil }; - guard let tint = self.imageOptions.tint else { return image }; - - let isTintTransparent = tint.rgba.a < 1; - - if isTintTransparent { - let overlay = RNIImageMaker(size: image.size, fillColor: tint, borderRadius: 0); - let overlayImage = overlay.makeImage(); - - return UIGraphicsImageRenderer(size: image.size).image { context in - let rect = CGRect(origin: .zero, size: image.size); - - image.draw(in: rect); - overlayImage.draw(in: rect); - }; - }; - - if image.renderingMode != self.imageOptions.renderingMode { - image = image.withRenderingMode(self.imageOptions.renderingMode) - }; - - if #available(iOS 13.0, *) { - image = image.withTintColor( - tint, - renderingMode: self.imageOptions.renderingMode - ); - }; - - return image; - }; - - internal var imageWithRoundedEdges: UIImage? { - guard let image = self.imageWithTint - else { return nil }; - - guard let cornerRadius = self.imageOptions.cornerRadius - else { return image }; - - return UIGraphicsImageRenderer(size: image.size).image { context in - let rect = CGRect(origin: .zero, size: image.size); - - let clipPath = UIBezierPath( - roundedRect : rect, - cornerRadius: cornerRadius - ); - - clipPath.addClip(); - image.draw(in: rect); - }; - }; - - internal var image: UIImage? { - self.imageWithRoundedEdges - }; - - internal var dictionary: [String: Any] { - var dict: [String: Any] = [ - "type": self.type - ]; - - if let imageValue = self.imageValue { - dict["imageValue"] = imageValue; - }; - - return dict; - }; - - // MARK: - Init - // ----------- - - internal init?( - type: RNIImageType, - imageValue: Any?, - imageOptions: NSDictionary?, - imageLoadingConfig: NSDictionary? = nil, - defaultImageSize: CGSize = CGSize(width: 100, height: 100) - ){ - - self.type = type; - self.imageValue = imageValue; - self.defaultSize = defaultImageSize; - - guard let imageConfig: RNIImageConfig = { - switch type { - case .IMAGE_ASSET: - guard let string = imageValue as? String - else { return nil }; - - return .IMAGE_ASSET(assetName: string); - - case .IMAGE_SYSTEM: - guard #available(iOS 13.0, *), - let rawConfig = imageValue as? NSDictionary, - let imageConfig = RNIImageSystemMaker(dict: rawConfig) - else { return nil }; - - return .IMAGE_SYSTEM(config: imageConfig); - - case .IMAGE_REQUIRE: - guard let rawConfig = imageValue as? NSDictionary, - let imageConfig = RNIImageRequireMaker( - dict: rawConfig, - imageLoadingConfig: imageLoadingConfig - ) - else { return nil }; - - return .IMAGE_REQUIRE(config: imageConfig); - - case .IMAGE_EMPTY: - return .IMAGE_EMPTY; - - case .IMAGE_RECT: - guard let rawConfig = imageValue as? NSDictionary, - let imageConfig = RNIImageMaker(dict: rawConfig) - else { return nil }; - - return .IMAGE_RECT(config: imageConfig); - - case .IMAGE_GRADIENT: - guard let rawConfig = imageValue as? NSDictionary, - var imageConfig = RNIImageGradientMaker(dict: rawConfig) - else { return nil }; - - imageConfig.setSizeIfNotSet(defaultImageSize); - return .IMAGE_GRADIENT(config: imageConfig); - - case .IMAGE_REMOTE_URL: - guard let rawConfig = imageValue as? NSDictionary, - let imageConfig = RNIImageRemoteURLMaker( - dict: rawConfig, - imageLoadingConfig: imageLoadingConfig - ) - else { return nil }; - - return .IMAGE_REMOTE_URL(config: imageConfig); - }; - }() else { return nil }; - - self.imageConfig = imageConfig; - self.imageOptions = RNIImageOptions(dict: imageOptions ?? [:]); - }; - - internal convenience init?(dict: NSDictionary){ - guard let typeString = dict["type"] as? String, - let type = RNIImageType(rawValue: typeString) - else { return nil }; - - self.init( - type: type, - imageValue: dict["imageValue"], - imageOptions: dict["imageOptions"] as? NSDictionary, - imageLoadingConfig: dict["imageLoadingConfig"] as? NSDictionary - ); - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageLoadingConfig.swift b/ios/Temp/RNIImage/RNIImageLoadingConfig.swift deleted file mode 100644 index 4b4cde62..00000000 --- a/ios/Temp/RNIImage/RNIImageLoadingConfig.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// RNIImageCacheAndLoadingConfig.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/27/22. -// - -import UIKit - - -internal protocol RNIImageLoadingConfigurable { - var shouldCache: Bool? { get }; - var shouldLazyLoad: Bool? { get }; -}; - -// TODO: Per file defaults via extension -internal struct RNIImageLoadingConfig: RNIImageLoadingConfigurable { - - internal let shouldCache: Bool?; - internal let shouldLazyLoad: Bool?; - - internal init(dict: NSDictionary) { - self.shouldCache = dict["shouldCache"] as? Bool; - self.shouldLazyLoad = dict["shouldLazyLoad"] as? Bool; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageMaker.swift b/ios/Temp/RNIImage/RNIImageMaker.swift deleted file mode 100644 index f96e415a..00000000 --- a/ios/Temp/RNIImage/RNIImageMaker.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// RNIImageMaker.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/26/22. -// - -import UIKit -import UIKit - - -internal struct RNIImageMaker { - - internal let size : CGSize; - internal let fillColor : UIColor; - internal let borderRadius: CGFloat; - - internal init( - size: CGSize, - fillColor: UIColor, - borderRadius: CGFloat - ) { - self.size = size; - self.fillColor = fillColor; - self.borderRadius = borderRadius; - }; - - internal init?(dict: NSDictionary) { - guard let width = dict["width" ] as? CGFloat, - let height = dict["height"] as? CGFloat - else { return nil }; - - self.size = CGSize(width: width, height: height); - - guard let fillColorValue = dict["fillColor" ], - let fillColor = UIColor.parseColor(value: fillColorValue) - else { return nil }; - - self.fillColor = fillColor; - - self.borderRadius = dict["borderRadius"] as? CGFloat ?? 0; - }; - - internal func makeImage() -> UIImage { - return UIGraphicsImageRenderer(size: self.size).image { context in - let rect = CGRect(origin: .zero, size: self.size); - - let clipPath = UIBezierPath( - roundedRect : rect, - cornerRadius: self.borderRadius - ); - - clipPath.addClip(); - self.fillColor.setFill(); - - context.fill(rect); - }; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageOptions.swift b/ios/Temp/RNIImage/RNIImageOptions.swift deleted file mode 100644 index deb7d4c5..00000000 --- a/ios/Temp/RNIImage/RNIImageOptions.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// RNIImageOptions.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/28/22. -// - -import UIKit - - -internal struct RNIImageOptions { - let tint: UIColor?; - let renderingMode: UIImage.RenderingMode; - let cornerRadius: CGFloat?; - - init(dict: NSDictionary){ - self.tint = { - guard let value = dict["tint"], - let color = UIColor.parseColor(value: value) - else { return nil }; - - return color; - }(); - - self.renderingMode = { - guard let string = dict["renderingMode"] as? String, - let mode = UIImage.RenderingMode(string: string) - else { return .automatic }; - - return mode; - }(); - - self.cornerRadius = dict["cornerRadius"] as? CGFloat; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageRemoteURLMaker.swift b/ios/Temp/RNIImage/RNIImageRemoteURLMaker.swift deleted file mode 100644 index bd1ebe15..00000000 --- a/ios/Temp/RNIImage/RNIImageRemoteURLMaker.swift +++ /dev/null @@ -1,361 +0,0 @@ -// -// RNIImageRemoteURLMaker.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/27/22. -// - -import UIKit -import React - - -internal class RNIImageRemoteURLMaker { - - // MARK: - Embedded Types - // ---------------------- - - /// Note: Unable to synthesize `Equatable` conformance because of `Error` associated value. - internal enum State { - - // MARK: - Start State - // ------------------- - - case INITIAL; - - // MARK: - Intermediate State - // -------------------------- - - case LOADING; - - // loading was triggered again because it failed previously - case RETRYING(prevError: Error); - - case LOADED_ERROR (error: Error? = nil); - - // MARK: - Final State - // ------------------- - - case LOADED(image: UIImage); - - // no more remaining retry attempts, don't trigger loading anymore - case LOADED_ERROR_FINAL (error: Error? = nil); - - // MARK: - Computed Properties - // --------------------------- - - var isLoading: Bool { - switch self { - case .LOADING : fallthrough; - case .RETRYING: return true; - - default: return false; - }; - }; - - var error: Error? { - switch self { - case let .LOADED_ERROR(error): return error; - default: return nil; - }; - }; - - var isErrorState: Bool { - switch self { - case .LOADED_ERROR: return true; - default: return false; - }; - }; - - var isFinalState: Bool { - switch self { - case .LOADED : fallthrough; - case .LOADED_ERROR_FINAL: return true; - - default: return false; - }; - }; - }; - - internal typealias ImageDidLoadHandler = ( - _ isSuccess: Bool, - _ sender: RNIImageRemoteURLMaker - ) -> Void; - - // MARK: - Class Members - // --------------------- - - internal static var imageCache: [String: UIImage] = [:]; - - // MARK: - Properties - Serialized - // ------------------------------- - - internal let urlString: String; - - // MARK: - Properties - Derived/Parsed - // ----------------------------------- - - internal let url: URL?; - internal let imageLoadingConfig: RNIRemoteURLImageLoadingConfig; - - internal let fallbackImageConfig: RNIImageItem?; - - // MARK: - Properties - // ------------------ - - internal lazy var imageLoader: RCTImageLoaderWithAttributionProtocol? = { - RNIUtilities.sharedBridge?.module(forName: "ImageLoader") as? - RCTImageLoaderWithAttributionProtocol; - }(); - - internal var state: State = .INITIAL; - internal var loadingAttemptsCount = 0; - - /// Reminder: Use weak self to prevent retain cycle + memory leak - internal var onImageDidLoadBlock: ImageDidLoadHandler?; - - // MARK: - Properties - Computed - // ----------------------------- - - private var cachedImage: UIImage? { - guard self.imageLoadingConfig._shouldCache, - let cachedImage = Self.imageCache[self.urlString] - else { return nil }; - - return cachedImage; - }; - - internal var shouldRetry: Bool { - let maxRetryAttempts = self.imageLoadingConfig._maxRetryAttempts; - - // Note: negative max retry attempt means infinite retry - return maxRetryAttempts < 0 - ? true - : self.loadingAttemptsCount < maxRetryAttempts; - }; - - // Get image w/o triggering loading logic (i.e. no side effects) - // This will also use the fallback image when appropriate - internal var _image: UIImage? { - let fallbackBehavior = self.imageLoadingConfig._fallbackBehavior; - - switch self.state { - case .INITIAL: fallthrough; - case .LOADING: - // A - Use fallback image when the remote image hasn't been loaded yet - switch fallbackBehavior { - case .whileNotLoaded: return self.fallbackImage; - default: return nil; - }; - - case .RETRYING : fallthrough; - case .LOADED_ERROR: - // B - Use fallback image when the remote image hasn't been loaded yet - // due to an error - switch fallbackBehavior { - case .whileNotLoaded: fallthrough; - case .onLoadError : return self.fallbackImage; - - default: return nil; - }; - - case .LOADED_ERROR_FINAL: - // C - Use fallback image when the remote image has failed to load, and - // no more "retry loading" attempts remaining - switch fallbackBehavior { - case .whileNotLoaded : fallthrough; - case .afterFinalAttempt: fallthrough; - case .onLoadError : return self.fallbackImage; - }; - - case .LOADED(image: let image): - return image; - }; - }; - - // Get image + trigger loading logic when not yet loaded - internal var image: UIImage? { - switch self.state { - case .INITIAL: - // A - image not loaded yet... - // trigger image loading so it's loaded the next time - self.loadImage(); - return self._image; - - case .LOADED_ERROR: - // B - image loading failed... - // retry loading so it's loaded next time - self.loadImage(); - fallthrough; - - default: - return self._image; - }; - }; - - internal var synthesizedURLRequest: URLRequest? { - guard let url = self.url else { return nil }; - return URLRequest(url: url); - }; - - internal var fallbackImage: UIImage? { - self.fallbackImageConfig?.image - }; - - // MARK: - Init - // ------------ - - internal init?( - dict: NSDictionary, - imageLoadingConfig: NSDictionary?, - onImageDidLoadBlock: ImageDidLoadHandler? = nil - ){ - guard let urlString = dict["url"] as? String - else { return nil }; - - self.urlString = urlString; - self.url = URL(string: urlString); - - self.fallbackImageConfig = { - guard let rawConfig = dict["fallbackImage"] as? NSDictionary - else { return nil }; - - return RNIImageItem(dict: rawConfig); - }(); - - self.imageLoadingConfig = - RNIRemoteURLImageLoadingConfig(dict: imageLoadingConfig ?? [:]); - - self.onImageDidLoadBlock = onImageDidLoadBlock; - - if self.url != nil { - self.setup(); - - } else if self.fallbackImage != nil { - // B - Failed to construct URL instance from string... - // Use fallback image. - self.state = .LOADED_ERROR(); - - } else { - // C - Failed to construct URL instance from string and no fallback image - // is available - return nil; - }; - }; - - // MARK: Functions - // --------------- - - private func setup(){ - let cachedImage = self.cachedImage; - - let shouldLazyLoad = self.imageLoadingConfig.shouldLazyLoad ?? false; - let shouldUseCache = self.imageLoadingConfig.shouldCache ?? false; - - /// Either: - /// * A - no cache exists for the provided url string - /// * B - image caching has been disabled - let hasCachedImage = shouldUseCache && cachedImage != nil; - - let shouldPreloadImage = !shouldLazyLoad && !hasCachedImage; - - if shouldPreloadImage { - // A - Load image in the bg, so it's potentially ready when the image is - // accessed later... - self.loadImage(); - - } else if hasCachedImage { - // B - Use the cached image that matched with the provided url - self.state = .LOADED(image: cachedImage!); - }; - }; - - internal func loadImage(){ - // still has retry attempts remaining, and not currently loading - let shouldLoad = - self.shouldRetry && !self.state.isFinalState; - - guard shouldLoad, - let urlRequest = self.synthesizedURLRequest, - let imageLoader = self.imageLoader - else { - return; - }; - - let prevError = self.state.error; - let hasPrevError = prevError != nil; - - self.state = hasPrevError - // A - Retry loading the remote image - ? .RETRYING(prevError: prevError!) - // B - Loading the remote image for the 1st time - : .LOADING; - - self.loadingAttemptsCount += 1; - let prevImage = self._image; - - imageLoader.loadImage(with: urlRequest){ [weak self] in - guard let strongSelf = self else { return }; - - if let error = $0 { - strongSelf.state = strongSelf.shouldRetry - // A - Error Loading - Try again - ? .LOADED_ERROR(error: error) - // B - Error Loading - Final attempt - : .LOADED_ERROR_FINAL(error: error); - - let nextImage = strongSelf._image; - - if !RNIUtilities.compareImages(prevImage, nextImage) { - DispatchQueue.main.async { [weak self] in - guard let strongSelf = self else { return }; - - // failed to load image, but is currently using fallback image, so - // notify that it's using the fallback image as a substitute - strongSelf.onImageDidLoadBlock?(false, strongSelf); - }; - }; - - if strongSelf.imageLoadingConfig._shouldImmediatelyRetryLoading { - strongSelf.loadImage(); - }; - - } else if let image = $1 { - DispatchQueue.main.async { [weak self] in - guard let strongSelf = self else { return }; - - strongSelf.state = .LOADED(image: image); - strongSelf.onImageDidLoadBlock?(true, strongSelf); - - if strongSelf.imageLoadingConfig.shouldCache ?? false { - Self.imageCache[strongSelf.urlString] = image; - }; - }; - }; - }; - }; -}; - -// MARK: - RNIRemoteURLImageLoadingConfig - Defaults -// ------------------------------------------------- - -fileprivate extension RNIRemoteURLImageLoadingConfig { - var _shouldLazyLoad: Bool { - self.shouldLazyLoad ?? false; - }; - - var _shouldCache: Bool { - self.shouldCache ?? false; - }; - - var _maxRetryAttempts: Int { - self.maxRetryAttempts ?? 3; - }; - - var _shouldImmediatelyRetryLoading: Bool { - self.shouldImmediatelyRetryLoading ?? false; - }; - - var _fallbackBehavior: FallbackBehavior { - self.fallbackBehavior ?? .onLoadError; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageRequireMaker.swift b/ios/Temp/RNIImage/RNIImageRequireMaker.swift deleted file mode 100644 index 368bdfd7..00000000 --- a/ios/Temp/RNIImage/RNIImageRequireMaker.swift +++ /dev/null @@ -1,76 +0,0 @@ -// -// RNIImageRequireMaker.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 10/4/22. -// - -import UIKit -import React - - -internal class RNIImageRequireMaker { - static private var imageCache: [String: UIImage] = [:]; - - internal let uri: String; - internal let imageLoadingConfig: RNIImageLoadingConfig; - - internal let rawConfig: NSDictionary; - - internal lazy var image: UIImage? = { - let shouldCache = self.imageLoadingConfig._shouldCache; - - if shouldCache, - let cachedImage = Self.imageCache[self.uri] { - - // A - Use cached image - return cachedImage; - }; - - // B - No cached image - let image = RCTConvert.uiImage(self.rawConfig); - - if shouldCache { - Self.imageCache[self.uri] = image; - }; - - return image; - }(); - - internal init?( - dict: NSDictionary, - imageLoadingConfig loadingConfigDict: NSDictionary? - ){ - guard let uriString = dict["uri"] as? String - else { return nil }; - - self.uri = uriString; - self.rawConfig = dict; - - self.imageLoadingConfig = - RNIImageLoadingConfig(dict: loadingConfigDict ?? [:]); - - self.preloadImageIfNeeded(); - }; - - private func preloadImageIfNeeded(){ - guard !self.imageLoadingConfig._shouldLazyLoad - else { return }; - - // trigger loading of image - _ = self.image; - }; -}; - -// MARK: - RNIImageLoadingConfig - Defaults -// ---------------------------------------- - -fileprivate extension RNIImageLoadingConfig { - var _shouldLazyLoad: Bool { - self.shouldLazyLoad ?? false; - }; - - var _shouldCache: Bool { - self.shouldCache ?? false; - }; -}; diff --git a/ios/Temp/RNIImage/RNIImageSystemMaker.swift b/ios/Temp/RNIImage/RNIImageSystemMaker.swift deleted file mode 100644 index 71363867..00000000 --- a/ios/Temp/RNIImage/RNIImageSystemMaker.swift +++ /dev/null @@ -1,113 +0,0 @@ -// -// RNIImageSystemMaker.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/26/22. -// - -import UIKit -import UIKit - - -internal struct RNIImageSystemMaker { - internal let systemName: String; - - internal let pointSize: CGFloat?; - internal let weight: String?; - internal let scale: String?; - - internal let hierarchicalColor: UIColor?; - internal let paletteColors: [UIColor]?; - - @available(iOS 13.0, *) - internal var symbolConfigs: [UIImage.SymbolConfiguration] { - var configs: [UIImage.SymbolConfiguration] = []; - - if let pointSize = self.pointSize { - configs.append( .init(pointSize: pointSize) ); - }; - - if let string = self.weight, - let weight = UIImage.SymbolWeight(string: string) { - - configs.append( .init(weight: weight) ); - }; - - if let string = self.scale, - let scale = UIImage.SymbolScale(string: string) { - - configs.append( .init(scale: scale) ); - }; - - #if swift(>=5.5) - if #available(iOS 15.0, *), - let color = self.hierarchicalColor { - - configs.append( .init(hierarchicalColor: color) ); - }; - - if #available(iOS 15.0, *), - let colors = self.paletteColors { - - configs.append( .init(paletteColors: colors) ); - }; - #endif - - return configs; - }; - - @available(iOS 13.0, *) - internal var symbolConfig: UIImage.SymbolConfiguration? { - var combinedConfig: UIImage.SymbolConfiguration?; - - for config in symbolConfigs { - if let prevCombinedConfig = combinedConfig { - combinedConfig = prevCombinedConfig.applying(config); - - } else { - combinedConfig = config; - }; - }; - - return combinedConfig; - }; - - @available(iOS 13.0, *) - internal var image: UIImage? { - if let symbolConfig = symbolConfig { - return UIImage( - systemName: self.systemName, - withConfiguration: symbolConfig - ); - }; - - return UIImage(systemName: self.systemName); - }; - - internal init?(dict: NSDictionary){ - guard let systemName = dict["systemName"] as? String - else { return nil }; - - self.systemName = systemName; - - self.pointSize = dict["pointSize"] as? CGFloat; - self.weight = dict["weight" ] as? String; - self.scale = dict["scale" ] as? String; - - self.hierarchicalColor = { - guard let value = dict["hierarchicalColor"], - let color = UIColor.parseColor(value: value) - else { return nil }; - - return color; - }(); - - self.paletteColors = { - guard let items = dict["paletteColors"] as? Array - else { return nil }; - - return items.compactMap { UIColor.parseColor(value: $0) }; - }(); - }; -}; - diff --git a/ios/Temp/RNIImage/RNIImageType.swift b/ios/Temp/RNIImage/RNIImageType.swift deleted file mode 100644 index 36518165..00000000 --- a/ios/Temp/RNIImage/RNIImageType.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// RNIImageType.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/26/22. -// - -import UIKit - - -internal enum RNIImageType: String { - case IMAGE_ASSET; - case IMAGE_SYSTEM; - case IMAGE_REQUIRE; - case IMAGE_EMPTY; - case IMAGE_RECT; - case IMAGE_GRADIENT; - case IMAGE_REMOTE_URL; -}; - -internal enum RNIImageConfig { - case IMAGE_ASSET(assetName: String); - case IMAGE_SYSTEM(config: RNIImageSystemMaker); - case IMAGE_REQUIRE(config: RNIImageRequireMaker); - case IMAGE_EMPTY; - case IMAGE_RECT(config: RNIImageMaker); - case IMAGE_GRADIENT(config: RNIImageGradientMaker); - case IMAGE_REMOTE_URL(config: RNIImageRemoteURLMaker); -}; diff --git a/ios/Temp/RNIImage/RNIRemoteURLImageLoadingConfig.swift b/ios/Temp/RNIImage/RNIRemoteURLImageLoadingConfig.swift deleted file mode 100644 index 9dc8f42e..00000000 --- a/ios/Temp/RNIImage/RNIRemoteURLImageLoadingConfig.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// RNIRemoteURLImageLoadingConfig.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 10/2/22. -// - -import UIKit - - - -/// Maps to: `ImageRemoteURLLoadingConfig` -internal struct RNIRemoteURLImageLoadingConfig: RNIImageLoadingConfigurable { - - // MARK: Embedded Types - // -------------------- - - /// Maps to: `ImageRemoteURLFallbackBehavior` - internal enum FallbackBehavior: String { - case afterFinalAttempt; - case whileNotLoaded; - case onLoadError; - }; - - // MARK: Properties - // ---------------- - - internal let shouldCache: Bool?; - internal let shouldLazyLoad: Bool?; - - internal let maxRetryAttempts: Int?; - internal let shouldImmediatelyRetryLoading: Bool?; - internal let fallbackBehavior: FallbackBehavior?; - - // MARK: Init - // ---------- - - internal init(dict: NSDictionary) { - self.shouldCache = dict["shouldCache"] as? Bool; - self.shouldLazyLoad = dict["shouldLazyLoad"] as? Bool; - - self.maxRetryAttempts = dict["maxRetryAttempts"] as? Int; - self.shouldImmediatelyRetryLoading = dict["shouldImmediatelyRetryLoading"] as? Bool; - - self.fallbackBehavior = { - guard let string = dict["fallbackBehavior"] as? String - else { return nil }; - - return FallbackBehavior(rawValue: string); - }(); - }; -}; diff --git a/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsNotifiable.swift b/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsNotifiable.swift deleted file mode 100644 index dcbc931f..00000000 --- a/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsNotifiable.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// RNIContextMenu.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 2/1/22. -// - -import UIKit - -internal protocol RNINavigationEventsNotifiable: NSObject { - - func notifyViewControllerDidPop(sender: RNINavigationEventsReportingViewController); - -}; diff --git a/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsReportingViewController.swift b/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsReportingViewController.swift deleted file mode 100644 index 30ca9803..00000000 --- a/ios/Temp/RNINavigationEventsReporting/RNINavigationEventsReportingViewController.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// RNINavigationEventsReportingViewController.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 2/1/22. -// - -import UIKit; - - -/// When added as a child VC, it will listen to the parent VC + navigation controller for navigation events -/// and report them to it's delegate and root view. -internal class RNINavigationEventsReportingViewController: UIViewController { - - internal weak var parentVC: UIViewController?; - internal weak var delegate: RNINavigationEventsNotifiable?; - - // MARK: - Init - // ------------ - - internal init() { - super.init(nibName: nil, bundle: nil); - }; - - // loaded from a storyboard - internal required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder); - }; - - // MARK: - Lifecycle - // ----------------- - - internal override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated); - - guard let navVC = self.navigationController, - let parentVC = self.parentVC - else { return }; - - // if parent VC still exist in the stack, - // then it hasn't been popped yet... - let isParentVCPopped = { - !navVC.viewControllers.contains(parentVC) - }; - - guard isParentVCPopped() - else { return }; - - let notifyDelegate = { - self.delegate?.notifyViewControllerDidPop(sender: self); - }; - - if animated, - let transitionCoordinator = parentVC.transitionCoordinator { - - transitionCoordinator.animate(alongsideTransition: nil){ _ in - guard isParentVCPopped() else { return }; - notifyDelegate(); - }; - - } else { - notifyDelegate(); - }; - }; -}; diff --git a/ios/Temp/RNIUtilities/RNIUtilities.swift b/ios/Temp/RNIUtilities/RNIUtilities.swift deleted file mode 100644 index 081e617b..00000000 --- a/ios/Temp/RNIUtilities/RNIUtilities.swift +++ /dev/null @@ -1,165 +0,0 @@ -// -// RNIUtilities.swift -// IosNavigatorExample -// -// Created by Dominic Go on 1/9/21. -// - -import UIKit; -import React; - - -internal class RNIUtilities { - - internal static weak var sharedBridge: RCTBridge?; - - internal static let osVersion = ProcessInfo().operatingSystemVersion; - - /// If you remove a "react view" from the view hierarchy (e.g. via - /// `removeFromSuperview`), it won't be released, because it's being retained - /// by the `_viewRegistry` ivar in the shared `UIManager` (singleton) instance. - /// - /// The `_viewRegistry` keeps a ref. to all of the "react views" in the app. - /// This explains how you can get a ref. to a view via `viewForReactTag` and - /// `viewForNativeID` (which also means that `reactTag`/`node` is just an index, - /// i.e. it's just a number that gets inc. every-time a "react view" is added). - /// - /// If you are **absolutely sure** that a particular `reactView` is no longer - /// being used, this helper func. will remove `reactView` (and all of it's - /// subviews) in the `_viewRegistry`. - internal static func recursivelyRemoveFromViewRegistry(bridge: RCTBridge, reactView: UIView) { - - func getRegistry(forKey key: String) -> NSMutableDictionary? { - return bridge.uiManager?.value(forKey: key) as? NSMutableDictionary; - }; - - /// Get a ref to the `_viewRegistry` ivar in the `RCTUIManager` instance. - /// * Note: Unlike objc properties, ivars are "private" so they aren't - /// automagically exposed/bridged to swift. - /// * Note: key: `NSNumber` (the `reactTag`), and value: `UIView` - guard let viewRegistry = getRegistry(forKey: "_viewRegistry") - else { return }; - - /// The "react tags" of the views that were removed - var removedViewTags: [NSNumber] = []; - - func removeView(_ v: UIView){ - /// if this really is a "react view" then it should have a `reactTag` - if let reactTag = v.reactTag, - viewRegistry[reactTag] != nil { - - removedViewTags.append(reactTag); - - /// remove from view hierarchy - v.removeFromSuperview(); - - /// remove this "react view" from the registry - viewRegistry.removeObject(forKey: reactTag); - }; - - /// remove other subviews... - v.subviews.forEach { - removeView($0); - }; - - /// remove other react subviews... - v.reactSubviews()?.forEach { - removeView($0); - }; - }; - - func removeShadowViews(){ - /// Get a ref to the `_shadowViewRegistry` ivar in the `RCTUIManager` instance. - /// Note: Execute on "RCT thread" (i.e. "com.facebook.react.ShadowQueue") - guard let shadowViewRegistry = getRegistry(forKey: "_shadowViewRegistry") - else { return }; - - for reactTag in removedViewTags { - shadowViewRegistry.removeObject(forKey: reactTag); - }; - }; - - DispatchQueue.main.async { - // start recursively removing views... - removeView(reactView); - - // remove shadow views... - RCTExecuteOnUIManagerQueue { - removeShadowViews(); - }; - }; - }; - - /// Recursive climb the responder chain until `T` is found. - /// Useful for finding the corresponding view controller of a view. - internal static func getParent(responder: UIResponder, type: T.Type) -> T? { - var parentResponder: UIResponder? = responder; - - while parentResponder != nil { - parentResponder = parentResponder?.next; - - if let parent = parentResponder as? T { - return parent; - }; - }; - - return nil; - }; - - internal static func getView( - forNode node: NSNumber, - type: T.Type, - bridge: RCTBridge? - ) -> T? { - guard let bridge = bridge, - let view = bridge.uiManager?.view(forReactTag: node) - else { return nil }; - - return view as? T; - }; - - internal static func recursivelyGetAllSubviews(for view: UIView) -> [UIView] { - var views: [UIView] = []; - - for subview in view.subviews { - views += Self.recursivelyGetAllSubviews(for: subview); - views.append(subview); - }; - - return views; - }; - - internal static func recursivelyGetAllSuperViews(for view: UIView) -> [UIView] { - var views: [UIView] = []; - - if let parentView = view.superview { - views.append(parentView); - views += Self.recursivelyGetAllSuperViews(for: parentView); - }; - - return views; - }; - - internal static func compareImages(_ a: UIImage?, _ b: UIImage?) -> Bool { - if (a == nil && b == nil){ - // both are nil, equal - return true; - - } else if a == nil || b == nil { - // one is nil, not equal - return false; - - } else if a! === b! { - // same ref to the object, true - return true; - - } else if a!.size == b!.size { - // size diff, not equal - return true; - }; - - // compare raw data - return a!.isEqual(b!); - }; -}; - diff --git a/ios/Temp/RNIUtilities/RNIUtilitiesModule.m b/ios/Temp/RNIUtilities/RNIUtilitiesModule.m deleted file mode 100644 index fe3e605e..00000000 --- a/ios/Temp/RNIUtilities/RNIUtilitiesModule.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// RNIUtilitiesModule.m -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/27/22. -// - -#import "React/RCTBridgeModule.h" - -@interface RCT_EXTERN_MODULE(RNIUtilitiesModule, NSObject) - -RCT_EXTERN_METHOD(initialize:(NSDictionary *)params); - -@end diff --git a/ios/Temp/RNIUtilities/RNIUtilitiesModule.swift b/ios/Temp/RNIUtilities/RNIUtilitiesModule.swift deleted file mode 100644 index 5982cc54..00000000 --- a/ios/Temp/RNIUtilities/RNIUtilitiesModule.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// RNIUtilitiesModule.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 9/27/22. -// - -import UIKit -import React - - -@objc(RNIUtilitiesModule) -internal class RNIUtilitiesModule: NSObject { - - @objc internal var bridge: RCTBridge! { - willSet { - RNIUtilities.sharedBridge = newValue; - } - }; - - @objc internal static func requiresMainQueueSetup() -> Bool { - // run init in bg thread - return false; - }; - - @objc internal func initialize(_ params: NSDictionary){ - // no-op - }; -}; diff --git a/ios/Temp/RNIWrapperView/RNIWrapperView.swift b/ios/Temp/RNIWrapperView/RNIWrapperView.swift deleted file mode 100644 index d2a19a7b..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperView.swift +++ /dev/null @@ -1,273 +0,0 @@ -// -// RNIWrapperView.swift -// IosNavigatorExample -// -// Created by Dominic Go on 2/1/21. -// - -import UIKit -import React - -/// Holds react views that have been detached, and are no longer managed by RN. -internal class RNIWrapperView: UIView { - - internal static var detachedViews = NSMapTable.init( - keyOptions: .copyIn, - valueOptions: .weakMemory - ); - - // MARK: - Properties - // ------------------ - - internal private(set) var bridge: RCTBridge!; - - internal weak var delegate: RNIWrapperViewEventsNotifiable?; - - /// When `shouldAutoDetachSubviews` is enabled, all the child views that were removed from - /// its parent will be stored here. - /// - /// This is only usually used when `isDummyView` is enabled. - internal var reactViews: [UIView] = []; - - internal var touchHandlers: Dictionary = [:]; - - // MARK: - Properties - Flags - // -------------------------- - - /// Whether or not `cleanup` was triggered. - internal private(set) var didTriggerCleanup = false; - - /// Set this property to `true` before moving this view somewhere else (i.e. - /// before calling `removeFromSuperView`). - /// - /// Setting this property to `true` will prevent triggering `cleanup` when removing this view - /// from it's parent view... - /// - /// After you've finished moving this view, set this back to `false`. - internal var isMovingToParent = false; - - internal var shouldDelayAutoCleanupOnJSUnmount = true; - - // MARK: - RN Exported Props - Config - Lifecycle Related - // ------------------------------------------------------ - - /// When this prop is set to `true`, the JS component will trigger - /// `shouldNotifyComponentWillUnmount` during `componentWillUnmount`. - @objc internal private(set) var shouldNotifyComponentWillUnmount: Bool = false; - - /// This property determines whether `cleanup` should be called when - /// `shouldNotifyComponentWillUnmount` is called. Defaults to: `true`. - /// - /// When `shouldNotifyComponentWillUnmount` prop is true, the JS component - /// will notify it's corresponding native view that it'll be unmounted (i.e. - /// via calling the `shouldNotifyComponentWillUnmount` method). - /// - /// * When a react view is "detached" (i.e. when `removeFromSuperView` is called), - /// the react view is on it's own (the view will leak since it won't be removed - /// when the corresponding view comp. un-mounts). - /// - /// * To get around this, the js comp. notifies the native view that it's - /// going to be unmount in `componentWillUnmount` react lifecycle. - /// - /// * This also fixes the issue where the js comp. has already been unmounted, - /// but it's corresponding native view is still being used. - /// - @objc internal private(set) var shouldAutoCleanupOnJSUnmount = false; - - /// Determines whether `cleanup` is called when this view is removed from the - /// view hierarchy (i.e. when the window ref. becomes nil). - @objc internal private(set) var shouldAutoCleanupOnWindowNil = false; - - /// Determines whether `layoutSubviews` will automatically trigger - /// `notifyForBoundsChange`. Defaults to `true`. - /// - /// * If the layout size is determined from the react/js side, set this to `false`. - /// - /// * Otherwise if the layout size is determined from the native side (e.g. via - /// the view controller, etc.) then set this to `true`. - @objc internal private(set) var shouldAutoSetSizeOnLayout = false; - - // MARK: - RN Exported Props - Config - "Dummy View"-Related - // --------------------------------------------------------- - - /// When set to `true`, the view itself is not the one that's being used for content, as such its a - /// "dummy" view (i.e. its not going to be displayed or used). - /// - /// In this mode, it's child views are the ones that are being used for content, and the parent view will - /// usually get removed from the view hierarchy. - @objc internal private(set) var isDummyView = false; - - /// When enabled, the child views will be automatically removed from it's parent, and will be stored in - /// the `reactViews` property. - /// - /// This is usually enabled together with `isDummyView`. - @objc internal private(set) var shouldAutoDetachSubviews = false; - - // MARK: - RN Exported Props - Config - Touch Handlers - // --------------------------------------------------- - - /// If you are planning on removing the parent view (i.e. this view instance) from the view hierarchy via - /// calling `removeFromSuperview`, and you still want it to receive touch events , then set this - /// property to `true`. - /// - /// When in dummy mode, `shouldAutoDetachSubviews` is usually also enabled. - @objc internal private(set) var shouldCreateTouchHandlerForParentView = false; - - /// If you are planning on removing the subviews from the view hierarchy (i.e. using "dummy view" mode), - /// and you still want them to receive touch event, then set this property to `true`. - @objc internal private(set) var shouldCreateTouchHandlerForSubviews = false; - - - // MARK: - Init/Lifecycle - // --------------------- - - init(bridge: RCTBridge) { - super.init(frame: CGRect()); - self.bridge = bridge; - - if self.shouldCreateTouchHandlerForParentView { - self.touchHandlers[self.reactTag] = { - let handler = RCTTouchHandler(bridge: self.bridge)!; - handler.attach(to: self); - - return handler; - }(); - }; - }; - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented"); - }; - - internal override func layoutSubviews() { - super.layoutSubviews(); - - if self.shouldAutoSetSizeOnLayout { - self.notifyForBoundsChange(size: self.bounds.size); - }; - }; - - internal override func didMoveToWindow() { - - let isMovingToWindowNil = self.window == nil; - - let isOrphaned = self.isDummyView - ? self.reactViews.allSatisfy { $0.superview == nil } - : self.superview == nil; - - /// A: Prevent `cleanup` when changing parent views - /// B: Only trigger cleanup when moving to a `nil` window - let shouldTriggerCleanup = - !self.isMovingToParent && isMovingToWindowNil && isOrphaned; - - if shouldTriggerCleanup { - self.cleanup(); - }; - }; - - internal override func removeFromSuperview() { - super.removeFromSuperview(); - Self.detachedViews.setObject(self, forKey: self.reactTag); - } - - // MARK: - React Lifecycle - // ---------------------- - - internal override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { - super.insertSubview(subview, at: atIndex); - - if self.shouldAutoDetachSubviews { - self.reactViews.append(subview); - subview.removeFromSuperview(); - }; - - if self.shouldCreateTouchHandlerForSubviews { - self.touchHandlers[subview.reactTag] = { - let handler = RCTTouchHandler(bridge: self.bridge); - handler?.attach(to: subview); - - return handler; - }(); - }; - }; - - // MARK: - Functions - // ------------------ - - internal func notifyForBoundsChange(size: CGSize){ - if self.isDummyView { - self.notifyForBoundsChangeForContent(size: size); - - } else { - self.notifyForBoundsChangeForWrapper(size: size); - }; - }; - - internal func notifyForBoundsChangeForWrapper(size: CGSize){ - guard let bridge = self.bridge else { return }; - bridge.uiManager.setSize(size, for: self); - }; - - internal func notifyForBoundsChangeForContent(size: CGSize){ - guard let bridge = self.bridge - else { return }; - - let views = self.isDummyView - ? self.reactViews - : self.subviews; - - for view in views { - bridge.uiManager.setSize(size, for: view); - }; - }; - - // MARK: - Commands For Module - // -------------------------- - - /// Called by `RNIWrapperViewModule.notifyComponentWillUnmount` - internal func onJSComponentWillUnmount(isManuallyTriggered: Bool){ - self.delegate?.onJSComponentWillUnmount( - sender: self, - isManuallyTriggered: isManuallyTriggered - ); - - guard self.shouldAutoCleanupOnJSUnmount else { return }; - - if self.shouldDelayAutoCleanupOnJSUnmount { - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in - self?.cleanup(); - }; - - } else { - self.cleanup(); - }; - }; -}; - - -// MARK: - RNICleanable -// -------------------- - -extension RNIWrapperView: RNICleanable { - - internal func cleanup(){ - guard !self.didTriggerCleanup else { return }; - self.didTriggerCleanup = true; - - let viewsToCleanup = self.reactViews + [self]; - - for view in viewsToCleanup { - if let touchHandler = self.touchHandlers[view.reactTag] { - touchHandler.detach(from: view); - }; - - RNIUtilities.recursivelyRemoveFromViewRegistry( - bridge: self.bridge, - reactView: view - ); - }; - - self.touchHandlers.removeAll(); - self.reactViews.removeAll(); - }; -}; diff --git a/ios/Temp/RNIWrapperView/RNIWrapperViewEventsNotifiable.swift b/ios/Temp/RNIWrapperView/RNIWrapperViewEventsNotifiable.swift deleted file mode 100644 index de401f52..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperViewEventsNotifiable.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// RNIWrapperViewEventsNotifiable.swift -// react-native-ios-context-menu -// -// Created by Dominic Go on 7/17/22. -// - -import Foundation - - -internal protocol RNIWrapperViewEventsNotifiable: AnyObject { - func onJSComponentWillUnmount( - sender: RNIWrapperView, - isManuallyTriggered: Bool - ); -}; diff --git a/ios/Temp/RNIWrapperView/RNIWrapperViewManager.m b/ios/Temp/RNIWrapperView/RNIWrapperViewManager.m deleted file mode 100644 index 2e434632..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperViewManager.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// RNIWrapperViewManager.m -// IosNavigatorExample -// -// Created by Dominic Go on 2/1/21. -// - -#import - -@interface RCT_EXTERN_MODULE(RNIWrapperViewManager, RCTViewManager) - -// MARK: - Export Props - Values -// ----------------------------- - -RCT_EXPORT_VIEW_PROPERTY(shouldNotifyComponentWillUnmount, BOOL); -RCT_EXPORT_VIEW_PROPERTY(shouldAutoCleanupOnJSUnmount, BOOL); -RCT_EXPORT_VIEW_PROPERTY(shouldAutoCleanupOnWindowNil, BOOL); -RCT_EXPORT_VIEW_PROPERTY(shouldAutoSetSizeOnLayout, BOOL); - -RCT_EXPORT_VIEW_PROPERTY(isDummyView, BOOL); -RCT_EXPORT_VIEW_PROPERTY(shouldAutoDetachSubviews, BOOL); - -RCT_EXPORT_VIEW_PROPERTY(shouldCreateTouchHandlerForParentView, BOOL); -RCT_EXPORT_VIEW_PROPERTY(shouldCreateTouchHandlerForSubviews, BOOL); - - - -@end diff --git a/ios/Temp/RNIWrapperView/RNIWrapperViewManager.swift b/ios/Temp/RNIWrapperView/RNIWrapperViewManager.swift deleted file mode 100644 index a5f11ea1..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperViewManager.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// RNIWrapperViewManager.swift -// IosNavigatorExample -// -// Created by Dominic Go on 2/1/21. -// - -import Foundation -import React - -@objc(RNIWrapperViewManager) -internal class RNIWrapperViewManager: RCTViewManager { - - static var sharedBridge: RCTBridge?; - - // MARK: - RN Module Setup - // ----------------------- - - override static func requiresMainQueueSetup() -> Bool { - // run init in bg thread - return false; - }; - - override func view() -> UIView! { - // save a ref to this module's RN bridge instance - if Self.sharedBridge == nil { - Self.sharedBridge = self.bridge; - }; - - return RNIWrapperView(bridge: self.bridge); - }; - - func invalidate(){ - /// reset ref to RCTBridge instance - Self.sharedBridge = nil; - }; -}; - diff --git a/ios/Temp/RNIWrapperView/RNIWrapperViewModule.m b/ios/Temp/RNIWrapperView/RNIWrapperViewModule.m deleted file mode 100644 index 3268f775..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperViewModule.m +++ /dev/null @@ -1,15 +0,0 @@ -// -// RNIWrapperViewModule.m -// react-native-ios-navigator -// -// Created by Dominic Go on 8/3/21. -// - -#import "React/RCTBridgeModule.h" - -@interface RCT_EXTERN_MODULE(RNIWrapperViewModule, NSObject) - -RCT_EXTERN_METHOD(notifyComponentWillUnmount:(nonnull NSNumber *)node - params:(NSDictionary *)params); - -@end diff --git a/ios/Temp/RNIWrapperView/RNIWrapperViewModule.swift b/ios/Temp/RNIWrapperView/RNIWrapperViewModule.swift deleted file mode 100644 index b0816f26..00000000 --- a/ios/Temp/RNIWrapperView/RNIWrapperViewModule.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// RNIWrapperViewModule.swift -// react-native-ios-navigator -// -// Created by Dominic Go on 8/3/21. -// - -import Foundation -import React - -@objc(RNIWrapperViewModule) -internal class RNIWrapperViewModule: NSObject { - - @objc internal private(set) var bridge: RCTBridge!; - - @objc static func requiresMainQueueSetup() -> Bool { - // run init in bg thread - return false; - }; - - func getWrapperView(_ node: NSNumber) -> RNIWrapperView? { - return RNIUtilities.getView( - forNode: node, - type : RNIWrapperView.self, - bridge : self.bridge - ); - }; - - // MARK: - Module Commands: Navigator - // --------------------------------- - - @objc func notifyComponentWillUnmount( - _ node: NSNumber, - params: NSDictionary - ){ - DispatchQueue.main.async { - // get `RNIWrapperView` instance that matches node/reactTag - guard let wrapperView = self.getWrapperView(node) else { - #if DEBUG - print( - "LOG - ViewManager, RNIWrapperViewModule: notifyComponentWillUnmount" - + " - for node: \(node)" - + " - no corresponding view found for node" - + " - the view might have already been unmounted..." - ); - #endif - return; - }; - - wrapperView.onJSComponentWillUnmount( - isManuallyTriggered: params["isManuallyTriggered"] as? Bool ?? false - ); - }; - }; -};