Prevent swipe rows from opening items
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { ReactNode, useRef } from "react";
|
||||
import { Pressable, StyleSheet, Text, View } from "react-native";
|
||||
import { Pressable, type PressableProps, StyleSheet, Text, View } from "react-native";
|
||||
import Swipeable, {
|
||||
type SwipeableMethods,
|
||||
} from "react-native-gesture-handler/ReanimatedSwipeable";
|
||||
@@ -24,6 +24,9 @@ type SwipeableRowProps = {
|
||||
actions: SwipeAction[];
|
||||
enabled?: boolean;
|
||||
backgroundColor?: string;
|
||||
onPress?: () => void;
|
||||
onLongPress?: () => void;
|
||||
contentStyle?: PressableProps["style"];
|
||||
};
|
||||
|
||||
export function SwipeableRow({
|
||||
@@ -31,11 +34,63 @@ export function SwipeableRow({
|
||||
actions,
|
||||
enabled = true,
|
||||
backgroundColor,
|
||||
onPress,
|
||||
onLongPress,
|
||||
contentStyle,
|
||||
}: SwipeableRowProps) {
|
||||
const { colors } = useAppTheme();
|
||||
const styles = useThemedStyles(createSwipeableRowStyles);
|
||||
const rowBackground = backgroundColor ?? colors.background;
|
||||
const swipeRef = useRef<SwipeableMethods>(null);
|
||||
const rowOpenRef = useRef(false);
|
||||
const suppressPressUntilRef = useRef(0);
|
||||
|
||||
function suppressContentPress() {
|
||||
suppressPressUntilRef.current = Date.now() + 350;
|
||||
}
|
||||
|
||||
function handleContentPress() {
|
||||
if (!onPress) return;
|
||||
|
||||
if (rowOpenRef.current || Date.now() < suppressPressUntilRef.current) {
|
||||
swipeRef.current?.close();
|
||||
rowOpenRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
onPress();
|
||||
}
|
||||
|
||||
function renderContent() {
|
||||
if (!onPress && !onLongPress) {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.row,
|
||||
{ backgroundColor: rowBackground },
|
||||
typeof contentStyle === "function" ? undefined : contentStyle,
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={handleContentPress}
|
||||
onLongPress={onLongPress}
|
||||
style={(state) => [
|
||||
styles.row,
|
||||
{ backgroundColor: rowBackground },
|
||||
typeof contentStyle === "function" ? contentStyle(state) : contentStyle,
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
function renderRightActions() {
|
||||
return (
|
||||
@@ -45,7 +100,9 @@ export function SwipeableRow({
|
||||
key={action.key}
|
||||
style={[styles.actionButton, { backgroundColor: action.backgroundColor }]}
|
||||
onPress={() => {
|
||||
suppressContentPress();
|
||||
swipeRef.current?.close();
|
||||
rowOpenRef.current = false;
|
||||
action.onPress();
|
||||
}}
|
||||
>
|
||||
@@ -58,12 +115,26 @@ export function SwipeableRow({
|
||||
}
|
||||
|
||||
if (!enabled || actions.length === 0) {
|
||||
return <View style={[styles.row, { backgroundColor: rowBackground }]}>{children}</View>;
|
||||
return renderContent();
|
||||
}
|
||||
|
||||
return (
|
||||
<Swipeable ref={swipeRef} renderRightActions={renderRightActions} overshootRight={false}>
|
||||
<View style={[styles.row, { backgroundColor: rowBackground }]}>{children}</View>
|
||||
<Swipeable
|
||||
ref={swipeRef}
|
||||
renderRightActions={renderRightActions}
|
||||
overshootRight={false}
|
||||
onSwipeableOpenStartDrag={suppressContentPress}
|
||||
onSwipeableCloseStartDrag={suppressContentPress}
|
||||
onSwipeableWillOpen={() => {
|
||||
suppressContentPress();
|
||||
rowOpenRef.current = true;
|
||||
}}
|
||||
onSwipeableWillClose={suppressContentPress}
|
||||
onSwipeableClose={() => {
|
||||
rowOpenRef.current = false;
|
||||
}}
|
||||
>
|
||||
{renderContent()}
|
||||
</Swipeable>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user