Bluesky app fork with some witchin' additions 馃挮
at main 3.3 kB view raw
1import {createContext, useContext, useMemo} from 'react' 2import {type GestureResponderEvent, type Insets, type View} from 'react-native' 3 4import {useHaptics} from '#/lib/haptics' 5import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 6import {atoms as a, useTheme} from '#/alf' 7import {Button, type ButtonProps} from '#/components/Button' 8import {type Props as SVGIconProps} from '#/components/icons/common' 9import {Text, type TextProps} from '#/components/Typography' 10 11export const DEFAULT_HITSLOP = {top: 5, bottom: 10, left: 10, right: 10} 12 13const PostControlContext = createContext<{ 14 big?: boolean 15 active?: boolean 16 color?: {color: string} 17}>({}) 18PostControlContext.displayName = 'PostControlContext' 19 20// Base button style, which the the other ones extend 21export function PostControlButton({ 22 ref, 23 onPress, 24 onLongPress, 25 children, 26 big, 27 active, 28 activeColor, 29 ...props 30}: Omit<ButtonProps, 'hitSlop'> & { 31 ref?: React.Ref<View> 32 active?: boolean 33 big?: boolean 34 color?: string 35 activeColor?: string 36 hitSlop?: Insets 37}) { 38 const t = useTheme() 39 const playHaptic = useHaptics() 40 41 const enableSquareButtons = useEnableSquareButtons() 42 43 const ctx = useMemo( 44 () => ({ 45 big, 46 active, 47 color: { 48 color: activeColor && active ? activeColor : t.palette.contrast_500, 49 }, 50 }), 51 [big, active, activeColor, t.palette.contrast_500], 52 ) 53 54 const style = useMemo( 55 () => [ 56 a.flex_row, 57 a.align_center, 58 a.gap_xs, 59 a.bg_transparent, 60 {padding: 5}, 61 ], 62 [], 63 ) 64 65 const handlePress = useMemo(() => { 66 if (!onPress) return 67 return (evt: GestureResponderEvent) => { 68 playHaptic('Light') 69 onPress(evt) 70 } 71 }, [onPress, playHaptic]) 72 73 const handleLongPress = useMemo(() => { 74 if (!onLongPress) return 75 return (evt: GestureResponderEvent) => { 76 playHaptic('Heavy') 77 onLongPress(evt) 78 } 79 }, [onLongPress, playHaptic]) 80 81 return ( 82 <Button 83 ref={ref} 84 onPress={handlePress} 85 onLongPress={handleLongPress} 86 style={style} 87 hoverStyle={t.atoms.bg_contrast_25} 88 shape={enableSquareButtons ? 'square' : 'round'} 89 variant="ghost" 90 color="secondary" 91 {...props} 92 hitSlop={{ 93 ...DEFAULT_HITSLOP, 94 ...(props.hitSlop || {}), 95 }}> 96 {typeof children === 'function' ? ( 97 args => ( 98 <PostControlContext.Provider value={ctx}> 99 {children(args)} 100 </PostControlContext.Provider> 101 ) 102 ) : ( 103 <PostControlContext.Provider value={ctx}> 104 {children} 105 </PostControlContext.Provider> 106 )} 107 </Button> 108 ) 109} 110 111export function PostControlButtonIcon({ 112 icon: Comp, 113 style, 114 ...rest 115}: SVGIconProps & { 116 icon: React.ComponentType<SVGIconProps> 117}) { 118 const {big, color} = useContext(PostControlContext) 119 120 return ( 121 <Comp 122 style={[color, a.pointer_events_none, style]} 123 {...rest} 124 width={big ? 22 : 18} 125 /> 126 ) 127} 128 129export function PostControlButtonText({style, ...props}: TextProps) { 130 const {big, active, color} = useContext(PostControlContext) 131 132 return ( 133 <Text 134 style={[ 135 color, 136 big ? a.text_md : a.text_sm, 137 active && a.font_semi_bold, 138 style, 139 ]} 140 {...props} 141 /> 142 ) 143}