Skip to content

Commit

Permalink
⭐️ Impl: ModalSheetBottomAttachedContentOverlay Scaffolding
Browse files Browse the repository at this point in the history
  • Loading branch information
dominicstop committed Oct 3, 2024
1 parent 49754e1 commit 624fb46
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 0 deletions.
179 changes: 179 additions & 0 deletions ios/RNIModalSheetView/RNIModalSheetDecorationController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//
// RNIModalSheetDecorationController.swift
// react-native-ios-modal
//
// Created by Dominic Go on 10/3/24.
//

import UIKit
import DGSwiftUtilities
import react_native_ios_utilities

#if !RCT_NEW_ARCH_ENABLED
import React
#endif

/// Holds/wraps a `RNIBaseView` instance (i.e. `RNIContentViewParentDelegate`)
///
open class RNIModalSheetDecorationController: UIViewController {

public var shouldTriggerDefaultCleanup = true;

public weak var rootReactView: RNIContentViewParentDelegate?;

public var positionConfig: AlignmentPositionConfig = .default;

// MARK: - Computed Properties
// ---------------------------

public var contentView: RNIContentViewDelegate? {
self.rootReactView?.contentDelegate;
};

// MARK: - View Controller Lifecycle
// ---------------------------------

public override func viewDidLoad() {
guard let rootReactView = self.rootReactView else {
return;
};

#if DEBUG && false
self.log();
#endif

// MARK: Setup Constraints
#if !RCT_NEW_ARCH_ENABLED
rootReactView.removeAllAncestorConstraints();
#endif

rootReactView.translatesAutoresizingMaskIntoConstraints = false;
self.view.addSubview(rootReactView);

NSLayoutConstraint.activate([
rootReactView.leadingAnchor.constraint(
equalTo: rootReactView.leadingAnchor
),
rootReactView.trailingAnchor.constraint(
equalTo: rootReactView.leadingAnchor
),
rootReactView.bottomAnchor.constraint(
equalTo: rootReactView.bottomAnchor
),
rootReactView.topAnchor.constraint(
equalTo: rootReactView.topAnchor
),
]);
};

public override func viewDidLayoutSubviews() {
guard let rootReactView = self.rootReactView else {
return;
};

#if DEBUG && false
self.log();
DispatchQueue.main.asyncAfter(deadline: .now() + 2){
self.log();
};
#endif
};

open override func didMove(toParent parent: UIViewController?) {
guard let parent = parent else {
return;
};

let constraints = self.positionConfig.createConstraints(
forView: self.view,
attachingTo: parent.view,
enclosingView: parent.view
);

self.view.translatesAutoresizingMaskIntoConstraints = false;
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: parent.view.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: parent.view.trailingAnchor),
self.view.bottomAnchor.constraint(equalTo: parent.view.bottomAnchor),
self.view.heightAnchor.constraint(equalToConstant: 100),
]);
}

// MARK: Methods
// --------------

#if DEBUG
func log(funcString: String = #function){
print(
"RNIModalSheetDecorationController.\(funcString)",
"\n - positionConfig:", self.positionConfig,

"\n - window.size:",
self.view.window?.bounds.size.debugDescription ?? "N/A",

"\n - view.size:", self.view.bounds.size,

"\n - view.globalFrame:",
self.view.globalFrame?.debugDescription ?? "N/A",

"\n - view.layer.frame:",
self.view.layer.presentation()?.frame.debugDescription ?? "N/A",

"\n - superview.size:",
self.view.superview?.bounds.size.debugDescription ?? "N/A",

"\n - superview.globalFrame:",
self.view.superview?.globalFrame?.debugDescription ?? "N/A",

"\n - rootReactView.size:",
self.rootReactView?.bounds.size.debugDescription ?? "N/A",

"\n - rootReactView.cachedLayoutMetrics.contentFrame:",
self.rootReactView?.cachedLayoutMetrics?.contentFrame.debugDescription ?? "N/A",

"\n - rootReactView.globalFrame:",
self.rootReactView?.globalFrame?.debugDescription ?? "N/A",

"\n - rootReactView.layer.frame:",
self.rootReactView?.layer.presentation()?.frame.debugDescription ?? "N/A",

"\n - rootReactView.intrinsicContentSize:",
self.rootReactView?.intrinsicContentSize.debugDescription ?? "N/A",

"\n - contentDelegate.bounds.size:",
self.rootReactView?.contentDelegate.bounds.size.debugDescription ?? "N/A",

"\n - contentDelegate.globalFrame:",
self.rootReactView?.contentDelegate.globalFrame?.debugDescription ?? "N/A",

"\n - contentDelegate.layer.frame:",
self.rootReactView?.contentDelegate.layer.presentation()?.frame.debugDescription ?? "N/A",

"\n"
);
};
#endif
};

extension RNIModalSheetDecorationController: RNIViewLifecycle {

public func notifyOnRequestForCleanup(sender: RNIContentViewParentDelegate) {
guard self.shouldTriggerDefaultCleanup,
self.view.window != nil
else {
return;
};

if self.presentingViewController != nil {
self.dismiss(animated: true);

} else if self.parent != nil {
self.willMove(toParent: nil);
self.view.removeFromSuperview();
self.removeFromParent();

} else {
self.view.removeFromSuperview();
};
};
};
26 changes: 26 additions & 0 deletions ios/RNIModalSheetView/RNIModalSheetViewDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public final class RNIModalSheetViewDelegate: UIView, RNIContentView {

enum NativeIDKey: String {
case mainSheetContent;
case bottomAttachedSheetOverlay;
};

public enum Events: String, CaseIterable {
Expand Down Expand Up @@ -55,6 +56,9 @@ public final class RNIModalSheetViewDelegate: UIView, RNIContentView {
public var modalSheetController: RNIModalSheetViewController?;
public var sheetMainContentParentView: RNIContentViewParentDelegate?;

public var sheetBottomAttachedOverlayController: RNIModalSheetDecorationController?;
public var sheetBottomAttachedOverlayParentView: RNIContentViewParentDelegate?;

// MARK: - Properties - RNIContentViewDelegate
// -------------------------------------------

Expand Down Expand Up @@ -117,6 +121,25 @@ public final class RNIModalSheetViewDelegate: UIView, RNIContentView {
modalVC.sheetPresentationStateMachine.eventDelegates.add(self);
modalVC.modalFocusEventDelegates.add(self);

if let sheetBottomAttachedOverlayParentView = self.sheetBottomAttachedOverlayParentView {
let childVC = RNIModalSheetDecorationController();
self.sheetBottomAttachedOverlayController = childVC;

childVC.rootReactView = sheetBottomAttachedOverlayParentView;

childVC.positionConfig = .init(
horizontalAlignment: .stretchTarget,
verticalAlignment: .targetBottom
);

childVC.view.backgroundColor = .red;
childVC.view.alpha = 0.5;

modalVC.view.addSubview(childVC.view);
modalVC.addChild(childVC);
childVC.didMove(toParent: modalVC);
};

return modalVC;
};

Expand Down Expand Up @@ -172,6 +195,9 @@ extension RNIModalSheetViewDelegate: RNIContentViewDelegate {
switch nativeIDKey {
case .mainSheetContent:
self.sheetMainContentParentView = reactView;

case .bottomAttachedSheetOverlay:
self.sheetBottomAttachedOverlayParentView = reactView;
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';

import { ModalSheetContent } from './ModalSheetContent';
import { ModalSheetViewNativeIDKeys } from '../ModalSheetView/ModalSheetViewNativeIDKeys';

import type { ModalSheetViewBottomAttachedContentOverlayProps } from './ModalSheetBottomAttachedContentOverlayTypes';


export function ModalSheetViewBottomAttachedContentOverlay(
props: React.PropsWithChildren<ModalSheetViewBottomAttachedContentOverlayProps>
) {
const { children, ...otherProps } = props;
return (
<ModalSheetContent
{...otherProps}
nativeID={ModalSheetViewNativeIDKeys.bottomAttachedSheetOverlay}
>
{children}
</ModalSheetContent>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ModalSheetContentProps } from './ModalSheetContentTypes';


export type ModalSheetViewBottomAttachedContentOverlayInheritedProps = Pick<ModalSheetContentProps,
| 'contentContainerStyle'
>;

export type ModalSheetViewBottomAttachedContentOverlayBaseProps = {
};

export type ModalSheetViewBottomAttachedContentOverlayProps =
& ModalSheetViewBottomAttachedContentOverlayInheritedProps
& ModalSheetViewBottomAttachedContentOverlayBaseProps;
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

export const ModalSheetViewNativeIDKeys = Object.freeze({
mainSheetContent: 'mainSheetContent',
bottomAttachedSheetOverlay: 'bottomAttachedSheetOverlay',
});
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export * from './components/ModalSheetView/ModalSheetViewTypes';
export * from './components/ModalSheetContent/ModalSheetMainContent';
export * from './components/ModalSheetContent/ModalSheetContentTypes';

export * from './components/ModalSheetContent/ModalSheetBottomAttachedContentOverlay';
export * from './components/ModalSheetContent/ModalSheetBottomAttachedContentOverlayTypes';

export * from './context/ModalSheetViewContext';
export * from './hooks/useModalSheetViewEvents';

Expand Down

0 comments on commit 624fb46

Please sign in to comment.