Bluesky app fork with some witchin' additions 💫

Clicking "see more" on user suggestions opens suggested users modal (#9482)

* Clicking "see more" on user suggestions now opens modal

* More conventional pattern

* Remove unneeded optional

---------

Co-authored-by: Eric Bailey <git@esb.lol>

authored by Alex Benzer Eric Bailey and committed by GitHub d3878bf0 fb3f67b1

Changed files
+70 -30
src
components
+40 -19
src/components/FeedInterstitials.tsx
··· 26 web, 27 } from '#/alf' 28 import {Button, ButtonIcon, ButtonText} from '#/components/Button' 29 import * as FeedCard from '#/components/FeedCard' 30 import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRight} from '#/components/icons/Arrow' 31 import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag' 32 - import {InlineLinkText, Link} from '#/components/Link' 33 import * as ProfileCard from '#/components/ProfileCard' 34 import {Text} from '#/components/Typography' 35 import type * as bsky from '#/types/bsky' 36 import {ProgressGuideList} from './ProgressGuide/List' 37 38 const MOBILE_CARD_WIDTH = 165 ··· 250 const {_} = useLingui() 251 const moderationOpts = useModerationOpts() 252 const {gtMobile} = useBreakpoints() 253 254 const isLoading = isSuggestionsLoading || !moderationOpts 255 const isProfileHeaderContext = viewContext === 'profileHeader' ··· 388 )} 389 </Text> 390 {!isProfileHeaderContext && ( 391 - <InlineLinkText 392 - label={_(msg`See more suggested profiles on the Explore page`)} 393 - to="/search" 394 onPress={() => { 395 - logger.metric('suggestedUser:seeMore', { 396 logContext: isFeedContext ? 'Explore' : 'Profile', 397 }) 398 }}> 399 - <Trans>See more</Trans> 400 - </InlineLinkText> 401 )} 402 </View> 403 404 {gtMobile ? ( 405 <View style={[a.p_lg, a.pt_md]}> 406 <View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}> ··· 417 decelerationRate="fast"> 418 {content} 419 420 - {!isProfileHeaderContext && <SeeMoreSuggestedProfilesCard />} 421 </ScrollView> 422 </BlockDrawerGesture> 423 )} ··· 425 ) 426 } 427 428 - function SeeMoreSuggestedProfilesCard() { 429 const t = useTheme() 430 const {_} = useLingui() 431 432 return ( 433 - <Link 434 - to="/search" 435 - color="primary" 436 - label={_(msg`Browse more accounts on the Explore page`)} 437 - onPress={() => { 438 - logger.metric('suggestedUser:seeMore', { 439 - logContext: 'Explore', 440 - }) 441 - }} 442 style={[ 443 a.flex_col, 444 a.align_center, ··· 454 style={[a.text_md, a.font_medium, a.leading_snug, a.text_center]}> 455 <Trans>See more</Trans> 456 </ButtonText> 457 - </Link> 458 ) 459 } 460
··· 26 web, 27 } from '#/alf' 28 import {Button, ButtonIcon, ButtonText} from '#/components/Button' 29 + import {useDialogControl} from '#/components/Dialog' 30 import * as FeedCard from '#/components/FeedCard' 31 import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRight} from '#/components/icons/Arrow' 32 import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag' 33 + import {InlineLinkText} from '#/components/Link' 34 import * as ProfileCard from '#/components/ProfileCard' 35 import {Text} from '#/components/Typography' 36 import type * as bsky from '#/types/bsky' 37 + import {FollowDialogWithoutGuide} from './ProgressGuide/FollowDialog' 38 import {ProgressGuideList} from './ProgressGuide/List' 39 40 const MOBILE_CARD_WIDTH = 165 ··· 252 const {_} = useLingui() 253 const moderationOpts = useModerationOpts() 254 const {gtMobile} = useBreakpoints() 255 + const followDialogControl = useDialogControl() 256 257 const isLoading = isSuggestionsLoading || !moderationOpts 258 const isProfileHeaderContext = viewContext === 'profileHeader' ··· 391 )} 392 </Text> 393 {!isProfileHeaderContext && ( 394 + <Button 395 + label={_(msg`See more suggested profiles`)} 396 onPress={() => { 397 + followDialogControl.open() 398 + logEvent('suggestedUser:seeMore', { 399 logContext: isFeedContext ? 'Explore' : 'Profile', 400 }) 401 }}> 402 + {({hovered}) => ( 403 + <Text 404 + style={[ 405 + a.text_sm, 406 + {color: t.palette.primary_500}, 407 + hovered && 408 + web({ 409 + textDecorationLine: 'underline', 410 + textDecorationColor: t.palette.primary_500, 411 + }), 412 + ]}> 413 + <Trans>See more</Trans> 414 + </Text> 415 + )} 416 + </Button> 417 )} 418 </View> 419 420 + <FollowDialogWithoutGuide control={followDialogControl} /> 421 + 422 {gtMobile ? ( 423 <View style={[a.p_lg, a.pt_md]}> 424 <View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}> ··· 435 decelerationRate="fast"> 436 {content} 437 438 + {!isProfileHeaderContext && ( 439 + <SeeMoreSuggestedProfilesCard 440 + onPress={() => { 441 + followDialogControl.open() 442 + logger.metric('suggestedUser:seeMore', { 443 + logContext: 'Explore', 444 + }) 445 + }} 446 + /> 447 + )} 448 </ScrollView> 449 </BlockDrawerGesture> 450 )} ··· 452 ) 453 } 454 455 + function SeeMoreSuggestedProfilesCard({onPress}: {onPress: () => void}) { 456 const t = useTheme() 457 const {_} = useLingui() 458 459 return ( 460 + <Button 461 + label={_(msg`Browse more accounts`)} 462 + onPress={onPress} 463 style={[ 464 a.flex_col, 465 a.align_center, ··· 475 style={[a.text_md, a.font_medium, a.leading_snug, a.text_center]}> 476 <Trans>See more</Trans> 477 </ButtonText> 478 + </Button> 479 ) 480 } 481
+30 -11
src/components/ProgressGuide/FollowDialog.tsx
··· 84 ) 85 } 86 87 // Fine to keep this top-level. 88 let lastSelectedInterest = '' 89 let lastSearchText = '' 90 91 - function DialogInner({guide}: {guide: Follow10ProgressGuide}) { 92 const {_} = useLingui() 93 const interestsDisplayNames = useInterestsDisplayNames() 94 const {data: preferences} = usePreferencesQuery() ··· 289 selectedInterest, 290 interestsDisplayNames, 291 }: { 292 - guide: Follow10ProgressGuide 293 inputRef: React.RefObject<TextInput | null> 294 listRef: React.RefObject<ListMethods | null> 295 onSelectTab: (v: string) => void ··· 340 } 341 Header = memo(Header) 342 343 - function HeaderTop({guide}: {guide: Follow10ProgressGuide}) { 344 const {_} = useLingui() 345 const t = useTheme() 346 const control = Dialog.useDialogContext() ··· 363 ]}> 364 <Trans>Find people to follow</Trans> 365 </Text> 366 - <View style={isWeb && {paddingRight: 36}}> 367 - <ProgressGuideTask 368 - current={guide.numFollows + 1} 369 - total={10 + 1} 370 - title={`${guide.numFollows} / 10`} 371 - tabularNumsTitle 372 - /> 373 - </View> 374 {isWeb ? ( 375 <Button 376 label={_(msg`Close`)}
··· 84 ) 85 } 86 87 + /** 88 + * Same as {@link FollowDialog} but without a progress guide. 89 + */ 90 + export function FollowDialogWithoutGuide({ 91 + control, 92 + }: { 93 + control: Dialog.DialogOuterProps['control'] 94 + }) { 95 + const {height: minHeight} = useWindowDimensions() 96 + return ( 97 + <Dialog.Outer control={control} nativeOptions={{minHeight}}> 98 + <Dialog.Handle /> 99 + <DialogInner /> 100 + </Dialog.Outer> 101 + ) 102 + } 103 + 104 // Fine to keep this top-level. 105 let lastSelectedInterest = '' 106 let lastSearchText = '' 107 108 + function DialogInner({guide}: {guide?: Follow10ProgressGuide}) { 109 const {_} = useLingui() 110 const interestsDisplayNames = useInterestsDisplayNames() 111 const {data: preferences} = usePreferencesQuery() ··· 306 selectedInterest, 307 interestsDisplayNames, 308 }: { 309 + guide?: Follow10ProgressGuide 310 inputRef: React.RefObject<TextInput | null> 311 listRef: React.RefObject<ListMethods | null> 312 onSelectTab: (v: string) => void ··· 357 } 358 Header = memo(Header) 359 360 + function HeaderTop({guide}: {guide?: Follow10ProgressGuide}) { 361 const {_} = useLingui() 362 const t = useTheme() 363 const control = Dialog.useDialogContext() ··· 380 ]}> 381 <Trans>Find people to follow</Trans> 382 </Text> 383 + {guide && ( 384 + <View style={isWeb && {paddingRight: 36}}> 385 + <ProgressGuideTask 386 + current={guide.numFollows + 1} 387 + total={10 + 1} 388 + title={`${guide.numFollows} / 10`} 389 + tabularNumsTitle 390 + /> 391 + </View> 392 + )} 393 {isWeb ? ( 394 <Button 395 label={_(msg`Close`)}