forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {StyleSheet} from 'react-native'
2import Animated from 'react-native-reanimated'
3import {useSafeAreaInsets} from 'react-native-safe-area-context'
4import {useMediaQuery} from 'react-responsive'
5
6import {HITSLOP_20} from '#/lib/constants'
7import {PressableScale} from '#/lib/custom-animations/PressableScale'
8import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform'
9import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
10import {clamp} from '#/lib/numbers'
11import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons'
12import {useSession} from '#/state/session'
13import {atoms as a, useLayoutBreakpoints, useTheme, web} from '#/alf'
14import {useInteractionState} from '#/components/hooks/useInteractionState'
15import {ArrowTop_Stroke2_Corner0_Rounded as ArrowIcon} from '#/components/icons/Arrow'
16import {CENTER_COLUMN_OFFSET} from '#/components/Layout'
17import {SubtleHover} from '#/components/SubtleHover'
18
19export function LoadLatestBtn({
20 onPress,
21 label,
22 showIndicator,
23}: {
24 onPress: () => void
25 label: string
26 showIndicator: boolean
27}) {
28 const {hasSession} = useSession()
29 const {isDesktop, isTablet, isMobile, isTabletOrMobile} = useWebMediaQueries()
30 const {centerColumnOffset} = useLayoutBreakpoints()
31 const fabMinimalShellTransform = useMinimalShellFabTransform()
32 const insets = useSafeAreaInsets()
33 const t = useTheme()
34 const enableSquareButtons = useEnableSquareButtons()
35 const {
36 state: hovered,
37 onIn: onHoverIn,
38 onOut: onHoverOut,
39 } = useInteractionState()
40
41 // move button inline if it starts overlapping the left nav
42 const isTallViewport = useMediaQuery({minHeight: 700})
43
44 // Adjust height of the fab if we have a session only on mobile web. If we don't have a session, we want to adjust
45 // it on both tablet and mobile since we are showing the bottom bar (see createNativeStackNavigatorWithAuth)
46 const showBottomBar = hasSession ? isMobile : isTabletOrMobile
47
48 const bottomPosition = isTablet
49 ? {bottom: 50}
50 : {bottom: clamp(insets.bottom, 15, 60) + 15}
51
52 return (
53 <Animated.View
54 testID="loadLatestBtn"
55 style={[
56 a.fixed,
57 a.z_20,
58 {left: 18},
59 isDesktop &&
60 (isTallViewport
61 ? styles.loadLatestOutOfLine
62 : styles.loadLatestInline),
63 isTablet &&
64 (centerColumnOffset
65 ? styles.loadLatestInlineOffset
66 : styles.loadLatestInline),
67 bottomPosition,
68 showBottomBar && fabMinimalShellTransform,
69 ]}>
70 <PressableScale
71 style={[
72 {
73 width: 42,
74 height: 42,
75 },
76 enableSquareButtons ? a.rounded_sm : a.rounded_full,
77 a.align_center,
78 a.justify_center,
79 a.border,
80 t.atoms.border_contrast_low,
81 showIndicator ? {backgroundColor: t.palette.primary_50} : t.atoms.bg,
82 ]}
83 onPress={onPress}
84 hitSlop={HITSLOP_20}
85 accessibilityLabel={label}
86 accessibilityHint=""
87 targetScale={0.9}
88 onPointerEnter={onHoverIn}
89 onPointerLeave={onHoverOut}>
90 <SubtleHover
91 hover={hovered}
92 style={[enableSquareButtons ? a.rounded_sm : a.rounded_full]}
93 />
94 <ArrowIcon
95 size="md"
96 style={[
97 a.z_10,
98 showIndicator
99 ? {color: t.palette.primary_500}
100 : t.atoms.text_contrast_medium,
101 ]}
102 />
103 </PressableScale>
104 </Animated.View>
105 )
106}
107
108const styles = StyleSheet.create({
109 loadLatestInline: {
110 left: web('calc(50vw - 282px)'),
111 },
112 loadLatestInlineOffset: {
113 left: web(`calc(50vw - 282px + ${CENTER_COLUMN_OFFSET}px)`),
114 },
115 loadLatestOutOfLine: {
116 left: web('calc(50vw - 382px)'),
117 },
118})