mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {ComponentProps} from 'react'
2import {StyleSheet, TouchableWithoutFeedback} from 'react-native'
3import Animated from 'react-native-reanimated'
4import {useSafeAreaInsets} from 'react-native-safe-area-context'
5import {LinearGradient} from 'expo-linear-gradient'
6
7import {PressableScale} from '#/lib/custom-animations/PressableScale'
8import {useHaptics} from '#/lib/haptics'
9import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform'
10import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
11import {clamp} from '#/lib/numbers'
12import {gradients} from '#/lib/styles'
13import {isWeb} from '#/platform/detection'
14import {ios} from '#/alf'
15
16export interface FABProps
17 extends ComponentProps<typeof TouchableWithoutFeedback> {
18 testID?: string
19 icon: JSX.Element
20}
21
22export function FABInner({testID, icon, onPress, ...props}: FABProps) {
23 const insets = useSafeAreaInsets()
24 const {isMobile, isTablet} = useWebMediaQueries()
25 const playHaptic = useHaptics()
26 const fabMinimalShellTransform = useMinimalShellFabTransform()
27
28 const size = isTablet ? styles.sizeLarge : styles.sizeRegular
29
30 const tabletSpacing = isTablet
31 ? {right: 50, bottom: 50}
32 : {right: 24, bottom: clamp(insets.bottom, 15, 60) + 15}
33
34 return (
35 <Animated.View
36 style={[
37 styles.outer,
38 size,
39 tabletSpacing,
40 isMobile && fabMinimalShellTransform,
41 ]}>
42 <PressableScale
43 testID={testID}
44 onPressIn={ios(() => playHaptic('Light'))}
45 onPress={evt => {
46 onPress?.(evt)
47 playHaptic('Light')
48 }}
49 onLongPress={ios((evt: any) => {
50 onPress?.(evt)
51 playHaptic('Heavy')
52 })}
53 targetScale={0.9}
54 {...props}>
55 <LinearGradient
56 colors={[gradients.blueLight.start, gradients.blueLight.end]}
57 start={{x: 0, y: 0}}
58 end={{x: 1, y: 1}}
59 style={[styles.inner, size]}>
60 {icon}
61 </LinearGradient>
62 </PressableScale>
63 </Animated.View>
64 )
65}
66
67const styles = StyleSheet.create({
68 sizeRegular: {
69 width: 60,
70 height: 60,
71 borderRadius: 30,
72 },
73 sizeLarge: {
74 width: 70,
75 height: 70,
76 borderRadius: 35,
77 },
78 outer: {
79 // @ts-ignore web-only
80 position: isWeb ? 'fixed' : 'absolute',
81 zIndex: 1,
82 cursor: 'pointer',
83 },
84 inner: {
85 justifyContent: 'center',
86 alignItems: 'center',
87 },
88})