diff --git a/modules/bottom-sheet/ios/BottomSheetModule.swift b/modules/bottom-sheet/ios/BottomSheetModule.swift
index 4866c41918..488349d2de 100644
--- a/modules/bottom-sheet/ios/BottomSheetModule.swift
+++ b/modules/bottom-sheet/ios/BottomSheetModule.swift
@@ -20,7 +20,6 @@ public class BottomSheetModule: Module {
}
AsyncFunction("updateLayout") { (view: SheetView) in
- view.updateLayout()
}
Prop("containerBackgroundColor") { (view: SheetView, prop: UIColor) in
diff --git a/modules/bottom-sheet/ios/BottomSheetScrollView.swift b/modules/bottom-sheet/ios/BottomSheetScrollView.swift
index 9c0fe0f29f..148f975dc0 100644
--- a/modules/bottom-sheet/ios/BottomSheetScrollView.swift
+++ b/modules/bottom-sheet/ios/BottomSheetScrollView.swift
@@ -6,30 +6,97 @@
//
class BottomSheetScrollView: UIScrollView, UIScrollViewDelegate {
+ private let sheetView: SheetView
private var previousHeight: CGFloat?
+ private var beganDraggingY: CGFloat?
- init() {
+ init(sheetView: SheetView) {
+ self.sheetView = sheetView
super.init(frame: .zero)
if let window = Util.getWindow() {
self.frame = window.bounds
- self.contentInset = UIEdgeInsets(top: 0,
- left: 0,
- bottom: window.safeAreaInsets.bottom,
- right: 0)
+ let offset = window.safeAreaInsets.bottom * 3
+ self.contentInset.bottom = offset
+ self.verticalScrollIndicatorInsets.top = 20
+ self.verticalScrollIndicatorInsets.bottom = offset
}
+
+ self.delegate = self
+
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(keyboardWillShow(notification:)),
+ name: UIResponder.keyboardWillShowNotification,
+ object: nil)
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(keyboardWillHide(notification:)),
+ name: UIResponder.keyboardWillHideNotification,
+ object: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
+ deinit {
+ NotificationCenter.default.removeObserver(self)
+ }
+
override func layoutSubviews() {
super.layoutSubviews()
if let height = self.subviews.first?.frame.size.height,
self.previousHeight != height,
let window = self.window {
- self.contentSize = CGSize(width: window.bounds.width, height: height + window.safeAreaInsets.bottom)
+ let newDetent = self.sheetView.sheetVc.updateDetents(contentHeight: self.sheetView.clampHeight(height),
+ preventExpansion: self.sheetView.preventExpansion)
+ self.sheetView.selectedDetentIdentifier = newDetent
+ self.contentSize = CGSize(width: window.bounds.width, height: height)
+ self.previousHeight = height
+ }
+ }
+
+ @objc func keyboardWillShow(notification: Notification) {
+ if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
+ let keyboardHeight = keyboardFrame.height
+ let newOffset = self.contentInset.bottom + keyboardHeight
+
+ // We purposefully add keyboard height to content inset and only update
+ // the scroll indicator inset
+ self.contentInset.bottom = newOffset
+ self.verticalScrollIndicatorInsets.bottom = keyboardHeight
+
+ if let firstResponder = self.findFirstResponder(),
+ let window = self.window {
+ let position = firstResponder.convert(firstResponder.bounds,
+ to: window)
+
+ if position.minY > window.bounds.height - keyboardHeight {
+ self.setContentOffset(CGPoint(x: 0, y: self.contentOffset.y + keyboardHeight),
+ animated: true)
+ }
+ }
+ }
+ }
+
+ @objc func keyboardWillHide(notification: Notification) {
+ if let window = Util.getWindow() {
+ let offset = window.safeAreaInsets.bottom * 3
+ self.contentInset.bottom = offset
+ self.verticalScrollIndicatorInsets.bottom = offset
+ }
+ }
+
+ func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
+ self.beganDraggingY = self.contentOffset.y
+ }
+
+ func scrollViewDidScroll(_ scrollView: UIScrollView) {
+ if let beganDraggingY = self.beganDraggingY,
+ self.contentOffset.y < beganDraggingY {
+ if let firstResponder = self.findFirstResponder() {
+ firstResponder.resignFirstResponder()
+ }
+ self.beganDraggingY = nil
}
}
}
diff --git a/modules/bottom-sheet/ios/Extensions/UIView+findFirstResponder.swift b/modules/bottom-sheet/ios/Extensions/UIView+findFirstResponder.swift
new file mode 100644
index 0000000000..c8a3b53ed8
--- /dev/null
+++ b/modules/bottom-sheet/ios/Extensions/UIView+findFirstResponder.swift
@@ -0,0 +1,20 @@
+//
+// UIView+findFirstResponder.swift
+// Pods
+//
+// Created by Hailey on 10/9/24.
+//
+
+extension UIView {
+ func findFirstResponder() -> UIView? {
+ if self.isFirstResponder {
+ return self
+ }
+ for subview in subviews {
+ if let responder = subview.findFirstResponder() {
+ return responder
+ }
+ }
+ return nil
+ }
+}
diff --git a/modules/bottom-sheet/ios/SheetView.swift b/modules/bottom-sheet/ios/SheetView.swift
index 6c37848958..9234b8db6c 100644
--- a/modules/bottom-sheet/ios/SheetView.swift
+++ b/modules/bottom-sheet/ios/SheetView.swift
@@ -3,13 +3,8 @@ import UIKit
class SheetView: ExpoView, UISheetPresentationControllerDelegate {
// Views
- private var sheetVc: SheetViewController!
+ var sheetVc: SheetViewController!
private var innerView: UIView?
- private var contentHeight: CGFloat? {
- get {
- self.innerView?.frame.height
- }
- }
// Scroll view
private var scrollView: BottomSheetScrollView!
@@ -59,6 +54,7 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
}
}
}
+
private var isClosing = false {
didSet {
if isClosing {
@@ -68,7 +64,8 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
}
}
}
- private var selectedDetentIdentifier: UISheetPresentationController.Detent.Identifier? {
+
+ var selectedDetentIdentifier: UISheetPresentationController.Detent.Identifier? {
didSet {
if selectedDetentIdentifier == .large {
onSnapPointChange([
@@ -89,12 +86,12 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
required init (appContext: AppContext? = nil) {
super.init(appContext: appContext)
- self.scrollView = BottomSheetScrollView()
-
self.sheetVc = SheetViewController()
if let sheet = self.sheetVc.sheetPresentationController {
sheet.delegate = self
}
+
+ self.scrollView = BottomSheetScrollView(sheetView: self)
self.sheetVc.view.addSubview(self.scrollView)
self.touchHandler = RCTTouchHandler(bridge: appContext?.reactBridge)
@@ -132,12 +129,10 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
guard !self.isOpen,
!self.isOpening,
!self.isClosing,
- let contentHeight = self.contentHeight,
let rvc = self.reactViewController() else {
return
}
- self.sheetVc.setDetents(contentHeight: self.clampHeight(contentHeight), preventExpansion: self.preventExpansion)
if let sheet = sheetVc.sheetPresentationController {
sheet.preferredCornerRadius = self.cornerRadius
self.selectedDetentIdentifier = sheet.selectedDetentIdentifier
@@ -151,16 +146,6 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
}
}
- func updateLayout() {
- if self.prevLayoutDetentIdentifier == self.selectedDetentIdentifier,
- let contentHeight = self.contentHeight {
- self.sheetVc.updateDetents(contentHeight: self.clampHeight(contentHeight),
- preventExpansion: self.preventExpansion)
- self.selectedDetentIdentifier = self.sheetVc.getCurrentDetentIdentifier()
- }
- self.prevLayoutDetentIdentifier = self.selectedDetentIdentifier
- }
-
func dismiss() {
self.isClosing = true
self.sheetVc.dismiss(animated: true) { [weak self] in
@@ -170,7 +155,7 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
// MARK: - Utils
- private func clampHeight(_ height: CGFloat) -> CGFloat {
+ func clampHeight(_ height: CGFloat) -> CGFloat {
if height < self.minHeight {
return self.minHeight
} else if height > self.maxHeight {
diff --git a/modules/bottom-sheet/ios/SheetViewController.swift b/modules/bottom-sheet/ios/SheetViewController.swift
index f79f358c42..04cdec23b0 100644
--- a/modules/bottom-sheet/ios/SheetViewController.swift
+++ b/modules/bottom-sheet/ios/SheetViewController.swift
@@ -20,9 +20,9 @@ class SheetViewController: UIViewController {
}
}
- func setDetents(contentHeight: CGFloat, preventExpansion: Bool) {
+ func setDetents(contentHeight: CGFloat, preventExpansion: Bool) -> UISheetPresentationController.Detent.Identifier? {
guard let sheet = self.sheetPresentationController else {
- return
+ return nil
}
if contentHeight > Util.getScreenHeight() - 100 {
@@ -48,17 +48,20 @@ class SheetViewController: UIViewController {
}
sheet.selectedDetentIdentifier = .medium
}
+ return sheet.selectedDetentIdentifier
}
- func updateDetents(contentHeight: CGFloat, preventExpansion: Bool) {
+ func updateDetents(contentHeight: CGFloat, preventExpansion: Bool) -> UISheetPresentationController.Detent.Identifier? {
+ var newDetent: UISheetPresentationController.Detent.Identifier?
if let sheet = self.sheetPresentationController {
sheet.animateChanges {
- self.setDetents(contentHeight: contentHeight, preventExpansion: preventExpansion)
+ newDetent = self.setDetents(contentHeight: contentHeight, preventExpansion: preventExpansion)
if #available(iOS 16.0, *) {
sheet.invalidateDetents()
}
}
}
+ return newDetent
}
func getCurrentDetentIdentifier() -> UISheetPresentationController.Detent.Identifier? {
diff --git a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx
index 0d0afe3536..a43abc50d8 100644
--- a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx
+++ b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx
@@ -2,10 +2,7 @@ import * as React from 'react'
import {
Dimensions,
NativeSyntheticEvent,
- Platform,
- ScrollView,
StyleProp,
- View,
ViewStyle,
} from 'react-native'
import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
@@ -66,7 +63,6 @@ export class BottomSheetNativeComponent extends React.Component<
render() {
const {children, ...rest} = this.props
- const cornerRadius = rest.cornerRadius ?? 0
if (!this.state.open) {
return null
@@ -82,19 +78,7 @@ export class BottomSheetNativeComponent extends React.Component<
height: screenHeight,
width: '100%',
}}>
- {/**/}
{children}
- {/**/}
)
}
diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx
index 659e4e31d5..b844e9eddc 100644
--- a/src/components/Dialog/index.tsx
+++ b/src/components/Dialog/index.tsx
@@ -1,26 +1,17 @@
import React, {useImperativeHandle} from 'react'
import {
- NativeScrollEvent,
- NativeSyntheticEvent,
Pressable,
processColor,
- ScrollView,
StyleProp,
TextInput,
View,
ViewStyle,
} from 'react-native'
-import {
- KeyboardAwareScrollView,
- useKeyboardHandler,
-} from 'react-native-keyboard-controller'
-import {runOnJS} from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {logger} from '#/logger'
-import {isAndroid, isIOS} from '#/platform/detection'
import {useA11y} from '#/state/a11y'
import {useDialogStateControlContext} from '#/state/dialogs'
import {List, ListMethods, ListProps} from '#/view/com/util/List'
@@ -161,6 +152,7 @@ export function Outer({
onSnapPointChange={onSnapPointChange}
onStateChange={onStateChange}
disableDrag={disableDrag}
+ // @ts-expect-error @TODO
containerBackgroundColor={processColor(t.atoms.bg.backgroundColor)}>
{children}
@@ -169,69 +161,16 @@ export function Outer({
)
}
-export function Inner({children, style}: DialogInnerProps) {
- const insets = useSafeAreaInsets()
+export function Inner({children, style, ...props}: DialogInnerProps) {
return (
-
+
{children}
)
}
-export const ScrollableInner = React.forwardRef(
- function ScrollableInner({children, style, ...props}, ref) {
- const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
- const insets = useSafeAreaInsets()
- const [keyboardHeight, setKeyboardHeight] = React.useState(0)
- useKeyboardHandler({
- onEnd: e => {
- 'worklet'
- runOnJS(setKeyboardHeight)(e.height)
- },
- })
-
- const basePading =
- (isIOS ? 30 : 50) + (isIOS ? keyboardHeight / 4 : keyboardHeight)
- const fullPaddingBase = insets.bottom + insets.top + basePading
- const fullPadding = isIOS ? fullPaddingBase : fullPaddingBase + 50
-
- const paddingBottom =
- nativeSnapPoint === BottomSheetSnapPoint.Full ? fullPadding : basePading
-
- const onScroll = (e: NativeSyntheticEvent) => {
- const {contentOffset} = e.nativeEvent
- if (contentOffset.y > 0 && !disableDrag) {
- setDisableDrag(true)
- } else if (contentOffset.y <= 1 && disableDrag) {
- setDisableDrag(false)
- }
- }
-
- return children
-
- return (
-
- {children}
-
- )
- },
-)
+// @TODO remove this later
+export const ScrollableInner = Inner
export const InnerFlatList = React.forwardRef<
ListMethods,
diff --git a/src/components/ReportDialog/index.tsx b/src/components/ReportDialog/index.tsx
index 5bf8aa5b4b..ed75488a9d 100644
--- a/src/components/ReportDialog/index.tsx
+++ b/src/components/ReportDialog/index.tsx
@@ -1,6 +1,5 @@
import React from 'react'
import {Pressable, View} from 'react-native'
-import {ScrollView} from 'react-native-gesture-handler'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -38,10 +37,8 @@ function ReportDialogInner(props: ReportDialogProps) {
} = useMyLabelersQuery()
const isLoading = useDelayedLoading(500, isLabelerLoading)
- const ref = React.useRef(null)
-
return (
-
+
{isLoading ? (