Skip to content

Commit a228e86

Browse files
committed
fix(draggableActingId): better handling of actingId reset
1 parent b7fdf08 commit a228e86

File tree

4 files changed

+121
-102
lines changed

4 files changed

+121
-102
lines changed

.prettierrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"printWidth": 111,
3-
"plugins": ["prettier-plugin-organize-imports"]
3+
"plugins": ["prettier-plugin-organize-imports"],
4+
"organizeImportsSkipDestructiveCodeActions": true
45
}

example/src/App.tsx

Lines changed: 5 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,8 @@
1-
import {
2-
DndProvider,
3-
DndProviderProps,
4-
Draggable,
5-
DraggableProps,
6-
Droppable,
7-
DroppableProps,
8-
} from "@mgcrea/react-native-dnd";
9-
import React, { useState, type FunctionComponent } from "react";
10-
import { SafeAreaView, StyleSheet, Text } from "react-native";
11-
import { GestureHandlerRootView, State } from "react-native-gesture-handler";
12-
import { runOnJS, useSharedValue } from "react-native-reanimated";
1+
import React, { type FunctionComponent } from "react";
2+
import { BasicExample } from "./BasicExample";
3+
import { FlatListExample } from "./FlatListExample";
134

145
export const App: FunctionComponent = () => {
15-
const [count, setCount] = useState(0);
16-
// const data = useRef({ count: 0 });
17-
const dynamicData = useSharedValue({ count: 0 });
18-
19-
const onDragEnd = () => {
20-
setCount((count) => count + 1);
21-
// data.current = { ...data.current, count: data.current.count + 1 };
22-
};
23-
24-
const handleDragEnd: DndProviderProps["onDragEnd"] = ({ active, over }) => {
25-
"worklet";
26-
if (over) {
27-
console.log(`Current count is ${active.data.value.count}`);
28-
dynamicData.value = { ...dynamicData.value, count: dynamicData.value.count + 1 };
29-
runOnJS(onDragEnd)();
30-
}
31-
};
32-
33-
const handleBegin: DndProviderProps["onBegin"] = () => {
34-
"worklet";
35-
console.log("onBegin");
36-
};
37-
38-
const handleFinalize: DndProviderProps["onFinalize"] = ({ state }) => {
39-
"worklet";
40-
console.log("onFinalize");
41-
if (state !== State.FAILED) {
42-
//
43-
}
44-
};
45-
46-
const draggableStyle: DraggableProps["animatedStyleWorklet"] = (style, { isActive, isActing }) => {
47-
"worklet";
48-
return {
49-
opacity: isActing ? 0.5 : 1,
50-
backgroundColor: isActive ? "lightseagreen" : "seagreen",
51-
};
52-
};
53-
54-
const droppableStyle: DroppableProps["animatedStyleWorklet"] = (style, { isActive }) => {
55-
"worklet";
56-
return {
57-
backgroundColor: isActive ? "lightsteelblue" : "steelblue",
58-
};
59-
};
60-
61-
return (
62-
<SafeAreaView>
63-
<GestureHandlerRootView>
64-
<DndProvider onBegin={handleBegin} onFinalize={handleFinalize} onDragEnd={handleDragEnd}>
65-
<Droppable id="drop" style={styles.box} animatedStyleWorklet={droppableStyle} activeOpacity={1}>
66-
<Text>DROP</Text>
67-
</Droppable>
68-
<Draggable
69-
id="drag"
70-
data={dynamicData}
71-
style={styles.box}
72-
animatedStyleWorklet={draggableStyle}
73-
delay={0}
74-
tolerance={0}
75-
>
76-
<Text>DRAG</Text>
77-
</Draggable>
78-
{/* <DraggablePressable
79-
id="drag-pressable"
80-
data={dynamicData}
81-
style={styles.box}
82-
animatedStyleWorklet={draggableStyle}
83-
>
84-
<Text>Pressable</Text>
85-
</DraggablePressable> */}
86-
<Text testID="button">count is {count}</Text>
87-
</DndProvider>
88-
</GestureHandlerRootView>
89-
</SafeAreaView>
90-
);
6+
// return <BasicExample />;
7+
return <FlatListExample />;
918
};
92-
93-
const styles = StyleSheet.create({
94-
box: {
95-
margin: 24,
96-
padding: 24,
97-
height: 128,
98-
width: 128,
99-
justifyContent: "center",
100-
alignItems: "center",
101-
backgroundColor: "darkseagreen",
102-
},
103-
});

example/src/BasicExample.tsx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import {
2+
DndProvider,
3+
DndProviderProps,
4+
Draggable,
5+
DraggableProps,
6+
Droppable,
7+
DroppableProps,
8+
} from "@mgcrea/react-native-dnd";
9+
import React, { useState, type FunctionComponent } from "react";
10+
import { SafeAreaView, StyleSheet, Text, View } from "react-native";
11+
import { GestureHandlerRootView } from "react-native-gesture-handler";
12+
import { runOnJS, useSharedValue } from "react-native-reanimated";
13+
14+
export const BasicExample: FunctionComponent = () => {
15+
const [count, setCount] = useState(0);
16+
const dynamicData = useSharedValue({ count: 0 });
17+
18+
const onDragEnd = () => {
19+
setCount((count) => count + 1);
20+
// data.current = { ...data.current, count: data.current.count + 1 };
21+
};
22+
23+
const handleDragEnd: DndProviderProps["onDragEnd"] = ({ active, over }) => {
24+
"worklet";
25+
if (over) {
26+
console.log(`Current count is ${active.data.value.count}`);
27+
dynamicData.value = { ...dynamicData.value, count: dynamicData.value.count + 1 };
28+
runOnJS(onDragEnd)();
29+
}
30+
};
31+
32+
const handleBegin: DndProviderProps["onBegin"] = () => {
33+
"worklet";
34+
console.log("onBegin");
35+
};
36+
37+
const handleFinalize: DndProviderProps["onFinalize"] = () => {
38+
"worklet";
39+
console.log("onFinalize");
40+
};
41+
42+
const draggableStyle: DraggableProps["animatedStyleWorklet"] = (style, { isActive, isActing }) => {
43+
"worklet";
44+
return {
45+
opacity: isActing ? 0.5 : 1,
46+
backgroundColor: isActive ? "lightseagreen" : "seagreen",
47+
};
48+
};
49+
50+
const droppableStyle: DroppableProps["animatedStyleWorklet"] = (style, { isActive }) => {
51+
"worklet";
52+
return {
53+
backgroundColor: isActive ? "lightsteelblue" : "steelblue",
54+
};
55+
};
56+
57+
return (
58+
<SafeAreaView style={styles.container}>
59+
<GestureHandlerRootView>
60+
<DndProvider onBegin={handleBegin} onFinalize={handleFinalize} onDragEnd={handleDragEnd}>
61+
<View style={styles.view}>
62+
<Droppable id="drop" style={styles.box} animatedStyleWorklet={droppableStyle} activeOpacity={1}>
63+
<Text style={styles.text}>DROP</Text>
64+
</Droppable>
65+
<Draggable id="drag" data={dynamicData} style={styles.box} animatedStyleWorklet={draggableStyle}>
66+
<Text style={styles.text}>DRAG</Text>
67+
</Draggable>
68+
<Text testID="button">count is {count}</Text>
69+
</View>
70+
</DndProvider>
71+
</GestureHandlerRootView>
72+
</SafeAreaView>
73+
);
74+
};
75+
76+
const styles = StyleSheet.create({
77+
container: {
78+
alignItems: "center",
79+
justifyContent: "center",
80+
flex: 1,
81+
},
82+
view: {
83+
alignItems: "center",
84+
marginTop: -128,
85+
borderColor: "black",
86+
borderWidth: StyleSheet.hairlineWidth,
87+
borderRadius: 8,
88+
padding: 32,
89+
},
90+
box: {
91+
margin: 24,
92+
padding: 24,
93+
height: 96,
94+
width: 96,
95+
borderRadius: 8,
96+
justifyContent: "center",
97+
alignItems: "center",
98+
backgroundColor: "darkseagreen",
99+
},
100+
text: {
101+
color: "white",
102+
},
103+
});

src/DndProvider.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,16 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
287287
// Track current state for cancellation purposes
288288
draggableState.value = state; // can be `FAILED` or `ENDED`
289289
const { value: activeId } = draggableActiveId;
290+
const { value: actingId } = draggableActingId;
290291
const { value: layouts } = draggableLayouts;
291292
const { value: offsets } = draggableOffsets;
292293
// Ignore item-free interactions
293294
if (activeId === null) {
295+
// Check if we were currently waiting for activation delay
296+
if (actingId !== null) {
297+
runOnJS(clearActiveId)();
298+
draggableActingId.value = null;
299+
}
294300
return;
295301
}
296302
// Reset interaction-related shared state for styling purposes
@@ -325,7 +331,11 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
325331
],
326332
() => {
327333
// Cancel if we are interacting again with an item
328-
if (draggableState.value !== State.END && draggableActingId.value !== null) {
334+
if (
335+
draggableState.value !== State.END &&
336+
draggableState.value !== State.FAILED &&
337+
draggableActingId.value !== null
338+
) {
329339
return;
330340
}
331341
// Cancel if we are not the last interaction

0 commit comments

Comments
 (0)