about summary refs log tree commit diff
path: root/src/components/PostControls/PostControlButton.tsx
blob: ae69b1322d5d1f1621098fbd37f0b17a31a152d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {createContext, useContext, useMemo} from 'react'
import {type GestureResponderEvent, type View} from 'react-native'

import {POST_CTRL_HITSLOP} from '#/lib/constants'
import {useHaptics} from '#/lib/haptics'
import {atoms as a, useTheme} from '#/alf'
import {Button, type ButtonProps} from '#/components/Button'
import {type Props as SVGIconProps} from '#/components/icons/common'
import {Text, type TextProps} from '#/components/Typography'

const PostControlContext = createContext<{
  big?: boolean
  active?: boolean
  color?: {color: string}
}>({})
PostControlContext.displayName = 'PostControlContext'

// Base button style, which the the other ones extend
export function PostControlButton({
  ref,
  onPress,
  onLongPress,
  children,
  big,
  active,
  activeColor,
  ...props
}: ButtonProps & {
  ref?: React.Ref<View>
  active?: boolean
  big?: boolean
  color?: string
  activeColor?: string
}) {
  const t = useTheme()
  const playHaptic = useHaptics()

  const ctx = useMemo(
    () => ({
      big,
      active,
      color: {
        color: activeColor && active ? activeColor : t.palette.contrast_500,
      },
    }),
    [big, active, activeColor, t.palette.contrast_500],
  )

  const style = useMemo(
    () => [
      a.flex_row,
      a.align_center,
      a.gap_xs,
      a.bg_transparent,
      {padding: 5},
    ],
    [],
  )

  const handlePress = useMemo(() => {
    if (!onPress) return
    return (evt: GestureResponderEvent) => {
      playHaptic('Light')
      onPress(evt)
    }
  }, [onPress, playHaptic])

  const handleLongPress = useMemo(() => {
    if (!onLongPress) return
    return (evt: GestureResponderEvent) => {
      playHaptic('Heavy')
      onLongPress(evt)
    }
  }, [onLongPress, playHaptic])

  return (
    <Button
      ref={ref}
      onPress={handlePress}
      onLongPress={handleLongPress}
      style={style}
      hoverStyle={t.atoms.bg_contrast_25}
      shape="round"
      variant="ghost"
      color="secondary"
      hitSlop={POST_CTRL_HITSLOP}
      {...props}>
      {typeof children === 'function' ? (
        args => (
          <PostControlContext.Provider value={ctx}>
            {children(args)}
          </PostControlContext.Provider>
        )
      ) : (
        <PostControlContext.Provider value={ctx}>
          {children}
        </PostControlContext.Provider>
      )}
    </Button>
  )
}

export function PostControlButtonIcon({
  icon: Comp,
}: {
  icon: React.ComponentType<SVGIconProps>
}) {
  const {big, color} = useContext(PostControlContext)

  return <Comp style={[color, a.pointer_events_none]} width={big ? 22 : 18} />
}

export function PostControlButtonText({style, ...props}: TextProps) {
  const {big, active, color} = useContext(PostControlContext)

  return (
    <Text
      style={[color, big ? a.text_md : a.text_sm, active && a.font_bold, style]}
      {...props}
    />
  )
}