Skip to content

Commit

Permalink
🛠 Refactor: Cleanup RNIModalView
Browse files Browse the repository at this point in the history
Related: TODO:2023-03-04-06-34-28 - Library Native Cleanup

Summary: Re-arrange properties/methods in `RNIModalView`.
  • Loading branch information
dominicstop committed Mar 17, 2023
1 parent b3cd1a4 commit 6448ba8
Showing 1 changed file with 166 additions and 178 deletions.
344 changes: 166 additions & 178 deletions ios/src_library/React Native/RNIModalView/RNIModalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,166 @@ class RNIModalView: UIView {
self.deinitControllers();
};

};

// ----------------------
// MARK: Public Functions
// ----------------------

extension RNIModalView {
// MARK: - Functions - Private
// ----------------------------

private func initControllers(){
#if DEBUG
print(
"RNIModalView init - initControllers for modal: "
+ "\(self.modalID ?? self.modalUUID as NSString)");
#endif

self.modalVC = {
let vc = RNIModalViewController();
vc.modalViewRef = self;

vc.isBGBlurred = self.isModalBGBlurred;
vc.isBGTransparent = self.isModalBGTransparent;

if let blurStyle = UIBlurEffect.Style.fromString(self.modalBGBlurEffectStyle) {
vc.blurEffectStyle = blurStyle;
};

vc.boundsDidChangeBlock = { [weak self] (newBounds: CGRect) in
self?.notifyForBoundsChange(newBounds);
};

return vc;
}();

self.modalNVC = {
/// by this time, `modalVC` will already be init. so it's ok to force unwrap
let nvc = UINavigationController(rootViewController: self.modalVC!);
nvc.setNavigationBarHidden(true, animated: false);

return nvc;
}();
};

private func deinitControllers(){
#if DEBUG
print("RNIModalView init - deinitControllers for modal: \(self.modalID ?? self.modalUUID as NSString)");
#endif

self.modalVC?.reactView = nil;
self.modalNVC?.viewControllers.removeAll();

self.modalVC = nil;
self.modalNVC = nil;
};

private func notifyForBoundsChange(_ newBounds: CGRect){
guard (self.isPresented),
let bridge = self.bridge,
let reactSubview = self.reactSubview
else {
#if DEBUG
print("RNIModalView, notifyForBoundsChange: guard check failed");
#endif
return;
};

#if DEBUG
print("RNIModalView, notifyForBoundsChange - for reactTag: \(self.reactTag ?? -1)");
#endif

bridge.uiManager.setSize(newBounds.size, for: reactSubview);
};

private func getTopMostPresentedVC() -> (topLevel: Int, topVC: UIViewController)? {
guard let rootVC = UIWindow.key?.rootViewController else {
#if DEBUG
print("RNIModalView, getTopMostVC Error: could not get root VC. ");
#endif
return nil;
};

var index = 0;
var topmostVC = rootVC;

// climb the vc hierarchy to find the topmost presented vc
while topmostVC.presentedViewController != nil {
if let parent = topmostVC.presentedViewController {
index += 1;
topmostVC = parent;
};
};

return (index, topmostVC);
};

private func getPresentedVCList() -> [UIViewController] {
guard let rootVC = UIWindow.key?.rootViewController else {
#if DEBUG
print("RNIModalView, getTopMostVC Error: could not get root VC. ");
#endif
return [];
};

var vcList: [UIViewController] = [];
vcList.append(rootVC);

// climb the vc hierarchy to find the topmost presented vc
while let presentedVC = vcList.last?.presentedViewController {
vcList.append(presentedVC);
};

return vcList;
};

private func isModalInFocus() -> Bool {
guard let (_, vc) = self.getTopMostPresentedVC()
else { return false };

return vc === self.modalNVC;
};

private func enableSwipeGesture(_ flag: Bool? = nil){
self.modalNVC?
.presentationController?
.presentedView?
.gestureRecognizers?[0]
.isEnabled = flag ?? self.enableSwipeGesture;
};

/// helper func to hide/show the other modals that are below level
private func setIsHiddenForViewBelowLevel(_ level: Int, isHidden: Bool){
let presentedVCList = self.getPresentedVCList();

for (index, vc) in presentedVCList.enumerated() {
if index < level {
vc.view.isHidden = isHidden;
};
};
};

// MARK: - Functions - Internal
// ----------------------------

/// helper function to create a `NativeEvent` object
func createModalNativeEventDict() -> Dictionary<AnyHashable, Any> {
var dict: Dictionary<AnyHashable, Any> = [
"modalUUID" : self.modalUUID ,
"isInFocus" : self.isInFocus ,
"isPresented" : self.isPresented ,
"modalLevel" : self.modalLevel ,
"modalLevelPrev": self.modalLevelPrev,
];

if let reactTag = self.reactTag {
dict["reactTag"] = reactTag;
};

if let modalID = self.modalID {
dict["modalID"] = modalID;
};

return dict;
};

// MARK: - Functions - Public
// --------------------------

public func presentModal(completion: CompletionHandler? = nil) {
let hasWindow: Bool = (self.window != nil);
Expand All @@ -349,8 +502,8 @@ extension RNIModalView {
return;
};

/// weird bug where you cant present fullscreen if `presentationController`
/// delegate is set so only set the delegate when we are using a page sheet
// weird bug where you cant present fullscreen if `presentationController`
// delegate is set so only set the delegate when we are using a page sheet
switch self._modalPresentationStyle {
case .automatic, .pageSheet, .formSheet:
modalNVC.presentationController?.delegate = self;
Expand Down Expand Up @@ -451,8 +604,8 @@ extension RNIModalView {
};
};

// MARK: Module Functions
// ----------------------
// MARK: - Functions - Module-Related
// ----------------------------------

public func setModalVisibility(
visibility: Bool,
Expand Down Expand Up @@ -483,173 +636,8 @@ extension RNIModalView {
};
};

// MARK: - Internal Functions
// --------------------------

extension RNIModalView {

/// helper function to create a `NativeEvent` object
func createModalNativeEventDict() -> Dictionary<AnyHashable, Any> {
var dict: Dictionary<AnyHashable, Any> = [
"modalUUID" : self.modalUUID ,
"isInFocus" : self.isInFocus ,
"isPresented" : self.isPresented ,
"modalLevel" : self.modalLevel ,
"modalLevelPrev": self.modalLevelPrev,
];

if let reactTag = self.reactTag {
dict["reactTag"] = reactTag;
};

if let modalID = self.modalID {
dict["modalID"] = modalID;
};

return dict;
};
};

// ----------------------------------
// MARK: Extension: Private Functions
// ----------------------------------

extension RNIModalView {

private func initControllers(){
#if DEBUG
print(
"RNIModalView init - initControllers for modal: "
+ "\(self.modalID ?? self.modalUUID as NSString)");
#endif

self.modalVC = {
let vc = RNIModalViewController();
vc.modalViewRef = self;

vc.isBGBlurred = self.isModalBGBlurred;
vc.isBGTransparent = self.isModalBGTransparent;

if let blurStyle = UIBlurEffect.Style.fromString(self.modalBGBlurEffectStyle) {
vc.blurEffectStyle = blurStyle;
};

vc.boundsDidChangeBlock = { [weak self] (newBounds: CGRect) in
self?.notifyForBoundsChange(newBounds);
};

return vc;
}();

self.modalNVC = {
/// by this time, `modalVC` will already be init. so it's ok to force unwrap
let nvc = UINavigationController(rootViewController: self.modalVC!);
nvc.setNavigationBarHidden(true, animated: false);

return nvc;
}();
};

private func deinitControllers(){
#if DEBUG
print("RNIModalView init - deinitControllers for modal: \(self.modalID ?? self.modalUUID as NSString)");
#endif

self.modalVC?.reactView = nil;
self.modalNVC?.viewControllers.removeAll();

self.modalVC = nil;
self.modalNVC = nil;
};

private func notifyForBoundsChange(_ newBounds: CGRect){
guard (self.isPresented),
let bridge = self.bridge,
let reactSubview = self.reactSubview
else {
#if DEBUG
print("RNIModalView, notifyForBoundsChange: guard check failed");
#endif
return;
};

#if DEBUG
print("RNIModalView, notifyForBoundsChange - for reactTag: \(self.reactTag ?? -1)");
#endif

bridge.uiManager.setSize(newBounds.size, for: reactSubview);
};

private func getTopMostPresentedVC() -> (topLevel: Int, topVC: UIViewController)? {
guard let rootVC = UIWindow.key?.rootViewController else {
#if DEBUG
print("RNIModalView, getTopMostVC Error: could not get root VC. ");
#endif
return nil;
};

var index = 0;
var topmostVC = rootVC;

// climb the vc hierarchy to find the topmost presented vc
while topmostVC.presentedViewController != nil {
if let parent = topmostVC.presentedViewController {
index += 1;
topmostVC = parent;
};
};

return (index, topmostVC);
};

private func getPresentedVCList() -> [UIViewController] {
guard let rootVC = UIWindow.key?.rootViewController else {
#if DEBUG
print("RNIModalView, getTopMostVC Error: could not get root VC. ");
#endif
return [];
};

var vcList: [UIViewController] = [];
vcList.append(rootVC);

// climb the vc hierarchy to find the topmost presented vc
while let presentedVC = vcList.last?.presentedViewController {
vcList.append(presentedVC);
};

return vcList;
};

private func isModalInFocus() -> Bool {
guard let (_, vc) = self.getTopMostPresentedVC()
else { return false };

return vc === self.modalNVC;
};

private func enableSwipeGesture(_ flag: Bool? = nil){
self.modalNVC?
.presentationController?
.presentedView?
.gestureRecognizers?[0]
.isEnabled = flag ?? self.enableSwipeGesture;
};

/// helper func to hide/show the other modals that are below level
private func setIsHiddenForViewBelowLevel(_ level: Int, isHidden: Bool){
let presentedVCList = self.getPresentedVCList();

for (index, vc) in presentedVCList.enumerated() {
if index < level {
vc.view.isHidden = isHidden;
};
};
};
};

// MARK: Extension: UIAdaptivePresentationControllerDelegate
// ---------------------------------------------------------
// MARK: - UIAdaptivePresentationControllerDelegate
// ------------------------------------------------

extension RNIModalView: UIAdaptivePresentationControllerDelegate {

Expand Down

0 comments on commit 6448ba8

Please sign in to comment.