Open suman379 opened 1 year ago
Hey, I've been trying to reproduce without success. Can you specify if it was android / ios? Which version and what device? I tested on Android emulator Pixel 7 Pro and iOS simulator with iPhone 14 Pro. It would help if you attached a recording please
The first tap on the apple closed the keyboard while it should have actually chosen the apple and close the modal https://github.com/TheWidlarzGroup/rn-emoji-keyboard/assets/14316935/9a90e16d-0555-474b-9989-c8da5cc19b27
this must be one of the oldest bugs in react native where keyboardShouldPersistTaps="handled"
does not work inside a Modal
and this package relies on it.
Only solution that works fine is this:
SingleEmoji.tsx
:
import React, { memo } from "react";
import { TouchableOpacity, View, Text } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
measure,
runOnJS,
runOnUI,
useAnimatedRef
} from "react-native-reanimated";
import { createStyleSheet, useStyles } from "react-native-unistyles";
import type { StyleProp, ViewStyle } from "react-native";
import type { EmojiSizes, JsonEmoji } from "../types";
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);
type Props = {
emojiSize: number;
index: number;
isSelected?: boolean;
item: JsonEmoji;
onLongPress: (emoji: JsonEmoji, emojiIndex: number, emojiSizes: EmojiSizes) => void;
onPress: (emoji: JsonEmoji) => void;
selectedEmojiStyle?: StyleProp<ViewStyle>;
};
export const SingleEmoji = memo(
(p: Props) => {
const animatedRef = useAnimatedRef();
const { styles } = useStyles(stylesheet);
const handlePress = () => p.onPress(p.item);
const handleLongPress = () => {
runOnUI(() => {
const layout = measure(animatedRef);
if (layout === null) {
return;
}
runOnJS(p.onLongPress)(p.item, p.index, {
width: layout.width,
height: layout.height
});
})();
};
const longGesture = Gesture.LongPress().onStart(() => {
runOnJS(handleLongPress)();
});
const gesture = Gesture.Tap().onEnd(() => {
runOnJS(handlePress)();
});
return (
<GestureHandlerRootView style={styles.flex}> <=== even though the whole app might be wrapped with this, Android will fail to recognize taps for some f reason if you don't wrap it
<GestureDetector gesture={gesture}>
<GestureDetector gesture={longGesture}>
<AnimatedTouchable
accessibilityRole="button"
activeOpacity={0.8}
// @ts-ignore
ref={animatedRef}
style={styles.button}
>
<View style={[styles.emojiWrapper, p.selectedEmojiStyle]}>
<Text style={[styles.emoji, { fontSize: p.emojiSize }]}>
{p.item.emoji}
</Text>
</View>
</AnimatedTouchable>
</GestureDetector>
</GestureDetector>
<GestureHandlerRootView>
);
},
(prevProps, nextProps) => prevProps.isSelected === nextProps.isSelected
);
SingleEmoji.displayName = "SingleEmoji";
const stylesheet = createStyleSheet((theme) => ({
button: {
alignItems: "center",
flex: 1,
justifyContent: "center",
padding: theme.spacing.mvs4
},
emojiWrapper: {
padding: theme.spacing.mvs4
},
emoji: { color: "#000" },
flex: {
flex: 1
}
}));
SingleSkinTone.tsx
:
import React, { Component } from "react";
import { Pressable, StyleSheet, View, Text} from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import { runOnJS } from "react-native-reanimated";
import type { JsonEmoji } from "../types";
export class SingleSkinTone extends Component<{
emojiSize: number;
item: JsonEmoji;
onLongPress: () => void;
onPress: () => void;
}> {
shouldComponentUpdate() {
return false;
}
render() {
const { item, emojiSize, onPress } = this.props;
const gesture = Gesture.Tap().onEnd(() => {
runOnJS(onPress)();
});
return (
<GestureHandlerRootView style={styles.flex}>
<GestureDetector gesture={gesture}>
<Pressable
accessibilityRole="button"
style={({ pressed }) => [styles.container, { opacity: pressed ? 0.7 : 1 }]}
>
<View style={styles.iconContainer}>
<Text style={[styles.emoji, { fontSize: emojiSize }]}>{item.emoji}</Text>
</View>
</Pressable>
</GestureDetector>
</GestureHandlerRootView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
padding: 0
},
emoji: {
color: "#000"
},
flex: {
flex:1
},
iconContainer: {
alignItems: "center",
justifyContent: "center"
}
});
Describe the bug Need to double tap on emoji to select the emoji when you search.
To Reproduce Steps to reproduce the behavior:
Expected behavior It should select the emoji on first tap even keyboard is selected.