diff --git a/ios/src_library/React Native/RNIModal/RNIModal+Helpers.swift b/ios/src_library/React Native/RNIModal/RNIModal+Helpers.swift index 5657c03e..549eeb3f 100644 --- a/ios/src_library/React Native/RNIModal/RNIModal+Helpers.swift +++ b/ios/src_library/React Native/RNIModal/RNIModal+Helpers.swift @@ -73,6 +73,11 @@ extension RNIModalState where Self: RNIModalPresentation { guard let window = self.window else { return nil }; return RNIModalWindowMapShared.get(forWindow: window); }; + + public var isModalInFocus: Bool { + self.modalPresentationState.isPresented && + self.modalFocusState.state.isFocused; + }; }; extension RNIModalState where Self: RNIModal { diff --git a/ios/src_library/React Native/RNIModal/RNIModal.swift b/ios/src_library/React Native/RNIModal/RNIModal.swift index b269e7c0..75dd9c53 100644 --- a/ios/src_library/React Native/RNIModal/RNIModal.swift +++ b/ios/src_library/React Native/RNIModal/RNIModal.swift @@ -33,10 +33,9 @@ public protocol RNIModalState: AnyObject { var modalIndex: Int! { set get }; - - var isModalInFocus: Bool { set get }; var modalPresentationState: RNIModalPresentationStateMachine { set get }; + var modalFocusState: RNIModalFocusStateMachine { set get }; }; /// Contains functions that are invoked to request modal-related actions. diff --git a/ios/src_library/React Native/RNIModal/RNIModalFocusState.swift b/ios/src_library/React Native/RNIModal/RNIModalFocusState.swift new file mode 100644 index 00000000..17884267 --- /dev/null +++ b/ios/src_library/React Native/RNIModal/RNIModalFocusState.swift @@ -0,0 +1,93 @@ +// +// RNIModalFocusState.swift +// react-native-ios-modal +// +// Created by Dominic Go on 4/8/23. +// + +import Foundation + + +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 { + + // MARK: - Properties + // ------------------ + + private(set) public var state: RNIModalFocusState = .INITIAL; + private(set) public var statePrev: RNIModalFocusState = .INITIAL; + + // 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; + }; + }; +}; diff --git a/ios/src_library/React Native/RNIModal/RNIModalManager.swift b/ios/src_library/React Native/RNIModal/RNIModalManager.swift index 06e573e7..7760d13e 100644 --- a/ios/src_library/React Native/RNIModal/RNIModalManager.swift +++ b/ios/src_library/React Native/RNIModal/RNIModalManager.swift @@ -280,8 +280,6 @@ public class RNIModalManager { modal.modalIndex = -1; modal.modalIndexPrev = -1; - modal.isModalInFocus = false; - modal.modalPresentationNotificationDelegate = self; self.modalInstanceDict[modal.synthesizedUUID] = modal; }; @@ -355,6 +353,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { ); #endif + sender.modalFocusState.set(state: .FOCUSING); sender.modalPresentationState.set(state: .PRESENTING_UNKNOWN); sender.onModalWillFocusNotification(sender: sender); @@ -363,6 +362,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { $0.isModalInFocus else { return }; + $0.modalFocusState.set(state: .BLURRING); $0.onModalWillBlurNotification(sender: sender); }; }; @@ -417,7 +417,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { ); #endif - sender.isModalInFocus = true; + sender.modalFocusState.set(state: .FOCUSED); sender.modalPresentationState.set(state: .PRESENTED_UNKNOWN); sender.onModalDidFocusNotification(sender: sender); @@ -428,7 +428,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { else { return }; $0.onModalDidBlurNotification(sender: sender); - $0.isModalInFocus = false; + $0.modalFocusState.set(state: .BLURRED); }; }; @@ -485,6 +485,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { ); #endif + sender.modalFocusState.set(state: .BLURRING); sender.modalPresentationState.set(state: .DISMISSING_UNKNOWN); sender.onModalWillBlurNotification(sender: sender); @@ -493,6 +494,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { !$0.isModalInFocus else { return }; + $0.modalFocusState.set(state: .FOCUSING); $0.onModalWillFocusNotification(sender: sender); }; }; @@ -547,7 +549,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { ); #endif - sender.isModalInFocus = false; + sender.modalFocusState.set(state: .BLURRED); sender.modalPresentationState.set(state: .DISMISSED); sender.onModalDidBlurNotification(sender: sender); @@ -558,7 +560,7 @@ extension RNIModalManager: RNIModalPresentationNotifiable { else { return }; $0.onModalDidFocusNotification(sender: sender); - $0.isModalInFocus = true; + sender.modalFocusState.set(state: .FOCUSED); }; }; }; diff --git a/ios/src_library/React Native/RNIModal/RNIModalPresentationState.swift b/ios/src_library/React Native/RNIModal/RNIModalPresentationState.swift index 8e123b96..467cae73 100644 --- a/ios/src_library/React Native/RNIModal/RNIModalPresentationState.swift +++ b/ios/src_library/React Native/RNIModal/RNIModalPresentationState.swift @@ -18,10 +18,7 @@ public enum RNIModalPresentationState: String, CaseIterable { case PRESENTING_PROGRAMMATIC; case PRESENTING_UNKNOWN; - case PRESENTED_FOCUSING; - case PRESENTED_FOCUSED; - case PRESENTED_BLURRING; - case PRESENTED_BLURRED; + case PRESENTED; case PRESENTED_UNKNOWN; case DISMISSING_GESTURE; @@ -44,11 +41,8 @@ public enum RNIModalPresentationState: String, CaseIterable { case .PRESENTING_UNKNOWN : return 1; - case .PRESENTED_FOCUSING: fallthrough; - case .PRESENTED_FOCUSED : fallthrough; - case .PRESENTED_BLURRING: fallthrough; - case .PRESENTED_BLURRED : fallthrough; - case .PRESENTED_UNKNOWN : + case .PRESENTED : fallthrough + case .PRESENTED_UNKNOWN: return 2; case .DISMISSING_GESTURE : fallthrough; @@ -97,10 +91,7 @@ public enum RNIModalPresentationState: String, CaseIterable { public var isPresented: Bool { switch self { - case .PRESENTED_FOCUSING, - .PRESENTED_FOCUSED, - .PRESENTED_BLURRING, - .PRESENTED_BLURRED, + case .PRESENTED, .PRESENTED_UNKNOWN: return true; @@ -135,10 +126,6 @@ public enum RNIModalPresentationState: String, CaseIterable { public var isDismissed: Bool { self == .DISMISSED; }; - - public var isInFocus: Bool { - self == .PRESENTED_FOCUSED; - }; }; public struct RNIModalPresentationStateMachine { @@ -162,10 +149,6 @@ public struct RNIModalPresentationStateMachine { self.state.isPresented }; - public var isInFocus: Bool { - self.state.isInFocus - }; - public var wasDismissViaGestureCancelled: Bool { self.statePrev.isDismissViaGestureCancelling }; diff --git a/ios/src_library/React Native/RNIModalView/RNIModalView.swift b/ios/src_library/React Native/RNIModalView/RNIModalView.swift index efa0a404..90773838 100644 --- a/ios/src_library/React Native/RNIModalView/RNIModalView.swift +++ b/ios/src_library/React Native/RNIModalView/RNIModalView.swift @@ -55,7 +55,7 @@ public class RNIModalView: UIView, RNIIdentifiable, } ); - public var isModalInFocus: Bool = false; + public var modalFocusState = RNIModalFocusStateMachine(); // MARK: - Properties - RNIModalPresentation // -----------------------------------------