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