Skip to content

Commit 4b0fce9

Browse files
committed
feat: enhance FloatingButton with draggable functionality and error handling for missing libraries
1 parent 1658da2 commit 4b0fce9

File tree

1 file changed

+65
-13
lines changed

1 file changed

+65
-13
lines changed

src/FloatingButton.tsx

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,44 @@ import {
55
TouchableOpacity,
66
Dimensions,
77
} from 'react-native';
8-
import React from 'react';
9-
import Animated, {
10-
useSharedValue,
11-
useAnimatedStyle,
12-
withSpring,
13-
} from 'react-native-reanimated';
14-
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
8+
import React, { useEffect } from 'react';
159
import Icon from './Icon';
16-
10+
import NonFloatingButton from './NonFloatingButton';
1711
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
1812

13+
let Animated: any = null;
14+
let Reanimated: any = null;
15+
let useSharedValue: any = null;
16+
let useAnimatedStyle: any = null;
17+
let withSpring: any = null;
18+
let Gesture: any = null;
19+
let GestureDetector: any = null;
20+
21+
let librariesAvailable = false;
22+
23+
try {
24+
Animated = require('react-native-reanimated').default;
25+
Reanimated = require('react-native-reanimated');
26+
useSharedValue = Reanimated.useSharedValue;
27+
useAnimatedStyle = Reanimated.useAnimatedStyle;
28+
withSpring = Reanimated.withSpring;
29+
30+
const gestureHandler = require('react-native-gesture-handler');
31+
Gesture = gestureHandler.Gesture;
32+
GestureDetector = gestureHandler.GestureDetector;
33+
34+
librariesAvailable = !!(
35+
Animated &&
36+
useSharedValue &&
37+
useAnimatedStyle &&
38+
withSpring &&
39+
Gesture &&
40+
GestureDetector
41+
);
42+
} catch (error) {
43+
librariesAvailable = false;
44+
}
45+
1946
const BUTTON_SIZE = 58;
2047
const CLOSE_BUTTON_SIZE = 58;
2148
const PADDING = 20;
@@ -24,21 +51,20 @@ interface FloatingButtonProps {
2451
openModal: () => void;
2552
hideIcon: () => void;
2653
logsLength: number;
54+
draggable?: boolean;
2755
enableDeviceShake?: boolean;
2856
}
2957

30-
const FloatingButton: React.FunctionComponent<FloatingButtonProps> = ({
58+
const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
3159
hideIcon,
32-
logsLength,
3360
openModal,
61+
logsLength,
3462
enableDeviceShake,
3563
}) => {
3664
const positionX = useSharedValue(screenWidth - BUTTON_SIZE - PADDING);
3765
const positionY = useSharedValue(screenHeight - 150);
38-
3966
const startPositionX = useSharedValue(0);
4067
const startPositionY = useSharedValue(0);
41-
4268
const isDragging = useSharedValue(false);
4369

4470
const panGesture = Gesture.Pan()
@@ -47,7 +73,7 @@ const FloatingButton: React.FunctionComponent<FloatingButtonProps> = ({
4773
startPositionX.value = positionX.value;
4874
startPositionY.value = positionY.value;
4975
})
50-
.onUpdate((event) => {
76+
.onUpdate((event: { translationX: any; translationY: any }) => {
5177
const newX = startPositionX.value + event.translationX;
5278
const newY = startPositionY.value + event.translationY;
5379

@@ -111,6 +137,24 @@ const FloatingButton: React.FunctionComponent<FloatingButtonProps> = ({
111137
);
112138
};
113139

140+
const FloatingButton: React.FC<FloatingButtonProps> = (props) => {
141+
const { draggable } = props;
142+
143+
useEffect(() => {
144+
if (draggable && !librariesAvailable) {
145+
throw new Error(
146+
`Missing Libraries: Required libraries "react-native-reanimated" and "react-native-gesture-handler" are not installed. Please install them to enable this feature.\n\nRun:\n\nnpm install react-native-reanimated react-native-gesture-handler\n\nand rebuild your app.`
147+
);
148+
}
149+
}, [draggable]);
150+
151+
if (!librariesAvailable || !draggable) {
152+
return <NonFloatingButton {...props} />;
153+
}
154+
155+
return <AnimatedFloatingButton {...props} />;
156+
};
157+
114158
const styles = StyleSheet.create({
115159
gestureRoot: {
116160
flex: 1,
@@ -134,6 +178,10 @@ const styles = StyleSheet.create({
134178
position: 'absolute',
135179
zIndex: 1000,
136180
},
181+
staticPosition: {
182+
left: screenWidth - BUTTON_SIZE - PADDING,
183+
top: screenHeight - 150,
184+
},
137185
buttonTouchable: {
138186
backgroundColor: '#007AFF',
139187
padding: 16,
@@ -149,6 +197,10 @@ const styles = StyleSheet.create({
149197
position: 'absolute',
150198
zIndex: 1001,
151199
},
200+
staticClosePosition: {
201+
left: screenWidth - BUTTON_SIZE - PADDING + 4,
202+
top: screenHeight - 150 - 50,
203+
},
152204
closeButton: {
153205
padding: 16,
154206
borderRadius: 70,

0 commit comments

Comments
 (0)