[Critical Bug] App Freezes on Android When Opening Modals (+ Button & Long Press on Channel Message) After RN 0.76.x Upgrade

[Problem/Question]
Hi Sendbird Community,

I am encountering a critical issue with Sendbird UIKit on Android. The app freezes completely when interacting with certain UI elements that trigger a modal. Specifically, the freeze occurs in the following cases:

  1. When tapping the “+” button in a channel.
  2. When long-pressing a message related to channel.

This issue does not happen on iOS or in the simulator—only on Android physical devices.

Key Observations:

  • This issue started appearing after upgrading from React Native 0.75.x to 0.76.x.
  • If I minimize the app and reopen it, the issue no longer occurs. Everything works fine after reopening.
  • I inspected the Sendbird UIKit code and noticed that the freeze happens when the Modal component from Sendbird is used. This might be the root cause of the issue.
  • Logcat error when freeze occurs:
Got DOWN touch before receiving UP or CANCEL from last gesture

[UIKit Version]

  • Sendbird UIKit: 3.8.6
  • React Native version: 0.76.7 (Issue started after upgrading to 0.76.x)

[Reproduction Steps]

  • In a channel, tap the “+” button to open the attachment menu or long press on a message.
  • The app freezes, and the UI becomes unresponsive.
  • Force close the app (remove it from recent apps) and reopen it.
  • Repeat the same actions (“+” button or long press on a message), and the freeze happens again.
  • However, if you minimize the app before testing the freeze and then try the same actions, the app does not freeze anymore, and everything works as expected.

[Frequency]

  • Happens 100% of the time on Android.
  • Does NOT happen on iOS or in the simulator.

[Current impact]

  • The app becomes completely unresponsive when trying to open a modal-related component in Sendbird.
  • Users cannot interact with the app unless they minimize and reopen it.
  • This is highly critical as it blocks core functionality in channels.

I would appreciate any guidance or solutions to resolve this issue. Thank you in advance!

Best regards,
Yurii

I have already managed with it.
@sendbird-uikit-react-native-foundation-npm-3.3.0-25f9e4acde.patch :

diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index fc798390cc467dc7a55e593631d5e4efdd1db00e..1cefc11e591b70e8e034a559a493bc9d7b5fc3c6 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -13,12 +13,16 @@ import {
   TouchableWithoutFeedback,
   ViewStyle,
   useWindowDimensions,
+  BackHandler,
 } from 'react-native';
+import Reanimated, { FadeIn, FadeOut } from 'react-native-reanimated';
 
 import createStyleSheet from '../../styles/createStyleSheet';
 import useHeaderStyle from '../../styles/useHeaderStyle';
 import useUIKitTheme from '../../theme/useUIKitTheme';
 
+const AnimatedPressable = Reanimated.createAnimatedComponent(Pressable);
+
 type ModalAnimationType = 'slide' | 'slide-no-gesture' | 'fade';
 type Props = {
   type?: ModalAnimationType;
@@ -53,7 +57,13 @@ const Modal = ({
   const { topInset } = useHeaderStyle();
 
   const [modalVisible, setModalVisible] = useState(false);
-  const showAction = () => setModalVisible(true);
+  const showAction = () => {
+    if (Platform.OS === 'android') {
+      showTransition(() => setModalVisible(true))
+    } else {
+      setModalVisible(true)
+    }
+  };
   const hideAction = () => hideTransition(() => setModalVisible(false));
 
   const { width, height } = useWindowDimensions();
@@ -65,6 +75,70 @@ const Modal = ({
 
   useOnDismiss(modalVisible, onDismiss);
 
+  const handleClose = () => {
+    onClose();
+    onDismiss?.();
+  }
+
+  useEffect(() => {
+    if (!visible) {
+      return;
+    }
+
+    const hardwareBackPress = () => {
+      handleClose();
+      return true;
+    }
+
+    BackHandler.addEventListener('hardwareBackPress', hardwareBackPress);
+    return () => {
+      BackHandler.removeEventListener('hardwareBackPress', hardwareBackPress);
+    };
+  }, []);
+
+  if (Platform.OS === 'android') {
+    if (visible) {
+      return (
+        <AnimatedPressable
+          style={[StyleSheet.absoluteFill, {
+            backgroundColor: palette.onBackgroundLight03,
+          }]}
+          onPress={() => {
+            if (!disableBackgroundClose) {
+              handleClose();
+            }
+          }}
+          entering={FadeIn}
+          exiting={FadeOut}>
+          <KeyboardAvoidingView
+            // NOTE: This is trick for Android.
+            //  When orientation is changed on Android, the offset that to avoid soft-keyboard is not updated normally.
+            key={Platform.OS === 'android' && enableKeyboardAvoid ? `${width}-${height}` : undefined}
+            enabled={enableKeyboardAvoid}
+            style={styles.background}
+            behavior={Platform.select({ ios: 'padding', default: 'height' })}
+            pointerEvents={'box-none'}
+            keyboardVerticalOffset={enableKeyboardAvoid && statusBarTranslucent ? -topInset : 0}
+          >
+            <Animated.View  
+              style={[
+                styles.background,
+                backgroundStyle,
+                { opacity: content.opacity, transform: [{ translateY: content.translateY }] },
+              ]}
+              pointerEvents={'box-none'}
+              {...panResponder.panHandlers}
+            >
+              {children}
+            </Animated.View>  
+          </KeyboardAvoidingView>
+        </AnimatedPressable>
+      )
+    } 
+    
+    return null
+  }
+
   return (
     <RNModal
       statusBarTranslucent={statusBarTranslucent}