forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useState} from 'react'
2import {View} from 'react-native'
3import {PrivacySensitive} from 'expo-privacy-sensitive'
4
5import {useAppState} from '#/lib/appState'
6import {atoms as a, useTheme} from '#/alf'
7import {sizes as iconSizes} from '#/components/icons/common'
8import {Mark as Logo} from '#/components/icons/Logo'
9import {IS_IOS} from '#/env'
10
11const ICON_SIZE = 'xl' as const
12
13export function GrowthHack({
14 children,
15 align = 'right',
16}: {
17 children: React.ReactNode
18 align?: 'left' | 'right'
19}) {
20 const t = useTheme()
21
22 // the button has a variable width and is absolutely positioned, so we need to manually
23 // set the minimum width of the underlying button
24 const [width, setWidth] = useState<number | undefined>(undefined)
25
26 const appState = useAppState()
27
28 if (!IS_IOS || appState !== 'active') return children
29
30 return (
31 <View
32 style={[
33 a.relative,
34 a.justify_center,
35 align === 'right' ? a.align_end : a.align_start,
36 {minWidth: width ?? iconSizes[ICON_SIZE]},
37 ]}>
38 <PrivacySensitive
39 style={[
40 a.absolute,
41 a.z_10,
42 a.flex_col,
43 align === 'right'
44 ? [a.right_0, a.align_end]
45 : [a.left_0, a.align_start],
46 // when finding the size of the button, we need the containing
47 // element to have a concrete size otherwise the text will
48 // collapse to 0 width. so set it to a really big number
49 // and just use `pointer-events: box-none` so it doesn't interfere with the UI
50 {width: 1000},
51 a.pointer_events_box_none,
52 ]}>
53 <View
54 onLayout={evt => setWidth(evt.nativeEvent.layout.width)}
55 style={[
56 t.atoms.bg,
57 // make sure it covers the icon! children might be undefined
58 {minWidth: iconSizes[ICON_SIZE], minHeight: iconSizes[ICON_SIZE]},
59 ]}>
60 {children}
61 </View>
62 </PrivacySensitive>
63 <Logo size={ICON_SIZE} />
64 </View>
65 )
66}