mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at ruby-v 192 lines 5.2 kB view raw
1import ExpoModulesCore 2import UIKit 3 4class SheetView: ExpoView, UISheetPresentationControllerDelegate { 5 // Views 6 private var sheetVc: SheetViewController? 7 private var innerView: UIView? 8 private var touchHandler: RCTTouchHandler? 9 10 // Events 11 private let onAttemptDismiss = EventDispatcher() 12 private let onSnapPointChange = EventDispatcher() 13 private let onStateChange = EventDispatcher() 14 15 // Open event firing 16 private var isOpen: Bool = false { 17 didSet { 18 onStateChange([ 19 "state": isOpen ? "open" : "closed" 20 ]) 21 } 22 } 23 24 // React view props 25 var preventDismiss = false 26 var preventExpansion = false 27 var cornerRadius: CGFloat? 28 var minHeight = 0.0 29 var maxHeight: CGFloat! { 30 didSet { 31 let screenHeight = Util.getScreenHeight() ?? 0 32 if maxHeight > screenHeight { 33 maxHeight = screenHeight 34 } 35 } 36 } 37 38 private var isOpening = false { 39 didSet { 40 if isOpening { 41 onStateChange([ 42 "state": "opening" 43 ]) 44 } 45 } 46 } 47 private var isClosing = false { 48 didSet { 49 if isClosing { 50 onStateChange([ 51 "state": "closing" 52 ]) 53 } 54 } 55 } 56 private var selectedDetentIdentifier: UISheetPresentationController.Detent.Identifier? { 57 didSet { 58 if selectedDetentIdentifier == .large { 59 onSnapPointChange([ 60 "snapPoint": 2 61 ]) 62 } else { 63 onSnapPointChange([ 64 "snapPoint": 1 65 ]) 66 } 67 } 68 } 69 private var prevLayoutDetentIdentifier: UISheetPresentationController.Detent.Identifier? 70 71 // MARK: - Lifecycle 72 73 required init (appContext: AppContext? = nil) { 74 super.init(appContext: appContext) 75 self.maxHeight = Util.getScreenHeight() 76 self.touchHandler = RCTTouchHandler(bridge: appContext?.reactBridge) 77 SheetManager.shared.add(self) 78 } 79 80 deinit { 81 self.destroy() 82 } 83 84 // We don't want this view to actually get added to the tree, so we'll simply store it for adding 85 // to the SheetViewController 86 override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { 87 self.touchHandler?.attach(to: subview) 88 self.innerView = subview 89 } 90 91 // We'll grab the content height from here so we know the initial detent to set 92 override func layoutSubviews() { 93 super.layoutSubviews() 94 95 guard let innerView = self.innerView else { 96 return 97 } 98 99 if innerView.subviews.count != 1 { 100 return 101 } 102 103 self.present() 104 } 105 106 private func destroy() { 107 self.isClosing = false 108 self.isOpen = false 109 self.sheetVc = nil 110 self.touchHandler?.detach(from: self.innerView) 111 self.touchHandler = nil 112 self.innerView = nil 113 SheetManager.shared.remove(self) 114 } 115 116 // MARK: - Presentation 117 118 func present() { 119 guard !self.isOpen, 120 !self.isOpening, 121 !self.isClosing, 122 let innerView = self.innerView, 123 let contentHeight = innerView.subviews.first?.frame.height, 124 let rvc = self.reactViewController() else { 125 return 126 } 127 128 let sheetVc = SheetViewController() 129 sheetVc.setDetents(contentHeight: self.clampHeight(contentHeight), preventExpansion: self.preventExpansion) 130 if let sheet = sheetVc.sheetPresentationController { 131 sheet.delegate = self 132 sheet.preferredCornerRadius = self.cornerRadius 133 self.selectedDetentIdentifier = sheet.selectedDetentIdentifier 134 } 135 sheetVc.view.addSubview(innerView) 136 137 self.sheetVc = sheetVc 138 self.isOpening = true 139 140 rvc.present(sheetVc, animated: true) { [weak self] in 141 self?.isOpening = false 142 self?.isOpen = true 143 } 144 } 145 146 func updateLayout() { 147 if self.prevLayoutDetentIdentifier == self.selectedDetentIdentifier, 148 let contentHeight = self.innerView?.subviews.first?.frame.size.height { 149 self.sheetVc?.updateDetents(contentHeight: self.clampHeight(contentHeight), 150 preventExpansion: self.preventExpansion) 151 self.selectedDetentIdentifier = self.sheetVc?.getCurrentDetentIdentifier() 152 } 153 self.prevLayoutDetentIdentifier = self.selectedDetentIdentifier 154 } 155 156 func dismiss() { 157 self.isClosing = true 158 self.sheetVc?.dismiss(animated: true) { [weak self] in 159 self?.destroy() 160 } 161 } 162 163 // MARK: - Utils 164 165 private func clampHeight(_ height: CGFloat) -> CGFloat { 166 if height < self.minHeight { 167 return self.minHeight 168 } else if height > self.maxHeight { 169 return self.maxHeight 170 } 171 return height 172 } 173 174 // MARK: - UISheetPresentationControllerDelegate 175 176 func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { 177 self.onAttemptDismiss() 178 return !self.preventDismiss 179 } 180 181 func presentationControllerWillDismiss(_ presentationController: UIPresentationController) { 182 self.isClosing = true 183 } 184 185 func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { 186 self.destroy() 187 } 188 189 func sheetPresentationControllerDidChangeSelectedDetentIdentifier(_ sheetPresentationController: UISheetPresentationController) { 190 self.selectedDetentIdentifier = sheetPresentationController.selectedDetentIdentifier 191 } 192}