Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

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

at 63fbf577d994ae0fd0e0ea9be75dfdfff7b0ddfb 166 lines 3.9 kB view raw
1import {useMemo} from 'react' 2import {View} from 'react-native' 3import {type AppBskyFeedDefs, AtUri} from '@atproto/api' 4 5import {PressableScale} from '#/lib/custom-animations/PressableScale' 6import {makeCustomFeedLink} from '#/lib/routes/links' 7import {UserAvatar} from '#/view/com/util/UserAvatar' 8import {atoms as a, native, useTheme, type ViewStyleProp} from '#/alf' 9import {Button, ButtonIcon} from '#/components/Button' 10import * as FeedCard from '#/components/FeedCard' 11import {sizes as iconSizes} from '#/components/icons/common' 12import {MagnifyingGlass_Stroke2_Corner0_Rounded as SearchIcon} from '#/components/icons/MagnifyingGlass' 13import {Link} from '#/components/Link' 14import {Text, type TextProps} from '#/components/Typography' 15import {useAnalytics} from '#/analytics' 16 17export function Container({ 18 style, 19 children, 20 bottomBorder, 21}: { 22 children: React.ReactNode 23 bottomBorder?: boolean 24} & ViewStyleProp) { 25 const t = useTheme() 26 return ( 27 <View 28 style={[ 29 a.flex_row, 30 a.align_center, 31 a.px_lg, 32 a.pt_2xl, 33 a.pb_md, 34 a.gap_sm, 35 t.atoms.bg, 36 bottomBorder && [a.border_b, t.atoms.border_contrast_low], 37 style, 38 ]}> 39 {children} 40 </View> 41 ) 42} 43 44export function FeedLink({ 45 feed, 46 children, 47}: { 48 feed: AppBskyFeedDefs.GeneratorView 49 children?: React.ReactNode 50}) { 51 const t = useTheme() 52 const {host: did, rkey} = useMemo(() => new AtUri(feed.uri), [feed.uri]) 53 return ( 54 <Link 55 to={makeCustomFeedLink(did, rkey)} 56 label={feed.displayName} 57 style={[a.flex_1]}> 58 {({focused, hovered, pressed}) => ( 59 <View 60 style={[ 61 a.flex_1, 62 a.flex_row, 63 a.align_center, 64 {gap: 10}, 65 a.rounded_md, 66 a.p_xs, 67 {marginLeft: -6}, 68 (focused || hovered || pressed) && t.atoms.bg_contrast_25, 69 ]}> 70 {children} 71 </View> 72 )} 73 </Link> 74 ) 75} 76 77export function FeedAvatar({feed}: {feed: AppBskyFeedDefs.GeneratorView}) { 78 return <UserAvatar type="algo" size={38} avatar={feed.avatar} /> 79} 80 81export function Icon({ 82 icon: Comp, 83 size = 'lg', 84}: Pick<React.ComponentProps<typeof ButtonIcon>, 'icon' | 'size'>) { 85 const iconSize = iconSizes[size] 86 87 return ( 88 <View style={[a.z_20, {width: iconSize, height: iconSize, marginLeft: -2}]}> 89 <Comp width={iconSize} /> 90 </View> 91 ) 92} 93 94export function TitleText({style, ...props}: TextProps) { 95 return ( 96 <Text 97 style={[a.font_semi_bold, a.flex_1, a.text_xl, style]} 98 emoji 99 {...props} 100 /> 101 ) 102} 103 104export function SubtitleText({style, ...props}: TextProps) { 105 const t = useTheme() 106 return ( 107 <Text 108 style={[ 109 t.atoms.text_contrast_medium, 110 a.leading_tight, 111 a.flex_1, 112 a.text_sm, 113 style, 114 ]} 115 {...props} 116 /> 117 ) 118} 119 120export function SearchButton({ 121 label, 122 metricsTag, 123 onPress, 124}: { 125 label: string 126 metricsTag: 'suggestedAccounts' | 'suggestedFeeds' 127 onPress?: () => void 128}) { 129 const ax = useAnalytics() 130 return ( 131 <Button 132 label={label} 133 size="small" 134 variant="ghost" 135 color="secondary" 136 shape="round" 137 PressableComponent={native(PressableScale)} 138 onPress={() => { 139 ax.metric('explore:module:searchButtonPress', {module: metricsTag}) 140 onPress?.() 141 }} 142 style={[ 143 { 144 right: -4, 145 }, 146 ]}> 147 <ButtonIcon icon={SearchIcon} size="lg" /> 148 </Button> 149 ) 150} 151 152export function PinButton({feed}: {feed: AppBskyFeedDefs.GeneratorView}) { 153 return ( 154 <View style={[a.z_20, {marginRight: -6}]}> 155 <FeedCard.SaveButton 156 pin 157 view={feed} 158 size="large" 159 color="secondary" 160 variant="ghost" 161 shape="square" 162 text={false} 163 /> 164 </View> 165 ) 166}