import React from 'react' import {View} from 'react-native' import { type AppBskyGraphDefs, AppBskyGraphStarterpack, moderateProfile, } from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {sanitizeHandle} from '#/lib/strings/handles' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useSession} from '#/state/session' import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' import {ButtonText} from '#/components/Button' import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {Link} from '#/components/Link' import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {useStarterPackLink} from '#/components/StarterPack/StarterPackCard' import {SubtleHover} from '#/components/SubtleHover' import {Text} from '#/components/Typography' import * as bsky from '#/types/bsky' export function StarterPackCard({ view, }: { view: AppBskyGraphDefs.StarterPackView }) { const t = useTheme() const {_} = useLingui() const {currentAccount} = useSession() const {gtPhone} = useBreakpoints() const link = useStarterPackLink({view}) const record = view.record if ( !bsky.dangerousIsType( record, AppBskyGraphStarterpack.isRecord, ) ) { return null } const profileCount = gtPhone ? 11 : 8 const profiles = view.listItemsSample ?.slice(0, profileCount) .map(item => item.subject) return ( {s => ( <> {record.name} {view.creator?.did === currentAccount?.did ? _(msg`By you`) : _(msg`By ${sanitizeHandle(view.creator.handle, '@')}`)} Open pack )} ) } export function AvatarStack({ profiles, numPending, total, }: { profiles: bsky.profile.AnyProfileView[] numPending: number total?: number }) { const t = useTheme() const {gtPhone} = useBreakpoints() const moderationOpts = useModerationOpts() const computedTotal = (total ?? numPending) - numPending const circlesCount = numPending + 1 // add total at end const widthPerc = 100 / circlesCount const [size, setSize] = React.useState(null) const isPending = (numPending && profiles.length === 0) || !moderationOpts const items = isPending ? Array.from({length: numPending ?? circlesCount}).map((_, i) => ({ key: i, profile: null, moderation: null, })) : profiles.map(item => ({ key: item.did, profile: item, moderation: moderateProfile(item, moderationOpts), })) return ( {items.map((item, i) => ( setSize(e.nativeEvent.layout.width)} style={[ a.rounded_full, t.atoms.bg_contrast_25, { paddingTop: '100%', }, ]}> {size && item.profile ? ( ) : ( )} ))} {computedTotal > 0 ? ( +{computedTotal} ) : ( )} ) } export function StarterPackCardSkeleton() { const t = useTheme() const {gtPhone} = useBreakpoints() const profileCount = gtPhone ? 11 : 8 return ( ) }