Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 146 lines 3.5 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 a.user_select_none, 137 big ? a.text_md : a.text_sm, 138 active && a.font_semi_bold, 139 // prevent layout shift on android 140 {includeFontPadding: false, textAlignVertical: 'center'}, 141 style, 142 ]} 143 {...props} 144 /> 145 ) 146}