Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Refactor search history (#8260)

authored by

Eric Bailey and committed by
GitHub
0a7734f9 8a602bf9

+73 -107
+1 -1
src/screens/Search/Shell.tsx
··· 112 112 const newAccountHistory = [ 113 113 item.did, 114 114 ...accountHistory.filter(p => p !== item.did), 115 - ].slice(0, 5) 115 + ].slice(0, 10) 116 116 setAccountHistory(newAccountHistory) 117 117 }, 118 118 [accountHistory, setAccountHistory],
+72 -106
src/screens/Search/components/SearchHistory.tsx
··· 1 - import {Pressable, ScrollView, StyleSheet, View} from 'react-native' 1 + import {Pressable, ScrollView, View} from 'react-native' 2 2 import {moderateProfile, type ModerationOpts} from '@atproto/api' 3 3 import {msg, Trans} from '@lingui/macro' 4 4 import {useLingui} from '@lingui/react' ··· 8 8 import {sanitizeDisplayName} from '#/lib/strings/display-names' 9 9 import {sanitizeHandle} from '#/lib/strings/handles' 10 10 import {useModerationOpts} from '#/state/preferences/moderation-opts' 11 - import {Link} from '#/view/com/util/Link' 12 11 import {UserAvatar} from '#/view/com/util/UserAvatar' 13 12 import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture' 14 - import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf' 13 + import {atoms as a} from '#/alf' 15 14 import {Button, ButtonIcon} from '#/components/Button' 16 15 import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' 17 16 import * as Layout from '#/components/Layout' 17 + import {Link} from '#/components/Link' 18 18 import {Text} from '#/components/Typography' 19 19 import {useSimpleVerificationState} from '#/components/verification' 20 20 import {VerificationCheck} from '#/components/verification/VerificationCheck' ··· 35 35 onRemoveItemClick: (item: string) => void 36 36 onRemoveProfileClick: (profile: bsky.profile.AnyProfileView) => void 37 37 }) { 38 - const {gtMobile} = useBreakpoints() 39 38 const {_} = useLingui() 40 39 const moderationOpts = useModerationOpts() 41 40 ··· 43 42 <Layout.Content 44 43 keyboardDismissMode="interactive" 45 44 keyboardShouldPersistTaps="handled"> 46 - <View style={[a.w_full, a.px_md]}> 45 + <View style={[a.w_full, a.gap_md]}> 47 46 {(searchHistory.length > 0 || selectedProfiles.length > 0) && ( 48 - <Text style={[a.text_md, a.font_bold, a.p_md]}> 49 - <Trans>Recent Searches</Trans> 50 - </Text> 47 + <View style={[a.px_lg, a.pt_sm]}> 48 + <Text style={[a.text_md, a.font_bold]}> 49 + <Trans>Recent Searches</Trans> 50 + </Text> 51 + </View> 51 52 )} 53 + 52 54 {selectedProfiles.length > 0 && ( 53 - <View 54 - style={[ 55 - styles.selectedProfilesContainer, 56 - !gtMobile && styles.selectedProfilesContainerMobile, 57 - ]}> 55 + <View> 58 56 <BlockDrawerGesture> 59 57 <ScrollView 60 58 horizontal 61 59 keyboardShouldPersistTaps="handled" 62 60 showsHorizontalScrollIndicator={false} 63 - style={[ 61 + contentContainerStyle={[ 62 + a.px_lg, 64 63 a.flex_row, 65 64 a.flex_nowrap, 66 - {marginHorizontal: tokens.space._2xl * -1}, 67 - ]} 68 - contentContainerStyle={[a.px_2xl, a.border_0]}> 65 + a.gap_xl, 66 + ]}> 69 67 {moderationOpts && 70 - selectedProfiles 71 - .slice(0, 5) 72 - .map(profile => ( 73 - <RecentProfileItem 74 - key={profile.did} 75 - profile={profile} 76 - moderationOpts={moderationOpts} 77 - onPress={() => onProfileClick(profile)} 78 - onRemove={() => onRemoveProfileClick(profile)} 79 - /> 80 - ))} 68 + selectedProfiles.map(profile => ( 69 + <RecentProfileItem 70 + key={profile.did} 71 + profile={profile} 72 + moderationOpts={moderationOpts} 73 + onPress={() => onProfileClick(profile)} 74 + onRemove={() => onRemoveProfileClick(profile)} 75 + /> 76 + ))} 81 77 </ScrollView> 82 78 </BlockDrawerGesture> 83 79 </View> 84 80 )} 81 + 85 82 {searchHistory.length > 0 && ( 86 - <View style={[a.pl_md, a.pr_xs, a.mt_md]}> 83 + <View style={[a.px_lg, a.pt_sm]}> 87 84 {searchHistory.slice(0, 5).map((historyItem, index) => ( 88 - <View key={index} style={[a.flex_row, a.align_center, a.mt_xs]}> 85 + <View key={index} style={[a.flex_row, a.align_center]}> 89 86 <Pressable 90 87 accessibilityRole="button" 91 88 onPress={() => onItemClick(historyItem)} 92 89 hitSlop={HITSLOP_10} 93 - style={[a.flex_1, a.py_md]}> 90 + style={[a.flex_1, a.py_sm]}> 94 91 <Text style={[a.text_md]}>{historyItem}</Text> 95 92 </Pressable> 96 93 <Button ··· 123 120 onRemove: () => void 124 121 }) { 125 122 const {_} = useLingui() 126 - const {gtMobile} = useBreakpoints() 127 - const t = useTheme() 123 + const width = 80 128 124 129 125 const moderation = moderateProfile(profile, moderationOpts) 130 126 const name = sanitizeDisplayName( ··· 134 130 const verification = useSimpleVerificationState({profile}) 135 131 136 132 return ( 137 - <View style={[styles.profileItem, !gtMobile && styles.profileItemMobile]}> 133 + <View style={[a.relative]}> 138 134 <Link 139 - href={makeProfileLink(profile)} 140 - title={profile.handle} 141 - asAnchor 142 - anchorNoUnderline 143 - onBeforePress={onPress} 144 - style={[a.align_center, a.w_full]}> 135 + to={makeProfileLink(profile)} 136 + label={profile.handle} 137 + onPress={onPress} 138 + style={[ 139 + a.flex_col, 140 + a.align_center, 141 + a.gap_xs, 142 + { 143 + width, 144 + }, 145 + ]}> 145 146 <UserAvatar 146 147 avatar={profile.avatar} 147 148 type={profile.associated?.labeler ? 'labeler' : 'user'} 148 - size={60} 149 + size={width - 8} 149 150 moderation={moderation.ui('avatar')} 150 151 /> 151 - <View style={styles.profileName}> 152 - <View 153 - style={[ 154 - a.flex_row, 155 - a.align_center, 156 - a.justify_center, 157 - web([a.flex_1]), 158 - ]}> 159 - <Text 160 - emoji 161 - style={[a.text_xs, a.leading_snug, a.self_start]} 162 - numberOfLines={1}> 163 - {name} 164 - </Text> 165 - {verification.showBadge && ( 166 - <View style={[a.pl_xs]}> 167 - <VerificationCheck 168 - width={12} 169 - verifier={verification.role === 'verifier'} 170 - /> 171 - </View> 172 - )} 173 - </View> 152 + <View style={[a.flex_row, a.align_center, a.justify_center, a.w_full]}> 153 + <Text emoji style={[a.text_xs, a.leading_snug]} numberOfLines={1}> 154 + {name} 155 + </Text> 156 + {verification.showBadge && ( 157 + <View style={[a.pl_2xs]}> 158 + <VerificationCheck 159 + width={10} 160 + verifier={verification.role === 'verifier'} 161 + /> 162 + </View> 163 + )} 174 164 </View> 175 165 </Link> 176 - <Pressable 177 - accessibilityRole="button" 178 - accessibilityLabel={_(msg`Remove profile`)} 179 - accessibilityHint={_(msg`Removes profile from search history`)} 166 + <Button 167 + label={_(msg`Remove profile`)} 180 168 hitSlop={createHitslop(6)} 181 - style={styles.profileRemoveBtn} 182 - onPress={onRemove}> 183 - <XIcon size="xs" style={t.atoms.text_contrast_low} /> 184 - </Pressable> 169 + size="tiny" 170 + variant="outline" 171 + color="secondary" 172 + shape="round" 173 + onPress={onRemove} 174 + style={[ 175 + a.absolute, 176 + { 177 + top: 0, 178 + right: 0, 179 + height: 18, 180 + width: 18, 181 + }, 182 + ]}> 183 + <ButtonIcon icon={XIcon} /> 184 + </Button> 185 185 </View> 186 186 ) 187 187 } 188 - 189 - const styles = StyleSheet.create({ 190 - selectedProfilesContainer: { 191 - marginTop: 10, 192 - paddingHorizontal: 12, 193 - height: 80, 194 - }, 195 - selectedProfilesContainerMobile: { 196 - height: 100, 197 - }, 198 - profileItem: { 199 - alignItems: 'center', 200 - marginRight: 15, 201 - width: 78, 202 - }, 203 - profileItemMobile: { 204 - width: 70, 205 - }, 206 - profileName: { 207 - width: 78, 208 - marginTop: 6, 209 - }, 210 - profileRemoveBtn: { 211 - position: 'absolute', 212 - top: 0, 213 - right: 5, 214 - backgroundColor: 'white', 215 - borderRadius: 10, 216 - width: 18, 217 - height: 18, 218 - alignItems: 'center', 219 - justifyContent: 'center', 220 - }, 221 - })