Bluesky app fork with some witchin' additions 💫

Merge branch 'main' of https://github.com/bluesky-social/social-app

+1080 -926
assets/images/onboarding/value_prop_1_dark.webp

This is a binary file and will not be displayed.

assets/images/onboarding/value_prop_1_dark_borderless.webp

This is a binary file and will not be displayed.

assets/images/onboarding/value_prop_1_dim.webp

This is a binary file and will not be displayed.

assets/images/onboarding/value_prop_1_dim_borderless.webp

This is a binary file and will not be displayed.

assets/images/onboarding/value_prop_1_light.webp

This is a binary file and will not be displayed.

assets/images/onboarding/value_prop_1_light_borderless.webp

This is a binary file and will not be displayed.

+2 -2
bskyembed/src/components/embed.tsx
··· 330 {content.external.thumb && ( 331 <img 332 src={content.external.thumb} 333 - className="aspect-[1.91/1] object-cover" 334 /> 335 )} 336 <div className="py-3 px-4"> ··· 435 <Link 436 href={starterPackHref} 437 className="w-full rounded-xl overflow-hidden border dark:border-slate-600 flex flex-col items-stretch"> 438 - <img src={imageUri} className="aspect-[1.91/1] object-cover" /> 439 <div className="py-3 px-4"> 440 <div className="flex space-x-2 items-center"> 441 <img src={starterPackIcon} className="w-10 h-10" />
··· 330 {content.external.thumb && ( 331 <img 332 src={content.external.thumb} 333 + className="aspect-[1200/630] object-cover" 334 /> 335 )} 336 <div className="py-3 px-4"> ··· 435 <Link 436 href={starterPackHref} 437 className="w-full rounded-xl overflow-hidden border dark:border-slate-600 flex flex-col items-stretch"> 438 + <img src={imageUri} className="aspect-[1200/630] object-cover" /> 439 <div className="py-3 px-4"> 440 <div className="flex space-x-2 items-center"> 441 <img src={starterPackIcon} className="w-10 h-10" />
+3 -2
package.json
··· 74 "@atproto/api": "^0.17.0", 75 "@bitdrift/react-native": "^0.6.8", 76 "@braintree/sanitize-url": "^6.0.2", 77 - "@bsky.app/alf": "^0.1.2", 78 "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", 79 "@emoji-mart/react": "^1.1.1", 80 "@expo/html-elements": "^0.12.5", ··· 145 "expo-image-manipulator": "~14.0.7", 146 "expo-image-picker": "~17.0.8", 147 "expo-intent-launcher": "~13.0.7", 148 "expo-linear-gradient": "~15.0.7", 149 "expo-linking": "~8.0.8", 150 "expo-localization": "~17.0.7", ··· 192 "react-native-gesture-handler": "~2.28.0", 193 "react-native-get-random-values": "~1.11.0", 194 "react-native-keyboard-controller": "1.18.5", 195 - "@bsky.app/react-native-mmkv": "2.12.5", 196 "react-native-pager-view": "6.8.0", 197 "react-native-progress": "bluesky-social/react-native-progress", 198 "react-native-qrcode-styled": "^0.3.3",
··· 74 "@atproto/api": "^0.17.0", 75 "@bitdrift/react-native": "^0.6.8", 76 "@braintree/sanitize-url": "^6.0.2", 77 + "@bsky.app/alf": "^0.1.5", 78 + "@bsky.app/react-native-mmkv": "2.12.5", 79 "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", 80 "@emoji-mart/react": "^1.1.1", 81 "@expo/html-elements": "^0.12.5", ··· 146 "expo-image-manipulator": "~14.0.7", 147 "expo-image-picker": "~17.0.8", 148 "expo-intent-launcher": "~13.0.7", 149 + "expo-keep-awake": "^15.0.7", 150 "expo-linear-gradient": "~15.0.7", 151 "expo-linking": "~8.0.8", 152 "expo-localization": "~17.0.7", ··· 194 "react-native-gesture-handler": "~2.28.0", 195 "react-native-get-random-values": "~1.11.0", 196 "react-native-keyboard-controller": "1.18.5", 197 "react-native-pager-view": "6.8.0", 198 "react-native-progress": "bluesky-social/react-native-progress", 199 "react-native-qrcode-styled": "^0.3.3",
+12 -1
src/alf/atoms.ts
··· 1 import {type StyleProp, type ViewStyle} from 'react-native' 2 import {atoms as baseAtoms} from '@bsky.app/alf' 3 4 import {native, platform, web} from '#/alf/util/platform' 5 import * as Layout from '#/components/Layout' 6 ··· 31 backgroundColor: 'transparent', 32 }, 33 34 /* 35 * Transition 36 */ ··· 67 }), 68 69 /* 70 - * Animaations 71 */ 72 fade_in: web({ 73 animation: 'fadeIn ease-out 0.15s',
··· 1 import {type StyleProp, type ViewStyle} from 'react-native' 2 import {atoms as baseAtoms} from '@bsky.app/alf' 3 4 + import {CARD_ASPECT_RATIO} from '#/lib/constants' 5 import {native, platform, web} from '#/alf/util/platform' 6 import * as Layout from '#/components/Layout' 7 ··· 32 backgroundColor: 'transparent', 33 }, 34 35 + /** 36 + * Aspect ratios 37 + */ 38 + aspect_square: { 39 + aspectRatio: 1, 40 + }, 41 + aspect_card: { 42 + aspectRatio: CARD_ASPECT_RATIO, 43 + }, 44 + 45 /* 46 * Transition 47 */ ··· 78 }), 79 80 /* 81 + * Animations 82 */ 83 fade_in: web({ 84 animation: 'fadeIn ease-out 0.15s',
+1 -1
src/components/AccountList.tsx
··· 172 </View> 173 174 {isCurrentAccount ? ( 175 - <Check size="sm" style={[{color: t.palette.positive_600}]} /> 176 ) : ( 177 <Chevron size="sm" style={[t.atoms.text]} /> 178 )}
··· 172 </View> 173 174 {isCurrentAccount ? ( 175 + <Check size="sm" style={[{color: t.palette.positive_500}]} /> 176 ) : ( 177 <Chevron size="sm" style={[t.atoms.text]} /> 178 )}
+1 -1
src/components/Admonition.tsx
··· 87 style?: StyleProp<ViewStyle> 88 }) { 89 return ( 90 - <View style={[a.flex_1, a.flex_row, a.align_start, a.gap_sm, style]}> 91 {children} 92 </View> 93 )
··· 87 style?: StyleProp<ViewStyle> 88 }) { 89 return ( 90 + <View style={[a.w_full, a.flex_row, a.align_start, a.gap_sm, style]}> 91 {children} 92 </View> 93 )
+1 -1
src/components/Dialog/shared.tsx
··· 62 style?: StyleProp<TextStyle> 63 }) { 64 return ( 65 - <Text style={[a.text_lg, a.text_center, a.font_bold, style]}> 66 {children} 67 </Text> 68 )
··· 62 style?: StyleProp<TextStyle> 63 }) { 64 return ( 65 + <Text style={[a.text_lg, a.text_center, a.font_semi_bold, style]}> 66 {children} 67 </Text> 68 )
+2 -2
src/components/InterestTabs.tsx
··· 258 t.atoms.border_contrast_low, 259 t.atoms.bg, 260 a.h_full, 261 - {aspectRatio: 1}, 262 a.rounded_full, 263 ]}> 264 <ButtonIcon icon={ArrowLeft} /> ··· 292 t.atoms.border_contrast_low, 293 t.atoms.bg, 294 a.h_full, 295 - {aspectRatio: 1}, 296 a.rounded_full, 297 ]}> 298 <ButtonIcon icon={ArrowRight} />
··· 258 t.atoms.border_contrast_low, 259 t.atoms.bg, 260 a.h_full, 261 + a.aspect_square, 262 a.rounded_full, 263 ]}> 264 <ButtonIcon icon={ArrowLeft} /> ··· 292 t.atoms.border_contrast_low, 293 t.atoms.bg, 294 a.h_full, 295 + a.aspect_square, 296 a.rounded_full, 297 ]}> 298 <ButtonIcon icon={ArrowRight} />
+28
src/components/KeepAwake.tsx
···
··· 1 + import {useId} from 'react' 2 + import {useKeepAwake} from 'expo-keep-awake' 3 + import {useIsFocused} from '@react-navigation/native' 4 + 5 + /** 6 + * Stops the screen from sleeping. Only applies to the current screen. 7 + * 8 + * Note: Expo keeps the screen permanently awake when in dev mode, so 9 + * you'll only see this do anything when in production. 10 + * 11 + * @platform ios, android 12 + */ 13 + export function KeepAwake({enabled = true}) { 14 + const isFocused = useIsFocused() 15 + if (enabled && isFocused) { 16 + return <KeepAwakeInner /> 17 + } else { 18 + return null 19 + } 20 + } 21 + 22 + function KeepAwakeInner() { 23 + const id = useId() 24 + // if you don't pass an explicit ID, any `useKeepAwake` hook unmounting disables them all. 25 + // very strange behaviour, but easily fixed by passing a unique ID -sfn 26 + useKeepAwake(id) 27 + return null 28 + }
+3
src/components/KeepAwake.web.tsx
···
··· 1 + export function KeepAwake() { 2 + return null 3 + }
-82
src/components/LoggedOutCTA.tsx
··· 1 - import {View, type ViewStyle} from 'react-native' 2 - import {msg, Trans} from '@lingui/macro' 3 - import {useLingui} from '@lingui/react' 4 - 5 - import {type Gate} from '#/lib/statsig/gates' 6 - import {useGate} from '#/lib/statsig/statsig' 7 - import {isWeb} from '#/platform/detection' 8 - import {useSession} from '#/state/session' 9 - import {useLoggedOutViewControls} from '#/state/shell/logged-out' 10 - import {Logo} from '#/view/icons/Logo' 11 - import {atoms as a, useTheme} from '#/alf' 12 - import {Button, ButtonText} from '#/components/Button' 13 - import {Text} from '#/components/Typography' 14 - 15 - interface LoggedOutCTAProps { 16 - style?: ViewStyle 17 - gateName: Gate 18 - } 19 - 20 - export function LoggedOutCTA({style, gateName}: LoggedOutCTAProps) { 21 - const {hasSession} = useSession() 22 - const {requestSwitchToAccount} = useLoggedOutViewControls() 23 - const gate = useGate() 24 - const t = useTheme() 25 - const {_} = useLingui() 26 - 27 - // Only show for logged-out users on web 28 - if (hasSession || !isWeb) { 29 - return null 30 - } 31 - 32 - // Check gate at the last possible moment to avoid counting users as exposed when they won't see the element 33 - if (!gate(gateName)) { 34 - return null 35 - } 36 - 37 - return ( 38 - <View style={[a.pb_md, style]}> 39 - <View 40 - style={[ 41 - a.flex_row, 42 - a.align_center, 43 - a.justify_between, 44 - a.px_lg, 45 - a.py_md, 46 - a.rounded_md, 47 - a.mb_xs, 48 - t.atoms.bg_contrast_25, 49 - ]}> 50 - <View style={[a.flex_row, a.align_center, a.flex_1, a.pr_md]}> 51 - <Logo width={30} style={[a.mr_md]} /> 52 - <View style={[a.flex_1]}> 53 - <Text style={[a.text_lg, a.font_semi_bold, a.leading_snug]}> 54 - <Trans>Join Bluesky</Trans> 55 - </Text> 56 - <Text 57 - style={[ 58 - a.text_md, 59 - a.font_medium, 60 - a.leading_snug, 61 - t.atoms.text_contrast_medium, 62 - ]}> 63 - <Trans>The open social network.</Trans> 64 - </Text> 65 - </View> 66 - </View> 67 - <Button 68 - onPress={() => { 69 - requestSwitchToAccount({requestedAccount: 'new'}) 70 - }} 71 - label={_(msg`Create account`)} 72 - size="small" 73 - variant="solid" 74 - color="primary"> 75 - <ButtonText> 76 - <Trans>Create account</Trans> 77 - </ButtonText> 78 - </Button> 79 - </View> 80 - </View> 81 - ) 82 - }
···
+3 -2
src/components/MediaPreview.tsx
··· 96 }) { 97 const t = useTheme() 98 return ( 99 - <View style={[a.relative, a.flex_1, {aspectRatio: 1, maxWidth: 100}]}> 100 <Image 101 key={thumbnail} 102 source={{uri: thumbnail}} ··· 140 style={[ 141 {backgroundColor: 'black'}, 142 a.flex_1, 143 - {aspectRatio: 1, maxWidth: 100}, 144 a.justify_center, 145 a.align_center, 146 ]}>
··· 96 }) { 97 const t = useTheme() 98 return ( 99 + <View style={[a.relative, a.flex_1, a.aspect_square, {maxWidth: 100}]}> 100 <Image 101 key={thumbnail} 102 source={{uri: thumbnail}} ··· 140 style={[ 141 {backgroundColor: 'black'}, 142 a.flex_1, 143 + a.aspect_square, 144 + {maxWidth: 100}, 145 a.justify_center, 146 a.align_center, 147 ]}>
+1 -3
src/components/Post/Embed/ExternalEmbed/index.tsx
··· 97 ]}> 98 {imageUri && !embedPlayerParams ? ( 99 <Image 100 - style={{ 101 - aspectRatio: 1.91, 102 - }} 103 source={{uri: imageUri}} 104 accessibilityIgnoresInvertColors 105 />
··· 97 ]}> 98 {imageUri && !embedPlayerParams ? ( 99 <Image 100 + style={[a.aspect_card]} 101 source={{uri: imageUri}} 102 accessibilityIgnoresInvertColors 103 />
+1 -1
src/components/Post/Embed/FeedEmbed.tsx
··· 17 return ( 18 <FeedCard.Link 19 view={embed.view} 20 - style={[a.border, t.atoms.border_contrast_medium, a.p_md, a.rounded_sm]}> 21 <FeedCard.Outer> 22 <FeedCard.Header> 23 <FeedCard.Avatar src={embed.view.avatar} />
··· 17 return ( 18 <FeedCard.Link 19 view={embed.view} 20 + style={[a.border, t.atoms.border_contrast_low, a.p_md, a.rounded_sm]}> 21 <FeedCard.Outer> 22 <FeedCard.Header> 23 <FeedCard.Avatar src={embed.view.avatar} />
+1 -1
src/components/Post/Embed/ListEmbed.tsx
··· 17 return ( 18 <ListCard.Default 19 view={embed.view} 20 - style={[a.border, t.atoms.border_contrast_medium, a.p_md, a.rounded_sm]} 21 /> 22 ) 23 }
··· 17 return ( 18 <ListCard.Default 19 view={embed.view} 20 + style={[a.border, t.atoms.border_contrast_low, a.p_md, a.rounded_sm]} 21 /> 22 ) 23 }
+2 -2
src/components/Post/Embed/index.tsx
··· 26 import {PostAlerts} from '#/components/moderation/PostAlerts' 27 import {RichText} from '#/components/RichText' 28 import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard' 29 - import {SubtleWebHover} from '#/components/SubtleWebHover' 30 import * as bsky from '#/types/bsky' 31 import { 32 type Embed as TEmbed, ··· 370 childContainerStyle={[a.pt_sm]}> 371 {({active}) => ( 372 <> 373 - {!active && <SubtleWebHover hover={hover} style={[a.rounded_md]} />} 374 <Link 375 style={[!active && a.p_md]} 376 hoverStyle={{borderColor: pal.colors.borderLinkHover}}
··· 26 import {PostAlerts} from '#/components/moderation/PostAlerts' 27 import {RichText} from '#/components/RichText' 28 import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard' 29 + import {SubtleHover} from '#/components/SubtleHover' 30 import * as bsky from '#/types/bsky' 31 import { 32 type Embed as TEmbed, ··· 370 childContainerStyle={[a.pt_sm]}> 371 {({active}) => ( 372 <> 373 + {!active && <SubtleHover hover={hover} style={[a.rounded_md]} />} 374 <Link 375 style={[!active && a.p_md]} 376 hoverStyle={{borderColor: pal.colors.borderLinkHover}}
+4 -9
src/components/PostControls/DiscoverDebug.tsx
··· 5 import {DISCOVER_DEBUG_DIDS} from '#/lib/constants' 6 import {useGate} from '#/lib/statsig/statsig' 7 import {useSession} from '#/state/session' 8 - import * as Toast from '#/view/com/util/Toast' 9 - import {atoms as a, useBreakpoints, useTheme} from '#/alf' 10 import {Text} from '#/components/Typography' 11 import {IS_INTERNAL} from '#/env' 12 ··· 16 feedContext: string | undefined 17 }) { 18 const {currentAccount} = useSession() 19 - const {gtMobile} = useBreakpoints() 20 const gate = useGate() 21 const isDiscoverDebugUser = 22 IS_INTERNAL || ··· 30 <Pressable 31 accessible={false} 32 hitSlop={10} 33 - style={[ 34 - a.absolute, 35 - {zIndex: 1000, maxWidth: 65, bottom: -4}, 36 - gtMobile ? a.right_0 : a.left_0, 37 - ]} 38 onPress={e => { 39 e.stopPropagation() 40 Clipboard.setStringAsync(feedContext) 41 - Toast.show(t`Copied to clipboard`, 'clipboard-check') 42 }}> 43 <Text 44 numberOfLines={1}
··· 5 import {DISCOVER_DEBUG_DIDS} from '#/lib/constants' 6 import {useGate} from '#/lib/statsig/statsig' 7 import {useSession} from '#/state/session' 8 + import {atoms as a, useTheme} from '#/alf' 9 + import * as Toast from '#/components/Toast' 10 import {Text} from '#/components/Typography' 11 import {IS_INTERNAL} from '#/env' 12 ··· 16 feedContext: string | undefined 17 }) { 18 const {currentAccount} = useSession() 19 const gate = useGate() 20 const isDiscoverDebugUser = 21 IS_INTERNAL || ··· 29 <Pressable 30 accessible={false} 31 hitSlop={10} 32 + style={[a.absolute, {zIndex: 1000, maxWidth: 65, bottom: -4}, a.left_0]} 33 onPress={e => { 34 e.stopPropagation() 35 Clipboard.setStringAsync(feedContext) 36 + Toast.show(t`Copied to clipboard`) 37 }}> 38 <Text 39 numberOfLines={1}
+29 -4
src/components/PostControls/PostMenu/PostMenuItems.tsx
··· 54 } from '#/state/queries/profile' 55 import {resolvePdsServiceUrl} from '#/state/queries/resolve-identity' 56 import {useToggleReplyVisibilityMutation} from '#/state/queries/threadgate' 57 import {useRequireAuth, useSession} from '#/state/session' 58 import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' 59 import * as Toast from '#/view/com/util/Toast' ··· 347 : _(msg({message: 'Reply visibility updated', context: 'toast'})), 348 ) 349 } catch (e: any) { 350 - Toast.show( 351 - _(msg({message: 'Updating reply visibility failed', context: 'toast'})), 352 - ) 353 - logger.error(`Failed to ${action} reply`, {safeMessage: e.message}) 354 } 355 } 356
··· 54 } from '#/state/queries/profile' 55 import {resolvePdsServiceUrl} from '#/state/queries/resolve-identity' 56 import {useToggleReplyVisibilityMutation} from '#/state/queries/threadgate' 57 + import { 58 + InvalidInteractionSettingsError, 59 + MAX_HIDDEN_REPLIES, 60 + MaxHiddenRepliesError, 61 + } from '#/state/queries/threadgate' 62 import {useRequireAuth, useSession} from '#/state/session' 63 import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' 64 import * as Toast from '#/view/com/util/Toast' ··· 352 : _(msg({message: 'Reply visibility updated', context: 'toast'})), 353 ) 354 } catch (e: any) { 355 + if (e instanceof MaxHiddenRepliesError) { 356 + Toast.show( 357 + _( 358 + msg({ 359 + message: `You can hide a maximum of ${MAX_HIDDEN_REPLIES} replies.`, 360 + context: 'toast', 361 + }), 362 + ), 363 + ) 364 + } else if (e instanceof InvalidInteractionSettingsError) { 365 + Toast.show( 366 + _(msg({message: 'Invalid interaction settings.', context: 'toast'})), 367 + ) 368 + } else { 369 + Toast.show( 370 + _( 371 + msg({ 372 + message: 'Updating reply visibility failed', 373 + context: 'toast', 374 + }), 375 + ), 376 + ) 377 + logger.error(`Failed to ${action} reply`, {safeMessage: e.message}) 378 + } 379 } 380 } 381
+1 -1
src/components/PostControls/RepostButton.tsx
··· 57 <PostControlButton 58 testID="repostBtn" 59 active={isReposted} 60 - activeColor={t.palette.positive_600} 61 big={big} 62 onPress={onPress} 63 onLongPress={onLongPress}
··· 57 <PostControlButton 58 testID="repostBtn" 59 active={isReposted} 60 + activeColor={t.palette.positive_500} 61 big={big} 62 onPress={onPress} 63 onLongPress={onLongPress}
+2 -2
src/components/PostControls/RepostButton.web.tsx
··· 47 <PostControlButton 48 testID="repostBtn" 49 active={isReposted} 50 - activeColor={t.palette.positive_600} 51 label={props.accessibilityLabel} 52 big={big} 53 {...props}> ··· 100 <PostControlButton 101 onPress={() => requireAuth(() => {})} 102 active={isReposted} 103 - activeColor={t.palette.positive_600} 104 label={_(msg`Repost or quote post`)} 105 big={big}> 106 <PostControlButtonIcon icon={Repost} />
··· 47 <PostControlButton 48 testID="repostBtn" 49 active={isReposted} 50 + activeColor={t.palette.positive_500} 51 label={props.accessibilityLabel} 52 big={big} 53 {...props}> ··· 100 <PostControlButton 101 onPress={() => requireAuth(() => {})} 102 active={isReposted} 103 + activeColor={t.palette.positive_500} 104 label={_(msg`Repost or quote post`)} 105 big={big}> 106 <PostControlButtonIcon icon={Repost} />
+3 -1
src/components/PostControls/ShareMenu/ShareMenuItems.tsx
··· 176 {hideInPWI && ( 177 <Menu.Group> 178 <Menu.ContainerItem> 179 - <Admonition type="warning" style={[a.flex_1, a.border_0, a.p_0]}> 180 <Trans>This post is only visible to logged-in users.</Trans> 181 </Admonition> 182 </Menu.ContainerItem>
··· 176 {hideInPWI && ( 177 <Menu.Group> 178 <Menu.ContainerItem> 179 + <Admonition 180 + type="warning" 181 + style={[a.flex_1, a.border_0, a.p_0, a.bg_transparent]}> 182 <Trans>This post is only visible to logged-in users.</Trans> 183 </Admonition> 184 </Menu.ContainerItem>
+1 -1
src/components/PostControls/index.tsx
··· 218 a.flex_1, 219 a.align_start, 220 {marginLeft: big ? -2 : -6}, 221 - replyDisabled ? {opacity: 0.5} : undefined, 222 ]}> 223 <PostControlButton 224 testID="replyBtn"
··· 218 a.flex_1, 219 a.align_start, 220 {marginLeft: big ? -2 : -6}, 221 + replyDisabled ? {opacity: 0.6} : undefined, 222 ]}> 223 <PostControlButton 224 testID="replyBtn"
+3 -3
src/components/Skeleton.tsx
··· 32 <View 33 style={[ 34 a.rounded_md, 35 - t.atoms.bg_contrast_25, 36 { 37 height: lineHeight * 0.7, 38 opacity: blend ? 0.6 : 1, ··· 57 a.justify_center, 58 a.align_center, 59 a.rounded_full, 60 - t.atoms.bg_contrast_25, 61 { 62 width: size, 63 height: size, ··· 80 <View 81 style={[ 82 a.rounded_full, 83 - t.atoms.bg_contrast_25, 84 { 85 width: size * 1.618, 86 height: size,
··· 32 <View 33 style={[ 34 a.rounded_md, 35 + t.atoms.bg_contrast_50, 36 { 37 height: lineHeight * 0.7, 38 opacity: blend ? 0.6 : 1, ··· 57 a.justify_center, 58 a.align_center, 59 a.rounded_full, 60 + t.atoms.bg_contrast_50, 61 { 62 width: size, 63 height: size, ··· 80 <View 81 style={[ 82 a.rounded_full, 83 + t.atoms.bg_contrast_50, 84 { 85 width: size * 1.618, 86 height: size,
+1 -1
src/components/StarterPack/ShareDialog.tsx
··· 91 source={{uri: imageUrl}} 92 style={[ 93 a.rounded_sm, 94 { 95 - aspectRatio: 1200 / 630, 96 transform: [{scale: gtMobile ? 0.85 : 1}], 97 marginTop: gtMobile ? -20 : 0, 98 },
··· 91 source={{uri: imageUrl}} 92 style={[ 93 a.rounded_sm, 94 + a.aspect_card, 95 { 96 transform: [{scale: gtMobile ? 0.85 : 1}], 97 marginTop: gtMobile ? -20 : 0, 98 },
+1 -1
src/components/StarterPack/StarterPackCard.tsx
··· 191 <Link starterPack={starterPack}> 192 <Image 193 source={imageUri} 194 - style={[a.w_full, {aspectRatio: 1.91}]} 195 accessibilityIgnoresInvertColors={true} 196 /> 197 <View style={[a.px_sm, a.py_md]}>
··· 191 <Link starterPack={starterPack}> 192 <Image 193 source={imageUri} 194 + style={[a.w_full, a.aspect_card]} 195 accessibilityIgnoresInvertColors={true} 196 /> 197 <View style={[a.px_sm, a.py_md]}>
+27 -3
src/components/SubtleHover.tsx
··· 1 import {View} from 'react-native' 2 3 import {atoms as a, useTheme, type ViewStyleProp} from '#/alf' 4 5 - export function SubtleHover({style, hover}: ViewStyleProp & {hover: boolean}) { 6 const t = useTheme() 7 8 let opacity: number ··· 18 break 19 } 20 21 - return ( 22 <View 23 style={[ 24 a.absolute, 25 a.inset_0, 26 a.pointer_events_none, 27 a.transition_opacity, 28 - t.atoms.bg_contrast_25, 29 style, 30 {opacity: hover ? opacity : 0}, 31 ]} 32 /> 33 ) 34 }
··· 1 import {View} from 'react-native' 2 3 + import {isTouchDevice} from '#/lib/browser' 4 + import {isNative, isWeb} from '#/platform/detection' 5 import {atoms as a, useTheme, type ViewStyleProp} from '#/alf' 6 7 + export function SubtleHover({ 8 + style, 9 + hover, 10 + web = true, 11 + native = false, 12 + }: ViewStyleProp & {hover: boolean; web?: boolean; native?: boolean}) { 13 const t = useTheme() 14 15 let opacity: number ··· 25 break 26 } 27 28 + const el = ( 29 <View 30 style={[ 31 a.absolute, 32 a.inset_0, 33 a.pointer_events_none, 34 a.transition_opacity, 35 + t.atoms.bg_contrast_50, 36 style, 37 {opacity: hover ? opacity : 0}, 38 ]} 39 /> 40 ) 41 + 42 + if (hover) { 43 + console.log({ 44 + isWeb, 45 + web, 46 + isNative, 47 + native, 48 + }) 49 + } 50 + 51 + if (isWeb && web) { 52 + return isTouchDevice ? null : el 53 + } else if (isNative && native) { 54 + return el 55 + } 56 + 57 + return null 58 }
-5
src/components/SubtleWebHover.tsx
··· 1 - import {type ViewStyleProp} from '#/alf' 2 - 3 - export function SubtleWebHover({}: ViewStyleProp & {hover: boolean}) { 4 - return null 5 - }
···
-49
src/components/SubtleWebHover.web.tsx
··· 1 - import {StyleSheet, View} from 'react-native' 2 - 3 - import {isTouchDevice} from '#/lib/browser' 4 - import {useTheme, type ViewStyleProp} from '#/alf' 5 - 6 - export function SubtleWebHover({ 7 - style, 8 - hover, 9 - }: ViewStyleProp & {hover: boolean}) { 10 - const t = useTheme() 11 - if (isTouchDevice) { 12 - return null 13 - } 14 - let opacity = 0.5 15 - switch (t.name) { 16 - case 'dark': 17 - opacity = 0.4 18 - break 19 - case 'dim': 20 - opacity = 0.45 21 - break 22 - case 'light': 23 - opacity = 0.5 24 - break 25 - } 26 - return ( 27 - <View 28 - style={[ 29 - t.atoms.bg_contrast_25, 30 - styles.container, 31 - {opacity: hover ? opacity : 0}, 32 - style, 33 - ]} 34 - /> 35 - ) 36 - } 37 - 38 - const styles = StyleSheet.create({ 39 - container: { 40 - position: 'absolute', 41 - left: 0, 42 - right: 0, 43 - bottom: 0, 44 - top: 0, 45 - pointerEvents: 'none', 46 - // @ts-ignore web only 47 - transition: '0.15s ease-in-out opacity', 48 - }, 49 - })
···
+1 -1
src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx
··· 159 a.pt_lg, 160 a.pb_md, 161 ]}> 162 - <SuccessIcon size="sm" fill={t.palette.positive_600} /> 163 <Text style={[a.text_xl, a.font_bold]}> 164 <Trans>Success</Trans> 165 </Text>
··· 159 a.pt_lg, 160 a.pb_md, 161 ]}> 162 + <SuccessIcon size="sm" fill={t.palette.positive_500} /> 163 <Text style={[a.text_xl, a.font_bold]}> 164 <Trans>Success</Trans> 165 </Text>
+1 -1
src/components/dialogs/EmailDialog/screens/Update.tsx
··· 281 <Divider /> 282 <View style={[a.gap_sm]}> 283 <View style={[a.flex_row, a.gap_sm, a.align_center]}> 284 - <Check fill={t.palette.positive_600} size="xs" /> 285 <Text style={[a.text_md, a.font_bold]}> 286 <Trans>Success!</Trans> 287 </Text>
··· 281 <Divider /> 282 <View style={[a.gap_sm]}> 283 <View style={[a.flex_row, a.gap_sm, a.align_center]}> 284 + <Check fill={t.palette.positive_500} size="xs" /> 285 <Text style={[a.text_md, a.font_bold]}> 286 <Trans>Success!</Trans> 287 </Text>
+2 -2
src/components/dialogs/EmailDialog/screens/Verify.tsx
··· 176 <View style={[a.gap_sm]}> 177 <Text style={[a.text_xl, a.font_bold]}> 178 <Span style={{top: 1}}> 179 - <Check size="sm" fill={t.palette.positive_600} /> 180 </Span> 181 {' '} 182 <Trans>Email verification complete!</Trans> ··· 202 state.mutationStatus === 'success' ? ( 203 <> 204 <Span style={{top: 1}}> 205 - <Check size="sm" fill={t.palette.positive_600} /> 206 </Span> 207 {' '} 208 <Trans>Email sent!</Trans>
··· 176 <View style={[a.gap_sm]}> 177 <Text style={[a.text_xl, a.font_bold]}> 178 <Span style={{top: 1}}> 179 + <Check size="sm" fill={t.palette.positive_500} /> 180 </Span> 181 {' '} 182 <Trans>Email verification complete!</Trans> ··· 202 state.mutationStatus === 'success' ? ( 203 <> 204 <Span style={{top: 1}}> 205 + <Check size="sm" fill={t.palette.positive_500} /> 206 </Span> 207 {' '} 208 <Trans>Email sent!</Trans>
+2 -1
src/components/dialogs/GifSelect.tsx
··· 300 a.flex_1, 301 a.mb_sm, 302 a.rounded_sm, 303 - {aspectRatio: 1, opacity: pressed ? 0.8 : 1}, 304 t.atoms.bg_contrast_25, 305 ]} 306 source={{
··· 300 a.flex_1, 301 a.mb_sm, 302 a.rounded_sm, 303 + a.aspect_card, 304 + {opacity: pressed ? 0.8 : 1}, 305 t.atoms.bg_contrast_25, 306 ]} 307 source={{
+10 -2
src/components/dialogs/lists/CreateOrEditListDialog.tsx
··· 349 ? _(msg`Create user list`) 350 : _(msg`Create moderation list`) 351 352 return ( 353 <Dialog.ScrollableInner 354 label={title} ··· 389 defaultValue={displayName} 390 onChangeText={onChangeDisplayName} 391 label={_(msg`Name`)} 392 - placeholder={_(msg`e.g. Great Posters`)} 393 testID="editListNameInput" 394 /> 395 </TextField.Root> ··· 426 onChangeText={onChangeDescription} 427 multiline 428 label={_(msg`Description`)} 429 - placeholder={_(msg`e.g. The posters that never miss.`)} 430 testID="editProfileDescriptionInput" 431 /> 432 </TextField.Root>
··· 349 ? _(msg`Create user list`) 350 : _(msg`Create moderation list`) 351 352 + const displayNamePlaceholder = isCurateList 353 + ? _(msg`e.g. Great Posters`) 354 + : _(msg`e.g. Spammers`) 355 + 356 + const descriptionPlaceholder = isCurateList 357 + ? _(msg`e.g. The posters who never miss.`) 358 + : _(msg`e.g. Users that repeatedly reply with ads.`) 359 + 360 return ( 361 <Dialog.ScrollableInner 362 label={title} ··· 397 defaultValue={displayName} 398 onChangeText={onChangeDisplayName} 399 label={_(msg`Name`)} 400 + placeholder={displayNamePlaceholder} 401 testID="editListNameInput" 402 /> 403 </TextField.Root> ··· 434 onChangeText={onChangeDescription} 435 multiline 436 label={_(msg`Description`)} 437 + placeholder={descriptionPlaceholder} 438 testID="editProfileDescriptionInput" 439 /> 440 </TextField.Root>
+1 -1
src/components/live/LiveStatusDialog.tsx
··· 102 style={[ 103 t.atoms.bg_contrast_25, 104 a.w_full, 105 - {aspectRatio: 1.91}, 106 android([ 107 a.overflow_hidden, 108 {
··· 102 style={[ 103 t.atoms.bg_contrast_25, 104 a.w_full, 105 + a.aspect_card, 106 android([ 107 a.overflow_hidden, 108 {
+3
src/components/moderation/PostHider.tsx
··· 34 modui: ModerationUI 35 profile: AppBskyActorDefs.ProfileViewBasic 36 interpretFilterAsBlur?: boolean 37 } 38 39 export function PostHider({ ··· 42 disabled, 43 modui, 44 style, 45 children, 46 iconSize, 47 iconStyles, ··· 100 }, 101 override ? {paddingBottom: 0} : undefined, 102 t.atoms.bg, 103 ]}> 104 <ModerationDetailsDialog control={control} modcause={blur} /> 105 <Pressable
··· 34 modui: ModerationUI 35 profile: AppBskyActorDefs.ProfileViewBasic 36 interpretFilterAsBlur?: boolean 37 + hiderStyle?: StyleProp<ViewStyle> 38 } 39 40 export function PostHider({ ··· 43 disabled, 44 modui, 45 style, 46 + hiderStyle, 47 children, 48 iconSize, 49 iconStyles, ··· 102 }, 103 override ? {paddingBottom: 0} : undefined, 104 t.atoms.bg, 105 + hiderStyle, 106 ]}> 107 <ModerationDetailsDialog control={control} modcause={blur} /> 108 <Pressable
+2 -2
src/env/common.ts
··· 21 export const IS_TESTFLIGHT = ENV === 'testflight' 22 23 /** 24 - * Indicates whether the app is __DEV__ 25 */ 26 export const IS_DEV = __DEV__ 27 28 /** 29 - * Indicates whether the app is __DEV__ or TestFlight 30 */ 31 export const IS_INTERNAL = IS_DEV || IS_TESTFLIGHT 32
··· 21 export const IS_TESTFLIGHT = ENV === 'testflight' 22 23 /** 24 + * Indicates whether the app is `__DEV__` 25 */ 26 export const IS_DEV = __DEV__ 27 28 /** 29 + * Indicates whether the app is `__DEV__` or TestFlight 30 */ 31 export const IS_INTERNAL = IS_DEV || IS_TESTFLIGHT 32
+1
src/lib/constants.ts
··· 16 export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` 17 export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download' 18 export const STARTER_PACK_MAX_SIZE = 150 19 20 // HACK 21 // Yes, this is exactly what it looks like. It's a hard-coded constant
··· 16 export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` 17 export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download' 18 export const STARTER_PACK_MAX_SIZE = 150 19 + export const CARD_ASPECT_RATIO = 1200 / 630 20 21 // HACK 22 // Yes, this is exactly what it looks like. It's a hard-coded constant
-4
src/lib/statsig/gates.ts
··· 1 export type Gate = 2 // Keep this alphabetic please. 3 | 'alt_share_icon' 4 - | 'cta_above_post_heading' 5 - | 'cta_above_post_replies' 6 | 'debug_show_feedcontext' 7 | 'debug_subscriptions' 8 | 'disable_onboarding_policy_update_notice' ··· 10 | 'feed_reply_button_open_thread' 11 | 'old_postonboarding' 12 | 'onboarding_add_video_feed' 13 - | 'onboarding_suggested_accounts' 14 - | 'onboarding_value_prop' 15 | 'post_follow_profile_suggested_accounts' 16 | 'remove_show_latest_button' 17 | 'test_gate_1'
··· 1 export type Gate = 2 // Keep this alphabetic please. 3 | 'alt_share_icon' 4 | 'debug_show_feedcontext' 5 | 'debug_subscriptions' 6 | 'disable_onboarding_policy_update_notice' ··· 8 | 'feed_reply_button_open_thread' 9 | 'old_postonboarding' 10 | 'onboarding_add_video_feed' 11 | 'post_follow_profile_suggested_accounts' 12 | 'remove_show_latest_button' 13 | 'test_gate_1'
+264 -252
src/locale/locales/en/messages.po
··· 18 msgid "\"{interestsDisplayName}\" category (active)" 19 msgstr "" 20 21 - #: src/screens/Messages/components/ChatListItem.tsx:160 22 msgid "(contains embedded content)" 23 msgstr "" 24 ··· 95 msgid "{0, plural, one {following} other {following}}" 96 msgstr "" 97 98 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:480 99 msgid "{0, plural, one {like} other {likes}}" 100 msgstr "" 101 ··· 103 msgid "{0, plural, one {post} other {posts}}" 104 msgstr "" 105 106 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:464 107 msgid "{0, plural, one {quote} other {quotes}}" 108 msgstr "" 109 110 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:446 111 msgid "{0, plural, one {repost} other {reposts}}" 112 msgstr "" 113 114 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:491 115 msgid "{0, plural, one {save} other {saves}}" 116 msgstr "" 117 ··· 171 msgid "{0} reacted {1}" 172 msgstr "" 173 174 - #: src/screens/Messages/components/ChatListItem.tsx:231 175 msgid "{0} reacted {1} to {2}" 176 msgstr "" 177 ··· 521 msgid "7 days" 522 msgstr "" 523 524 - #: src/screens/Onboarding/StepFinished.tsx:340 525 msgid "A collection of popular feeds you can find on Bluesky, including News, Booksky, Game Dev, Blacksky, and Fountain Pens" 526 msgstr "" 527 528 #. If last message does not contain text, fall back to "{user} reacted to {a message}" 529 - #: src/screens/Messages/components/ChatListItem.tsx:210 530 msgid "a message" 531 msgstr "" 532 ··· 555 msgstr "" 556 557 #. Accept a chat request 558 - #: src/screens/Messages/components/RequestButtons.tsx:259 559 msgid "Accept" 560 msgstr "" 561 562 - #: src/screens/Messages/components/RequestButtons.tsx:249 563 msgid "Accept chat request" 564 msgstr "" 565 ··· 590 msgid "Account" 591 msgstr "" 592 593 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:361 594 - #: src/screens/Messages/components/RequestButtons.tsx:91 595 #: src/view/com/profile/ProfileMenu.tsx:166 596 msgctxt "toast" 597 msgid "Account blocked" ··· 602 msgid "Account followed" 603 msgstr "" 604 605 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:384 606 #: src/view/com/profile/ProfileMenu.tsx:142 607 msgctxt "toast" 608 msgid "Account muted" ··· 636 msgid "Account unfollowed" 637 msgstr "" 638 639 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:374 640 #: src/view/com/profile/ProfileMenu.tsx:132 641 msgctxt "toast" 642 msgid "Account unmuted" ··· 1016 msgid "An error occurred while uploading the video." 1017 msgstr "" 1018 1019 - #: src/screens/Onboarding/StepFinished.tsx:358 1020 msgid "An illustration of several Bluesky posts alongside repost, like, and comment icons" 1021 msgstr "" 1022 ··· 1064 msgid "and" 1065 msgstr "" 1066 1067 - #: src/screens/Onboarding/index.tsx:45 1068 #: src/screens/Onboarding/state.ts:102 1069 msgid "Animals" 1070 msgstr "" ··· 1187 msgid "Apply Pull Request" 1188 msgstr "" 1189 1190 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:660 1191 msgid "Archived from {0}" 1192 msgstr "" 1193 1194 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:629 1195 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:668 1196 msgid "Archived post" 1197 msgstr "" 1198 ··· 1241 msgid "Are you writing in <0>{suggestedLanguageName}</0>?" 1242 msgstr "" 1243 1244 - #: src/screens/Onboarding/index.tsx:39 1245 #: src/screens/Onboarding/state.ts:103 1246 msgid "Art" 1247 msgstr "" ··· 1254 msgid "As a small team, we cannot justify building the expensive infrastructure this requirement demands while legal challenges to this law are pending." 1255 msgstr "" 1256 1257 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:497 1258 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:499 1259 msgid "Assign topic for algo" 1260 msgstr "" 1261 ··· 1317 msgid "Before creating a starter pack, you must first verify your email." 1318 msgstr "" 1319 1320 - #: src/screens/Messages/components/RequestButtons.tsx:235 1321 msgid "Before you can accept this chat request, you must first verify your email." 1322 msgstr "" 1323 ··· 1349 msgid "Birthday" 1350 msgstr "" 1351 1352 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:760 1353 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 1354 #: src/view/com/profile/ProfileMenu.tsx:495 1355 msgid "Block" ··· 1357 1358 #: src/components/dms/ConvoMenu.tsx:247 1359 #: src/components/dms/ConvoMenu.tsx:250 1360 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:645 1361 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:647 1362 #: src/screens/Messages/components/RequestButtons.tsx:144 1363 - #: src/screens/Messages/components/RequestButtons.tsx:146 1364 #: src/view/com/profile/ProfileMenu.tsx:401 1365 #: src/view/com/profile/ProfileMenu.tsx:408 1366 msgid "Block account" 1367 msgstr "" 1368 1369 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:755 1370 #: src/view/com/profile/ProfileMenu.tsx:478 1371 msgid "Block Account?" 1372 msgstr "" ··· 1418 msgid "Blocked Accounts" 1419 msgstr "" 1420 1421 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:757 1422 #: src/view/com/profile/ProfileMenu.tsx:490 1423 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." 1424 msgstr "" ··· 1427 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours." 1428 msgstr "" 1429 1430 - #: src/screens/Profile/Sections/Labels.tsx:204 1431 msgid "Blocking does not prevent this labeler from placing labels on your account." 1432 msgstr "" 1433 ··· 1448 msgid "Bluesky" 1449 msgstr "" 1450 1451 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:690 1452 msgid "Bluesky cannot confirm the authenticity of the claimed date." 1453 msgstr "" 1454 ··· 1510 msgid "Blur images and filter from feeds" 1511 msgstr "" 1512 1513 - #: src/screens/Onboarding/index.tsx:46 1514 #: src/screens/Onboarding/state.ts:104 1515 msgid "Books" 1516 msgstr "" ··· 1741 msgid "Chat" 1742 msgstr "" 1743 1744 - #: src/screens/Messages/components/RequestButtons.tsx:78 1745 - #: src/screens/Messages/components/RequestButtons.tsx:304 1746 msgctxt "toast" 1747 msgid "Chat deleted" 1748 msgstr "" ··· 1827 msgid "Choose Post Languages" 1828 msgstr "" 1829 1830 - #: src/screens/Onboarding/StepFinished.tsx:573 1831 msgid "Choose the algorithms that power your custom feeds." 1832 msgstr "" 1833 ··· 1900 msgid "Click to retry failed message" 1901 msgstr "" 1902 1903 - #: src/screens/Onboarding/index.tsx:48 1904 msgid "Climate" 1905 msgstr "" 1906 ··· 2037 msgid "Color theme" 2038 msgstr "" 2039 2040 - #: src/screens/Onboarding/index.tsx:54 2041 #: src/screens/Onboarding/state.ts:105 2042 msgid "Comedy" 2043 msgstr "" 2044 2045 - #: src/screens/Onboarding/index.tsx:40 2046 #: src/screens/Onboarding/state.ts:106 2047 msgid "Comics" 2048 msgstr "" ··· 2053 msgid "Community Guidelines" 2054 msgstr "" 2055 2056 - #: src/screens/Onboarding/StepFinished.tsx:472 2057 - #: src/screens/Onboarding/StepFinished.tsx:586 2058 msgid "Complete onboarding and start using your account" 2059 msgstr "" 2060 ··· 2243 msgid "Conversation deleted" 2244 msgstr "" 2245 2246 - #: src/screens/Messages/components/ChatListItem.tsx:196 2247 msgid "Conversation deleted" 2248 msgstr "" 2249 2250 - #: src/screens/Onboarding/index.tsx:57 2251 msgid "Cooking" 2252 msgstr "" 2253 ··· 2256 msgstr "" 2257 2258 #: src/components/dms/MessageContextMenu.tsx:55 2259 - #: src/components/PostControls/DiscoverDebug.tsx:41 2260 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:230 2261 #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:72 2262 #: src/lib/sharing.ts:25 2263 #: src/lib/sharing.ts:41 ··· 2302 msgid "Copy DID" 2303 msgstr "" 2304 2305 - #: src/screens/Settings/components/ChangeHandleDialog.tsx:434 2306 msgid "Copy host" 2307 msgstr "" 2308 ··· 2346 msgid "Copy post at:// URI" 2347 msgstr "" 2348 2349 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:452 2350 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:454 2351 msgid "Copy post text" 2352 msgstr "" 2353 ··· 2355 msgid "Copy QR code" 2356 msgstr "" 2357 2358 - #: src/screens/Settings/components/ChangeHandleDialog.tsx:455 2359 msgid "Copy TXT record value" 2360 msgstr "" 2361 ··· 2431 msgid "Create a starter pack for me" 2432 msgstr "" 2433 2434 - #: src/components/LoggedOutCTA.tsx:71 2435 - #: src/components/LoggedOutCTA.tsx:76 2436 #: src/components/WelcomeModal.tsx:155 2437 #: src/components/WelcomeModal.tsx:163 2438 #: src/view/com/auth/SplashScreen.tsx:72 ··· 2500 msgid "Creator has been blocked" 2501 msgstr "" 2502 2503 - #: src/screens/Onboarding/index.tsx:42 2504 #: src/screens/Onboarding/state.ts:107 2505 msgid "Culture" 2506 msgstr "" ··· 2569 msgstr "" 2570 2571 #: src/components/dms/MessageContextMenu.tsx:185 2572 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:704 2573 #: src/screens/Messages/components/ChatStatusInfo.tsx:55 2574 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:280 2575 #: src/screens/Settings/AppPasswords.tsx:212 ··· 2596 msgid "Delete app password?" 2597 msgstr "" 2598 2599 - #: src/screens/Messages/components/RequestButtons.tsx:316 2600 - #: src/screens/Messages/components/RequestButtons.tsx:323 2601 msgid "Delete chat" 2602 msgstr "" 2603 ··· 2607 2608 #: src/components/dms/ReportDialog.tsx:368 2609 #: src/components/dms/ReportDialog.tsx:371 2610 - #: src/screens/Messages/components/RequestButtons.tsx:136 2611 - #: src/screens/Messages/components/RequestButtons.tsx:139 2612 msgid "Delete conversation" 2613 msgstr "" 2614 ··· 2637 msgid "Delete my account" 2638 msgstr "" 2639 2640 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:685 2641 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:687 2642 #: src/view/com/composer/Composer.tsx:966 2643 msgid "Delete post" 2644 msgstr "" ··· 2656 msgid "Delete this list?" 2657 msgstr "" 2658 2659 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:699 2660 msgid "Delete this post?" 2661 msgstr "" 2662 ··· 2665 msgstr "" 2666 2667 #: src/components/dms/MessagesListHeader.tsx:121 2668 - #: src/screens/Messages/components/ChatListItem.tsx:128 2669 msgid "Deleted Account" 2670 msgstr "" 2671 ··· 2676 msgid "Deleted list" 2677 msgstr "" 2678 2679 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:428 2680 #: src/screens/Profile/Header/EditProfileDialog.tsx:363 2681 #: src/screens/Profile/Header/EditProfileDialog.tsx:370 2682 msgid "Description" ··· 2687 msgid "Descriptive alt text" 2688 msgstr "" 2689 2690 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:589 2691 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:599 2692 msgid "Detach quote" 2693 msgstr "" 2694 2695 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:735 2696 msgid "Detach quote post?" 2697 msgstr "" 2698 ··· 2815 msgid "Display name" 2816 msgstr "" 2817 2818 - #: src/screens/Onboarding/StepFinished.tsx:346 2819 msgid "Ditch the trolls and clickbait. Find real people and conversations that matter to you." 2820 msgstr "" 2821 ··· 2862 #: src/components/Select/index.tsx:192 2863 #: src/screens/Onboarding/StepProfile/index.tsx:333 2864 #: src/screens/Onboarding/StepProfile/index.tsx:336 2865 - #: src/screens/Settings/components/AddAppPasswordDialog.tsx:215 2866 - #: src/screens/Settings/components/AddAppPasswordDialog.tsx:222 2867 #: src/view/com/auth/server-input/index.tsx:232 2868 #: src/view/com/auth/server-input/index.tsx:233 2869 #: src/view/com/composer/labels/LabelsBtn.tsx:223 ··· 2892 msgid "Double tap to close the dialog" 2893 msgstr "" 2894 2895 - #: src/screens/VideoFeed/index.tsx:1085 2896 msgid "Double tap to like" 2897 msgstr "" 2898 ··· 2905 msgid "Download CAR file" 2906 msgstr "" 2907 2908 - #: src/view/com/composer/text-input/TextInput.web.tsx:361 2909 msgid "Drop to add images" 2910 msgstr "" 2911 ··· 2929 msgid "E.g. artistic nudes." 2930 msgstr "" 2931 2932 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:392 2933 msgid "e.g. Great Posters" 2934 msgstr "" 2935 2936 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:429 2937 - msgid "e.g. The posters that never miss." 2938 msgstr "" 2939 2940 #: src/screens/Settings/AccountSettings.tsx:145 ··· 2966 msgid "Edit image" 2967 msgstr "" 2968 2969 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:666 2970 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:679 2971 msgid "Edit interaction settings" 2972 msgstr "" 2973 ··· 3036 msgid "Edit your starter pack" 3037 msgstr "" 3038 3039 - #: src/screens/Onboarding/index.tsx:47 3040 #: src/screens/Onboarding/state.ts:109 3041 msgid "Education" 3042 msgstr "" ··· 3326 msgid "Expand post text" 3327 msgstr "" 3328 3329 - #: src/screens/VideoFeed/index.tsx:970 3330 msgid "Expands or collapses post text" 3331 msgstr "" 3332 ··· 3405 msgid "External Media Preferences" 3406 msgstr "" 3407 3408 - #: src/screens/Messages/components/RequestButtons.tsx:220 3409 msgctxt "toast" 3410 msgid "Failed to accept chat" 3411 msgstr "" ··· 3436 msgid "Failed to create starter pack" 3437 msgstr "" 3438 3439 - #: src/screens/Messages/components/RequestButtons.tsx:64 3440 - #: src/screens/Messages/components/RequestButtons.tsx:291 3441 msgctxt "toast" 3442 msgid "Failed to delete chat" 3443 msgstr "" ··· 3446 msgid "Failed to delete message" 3447 msgstr "" 3448 3449 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:199 3450 msgid "Failed to delete post, please try again" 3451 msgstr "" 3452 ··· 3560 msgid "Failed to submit appeal, please try again." 3561 msgstr "" 3562 3563 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:219 3564 msgid "Failed to toggle thread mute, please try again" 3565 msgstr "" 3566 ··· 3639 msgid "Feedback" 3640 msgstr "" 3641 3642 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:270 3643 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:288 3644 msgctxt "toast" 3645 msgid "Feedback sent to feed operator" 3646 msgstr "" ··· 3698 msgid "Filter who you receive notifications from" 3699 msgstr "" 3700 3701 - #: src/screens/Onboarding/StepFinished.tsx:478 3702 - #: src/screens/Onboarding/StepFinished.tsx:589 3703 msgid "Finalizing" 3704 msgstr "" 3705 ··· 3723 msgid "Find posts, users, and feeds on Bluesky" 3724 msgstr "" 3725 3726 - #: src/screens/Onboarding/StepFinished.tsx:344 3727 msgid "Find your people" 3728 msgstr "" 3729 ··· 3731 msgid "Finish" 3732 msgstr "" 3733 3734 - #: src/screens/Onboarding/index.tsx:51 3735 msgid "Fitness" 3736 msgstr "" 3737 ··· 3750 msgid "Flat White" 3751 msgstr "" 3752 3753 - #: src/screens/Onboarding/StepFinished.tsx:569 3754 msgid "Flexible" 3755 msgstr "" 3756 ··· 3760 #: src/components/ProfileHoverCard/index.web.tsx:507 3761 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:131 3762 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:252 3763 - #: src/screens/VideoFeed/index.tsx:854 3764 msgid "Follow" 3765 msgstr "" 3766 ··· 3774 msgid "Follow {0}" 3775 msgstr "" 3776 3777 - #: src/screens/VideoFeed/index.tsx:831 3778 msgid "Follow {handle}" 3779 msgstr "" 3780 ··· 3849 #: src/components/ProfileHoverCard/index.web.tsx:506 3850 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:134 3851 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:248 3852 - #: src/screens/VideoFeed/index.tsx:852 3853 msgid "Following" 3854 msgstr "" 3855 ··· 3864 msgid "Following {0}" 3865 msgstr "" 3866 3867 - #: src/screens/VideoFeed/index.tsx:830 3868 msgid "Following {handle}" 3869 msgstr "" 3870 ··· 3894 msgid "Font size" 3895 msgstr "" 3896 3897 - #: src/screens/Onboarding/index.tsx:56 3898 #: src/screens/Onboarding/state.ts:110 3899 msgid "Food" 3900 msgstr "" ··· 3907 msgid "For security reasons, we'll need to send a confirmation code to your email address." 3908 msgstr "" 3909 3910 - #: src/screens/Settings/components/AddAppPasswordDialog.tsx:209 3911 msgid "For security reasons, you won't be able to view this again. If you lose this app password, you'll need to generate a new one." 3912 msgstr "" 3913 ··· 3924 msgid "Forever" 3925 msgstr "" 3926 3927 - #: src/screens/Onboarding/StepFinished.tsx:353 3928 msgid "Forget the noise" 3929 msgstr "" 3930 ··· 3941 msgid "Forgot?" 3942 msgstr "" 3943 3944 - #: src/screens/Onboarding/StepFinished.tsx:335 3945 msgid "Free your feed" 3946 msgstr "" 3947 ··· 4059 #: src/screens/ProfileList/components/ErrorScreen.tsx:34 4060 #: src/screens/ProfileList/components/ErrorScreen.tsx:40 4061 #: src/screens/VideoFeed/components/Header.tsx:163 4062 - #: src/screens/VideoFeed/index.tsx:1146 4063 - #: src/screens/VideoFeed/index.tsx:1150 4064 #: src/view/com/auth/LoggedOut.tsx:72 4065 #: src/view/screens/NotFound.tsx:57 4066 msgid "Go back" ··· 4079 #: src/components/dms/ReportDialog.tsx:197 4080 #: src/components/ReportDialog/SelectReportOptionView.tsx:81 4081 #: src/components/ReportDialog/SubmitView.tsx:110 4082 - #: src/screens/Onboarding/Layout.tsx:121 4083 - #: src/screens/Onboarding/Layout.tsx:214 4084 #: src/screens/Signup/BackNextButtons.tsx:35 4085 msgid "Go back to previous step" 4086 msgstr "" ··· 4126 msgid "Go to account settings" 4127 msgstr "" 4128 4129 - #: src/screens/Messages/components/ChatListItem.tsx:360 4130 msgid "Go to conversation with {0}" 4131 msgstr "" 4132 ··· 4226 msgid "Hidden" 4227 msgstr "" 4228 4229 - #: src/screens/VideoFeed/index.tsx:628 4230 msgid "Hidden by your moderation settings." 4231 msgstr "" 4232 ··· 4238 #: src/components/interstitials/TrendingVideos.tsx:138 4239 #: src/components/moderation/ContentHider.tsx:203 4240 #: src/components/moderation/LabelPreference.tsx:140 4241 - #: src/components/moderation/PostHider.tsx:134 4242 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:715 4243 #: src/lib/moderation/useLabelBehaviorDescription.ts:18 4244 #: src/lib/moderation/useLabelBehaviorDescription.ts:23 4245 #: src/lib/moderation/useLabelBehaviorDescription.ts:28 ··· 4257 msgid "Hide customization options" 4258 msgstr "" 4259 4260 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:546 4261 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:552 4262 msgid "Hide post for me" 4263 msgstr "" 4264 4265 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:563 4266 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:573 4267 msgid "Hide reply for everyone" 4268 msgstr "" 4269 4270 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:545 4271 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:551 4272 msgid "Hide reply for me" 4273 msgstr "" 4274 ··· 4276 msgid "Hide this card" 4277 msgstr "" 4278 4279 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:710 4280 msgid "Hide this post?" 4281 msgstr "" 4282 4283 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:710 4284 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:745 4285 msgid "Hide this reply?" 4286 msgstr "" 4287 ··· 4309 msgstr "" 4310 4311 #: src/components/moderation/ContentHider.tsx:154 4312 - #: src/components/moderation/PostHider.tsx:89 4313 msgid "Hides the content" 4314 msgstr "" 4315 ··· 4406 msgid "If you need to update your email, <0>click here</0>." 4407 msgstr "" 4408 4409 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:701 4410 msgid "If you remove this post, you won't be able to recover it." 4411 msgstr "" 4412 ··· 4554 msgid "Invalid handle. Please try a different one." 4555 msgstr "" 4556 4557 #: src/components/moderation/ReportDialog/index.tsx:73 4558 msgid "Invalid report subject" 4559 msgstr "" ··· 4607 msgid "Jobs" 4608 msgstr "" 4609 4610 - #: src/components/LoggedOutCTA.tsx:54 4611 #: src/screens/StarterPack/StarterPackLandingScreen.tsx:210 4612 #: src/screens/StarterPack/StarterPackLandingScreen.tsx:216 4613 #: src/screens/StarterPack/StarterPackScreen.tsx:466 ··· 4620 msgid "Join the conversation" 4621 msgstr "" 4622 4623 - #: src/screens/Onboarding/index.tsx:37 4624 #: src/screens/Onboarding/state.ts:112 4625 msgid "Journalism" 4626 msgstr "" ··· 4658 msgid "Labels added" 4659 msgstr "" 4660 4661 - #: src/screens/Profile/Sections/Labels.tsx:195 4662 msgid "Labels are annotations on users and content. They can be used to hide, warn, and categorize the network." 4663 msgstr "" 4664 ··· 4737 msgid "Learn more about these changes and how to share your thoughts with us by reading our blog post." 4738 msgstr "" 4739 4740 - #: src/components/moderation/PostHider.tsx:110 4741 #: src/components/moderation/ScreenHider.tsx:133 4742 msgid "Learn more about this warning" 4743 msgstr "" ··· 4801 msgid "Let's get your password reset!" 4802 msgstr "" 4803 4804 - #: src/screens/Onboarding/StepFinished.tsx:480 4805 - #: src/screens/Onboarding/StepFinished.tsx:589 4806 msgid "Let's go!" 4807 msgstr "" 4808 ··· 4887 msgid "Likes of your reposts notifications" 4888 msgstr "" 4889 4890 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:473 4891 msgid "Likes on this post" 4892 msgstr "" 4893 ··· 4900 msgid "List" 4901 msgstr "" 4902 4903 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:372 4904 msgid "List avatar" 4905 msgstr "" 4906 ··· 4931 msgid "List deleted" 4932 msgstr "" 4933 4934 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:421 4935 msgid "List description" 4936 msgstr "" 4937 4938 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:441 4939 msgid "List description is too long. {DESCRIPTION_MAX_GRAPHEMES, plural, other {The maximum number of characters is #.}}" 4940 msgstr "" 4941 ··· 4947 msgid "List Hidden" 4948 msgstr "" 4949 4950 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:413 4951 msgid "List must have a name." 4952 msgstr "" 4953 ··· 4956 msgid "List muted" 4957 msgstr "" 4958 4959 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:385 4960 msgid "List name" 4961 msgstr "" 4962 4963 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:405 4964 msgid "List name is too long. {DISPLAY_NAME_MAX_GRAPHEMES, plural, other {The maximum number of characters is #.}}" 4965 msgstr "" 4966 ··· 5152 msgid "Message deleted" 5153 msgstr "" 5154 5155 - #: src/screens/Messages/components/ChatListItem.tsx:197 5156 msgid "Message deleted" 5157 msgstr "" 5158 ··· 5304 msgid "Mute {tag}" 5305 msgstr "" 5306 5307 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:628 5308 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:634 5309 #: src/view/com/profile/ProfileMenu.tsx:380 5310 #: src/view/com/profile/ProfileMenu.tsx:387 5311 msgid "Mute account" ··· 5357 msgid "Mute this word until you unmute it" 5358 msgstr "" 5359 5360 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:512 5361 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:516 5362 msgid "Mute thread" 5363 msgstr "" 5364 5365 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:526 5366 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:528 5367 msgid "Mute words & tags" 5368 msgstr "" 5369 ··· 5401 msgid "My Feeds" 5402 msgstr "" 5403 5404 - #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:391 5405 msgid "Name" 5406 msgstr "" 5407 ··· 5416 msgid "Name or Description Violates Community Standards" 5417 msgstr "" 5418 5419 - #: src/screens/Onboarding/index.tsx:38 5420 #: src/screens/Onboarding/state.ts:115 5421 msgid "Nature" 5422 msgstr "" ··· 5448 msgid "Need to report a copyright violation?" 5449 msgstr "" 5450 5451 - #: src/screens/Onboarding/StepFinished.tsx:557 5452 msgid "Never lose access to your followers or data." 5453 msgstr "" 5454 ··· 5563 msgid "Newest replies first" 5564 msgstr "" 5565 5566 - #: src/screens/Onboarding/index.tsx:36 5567 #: src/screens/Onboarding/state.ts:116 5568 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:238 5569 msgid "News" ··· 5575 #: src/screens/Login/LoginForm.tsx:350 5576 #: src/screens/Login/SetNewPasswordForm.tsx:182 5577 #: src/screens/Login/SetNewPasswordForm.tsx:188 5578 - #: src/screens/Onboarding/StepFinished.tsx:473 5579 - #: src/screens/Onboarding/StepFinished.tsx:482 5580 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:157 5581 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:165 5582 #: src/screens/Signup/BackNextButtons.tsx:67 ··· 5596 msgid "Next image" 5597 msgstr "" 5598 5599 - #: src/screens/Onboarding/StepFinished.tsx:355 5600 msgid "No ads, no invasive tracking, no engagement traps. Bluesky respects your time and attention." 5601 msgstr "" 5602 ··· 5635 msgid "No longer following {0}" 5636 msgstr "" 5637 5638 - #: src/screens/Messages/components/ChatListItem.tsx:139 5639 msgid "No messages yet" 5640 msgstr "" 5641 5642 - #: src/screens/Onboarding/StepFinished.tsx:337 5643 msgid "No more doomscrolling junk-filled algorithms. Find feeds that work for you, not against you." 5644 msgstr "" 5645 ··· 5861 msgstr "" 5862 5863 #: src/screens/Login/PasswordUpdatedForm.tsx:37 5864 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:695 5865 msgid "Okay" 5866 msgstr "" 5867 ··· 5935 msgid "Oops!" 5936 msgstr "" 5937 5938 - #: src/screens/Onboarding/StepFinished.tsx:553 5939 msgid "Open" 5940 msgstr "" 5941 ··· 5943 msgid "Open avatar creator" 5944 msgstr "" 5945 5946 - #: src/screens/Messages/components/ChatListItem.tsx:368 5947 - #: src/screens/Messages/components/ChatListItem.tsx:369 5948 msgid "Open conversation options" 5949 msgstr "" 5950 ··· 6226 msgid "Person toggle" 6227 msgstr "" 6228 6229 - #: src/screens/Onboarding/index.tsx:44 6230 #: src/screens/Onboarding/state.ts:117 6231 msgid "Pets" 6232 msgstr "" ··· 6258 msgid "Pin to Home" 6259 msgstr "" 6260 6261 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:420 6262 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:427 6263 msgid "Pin to your profile" 6264 msgstr "" 6265 ··· 6455 msgid "Please write your message below:" 6456 msgstr "" 6457 6458 - #: src/screens/Onboarding/index.tsx:50 6459 #: src/screens/Onboarding/state.ts:119 6460 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:232 6461 msgid "Politics" ··· 6465 msgid "Porn" 6466 msgstr "" 6467 6468 - #: src/screens/PostThread/index.tsx:503 6469 msgctxt "description" 6470 msgid "Post" 6471 msgstr "" ··· 6491 msgid "Post by @{0}" 6492 msgstr "" 6493 6494 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:179 6495 msgctxt "toast" 6496 msgid "Post deleted" 6497 msgstr "" ··· 6500 msgid "Post failed to upload. Please check your Internet connection and try again." 6501 msgstr "" 6502 6503 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:134 6504 #: src/screens/PostThread/components/ThreadItemPost.tsx:111 6505 #: src/screens/PostThread/components/ThreadItemTreePost.tsx:107 6506 - #: src/screens/VideoFeed/index.tsx:532 6507 msgid "Post has been deleted" 6508 msgstr "" 6509 ··· 6666 msgid "Profile updated" 6667 msgstr "" 6668 6669 - #: src/screens/Onboarding/StepFinished.tsx:539 6670 msgid "Public" 6671 msgstr "" 6672 ··· 6737 msgid "Quote post" 6738 msgstr "" 6739 6740 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:308 6741 msgid "Quote post was re-attached" 6742 msgstr "" 6743 6744 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:307 6745 msgid "Quote post was successfully detached" 6746 msgstr "" 6747 ··· 6763 msgid "Quotes" 6764 msgstr "" 6765 6766 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:457 6767 msgid "Quotes of this post" 6768 msgstr "" 6769 ··· 6771 msgid "Rate limit exceeded – you've tried to change your handle too many times in a short period. Please wait a minute before trying again." 6772 msgstr "" 6773 6774 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:588 6775 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:598 6776 msgid "Re-attach quote" 6777 msgstr "" 6778 ··· 6793 msgid "Read blog post" 6794 msgstr "" 6795 6796 - #: src/screens/VideoFeed/index.tsx:971 6797 msgid "Read less" 6798 msgstr "" 6799 6800 - #: src/screens/VideoFeed/index.tsx:971 6801 msgid "Read more" 6802 msgstr "" 6803 ··· 6866 msgstr "" 6867 6868 #. Reject a chat request, this opens a menu with options 6869 - #: src/screens/Messages/components/RequestButtons.tsx:124 6870 msgid "Reject" 6871 msgstr "" 6872 6873 - #: src/screens/Messages/components/RequestButtons.tsx:112 6874 msgid "Reject chat request" 6875 msgstr "" 6876 ··· 7120 msgid "Reply sorting" 7121 msgstr "" 7122 7123 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:339 7124 msgctxt "toast" 7125 msgid "Reply visibility updated" 7126 msgstr "" 7127 7128 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:338 7129 msgid "Reply was successfully hidden" 7130 msgstr "" 7131 ··· 7143 #: src/components/dms/ConvoMenu.tsx:255 7144 #: src/components/dms/ConvoMenu.tsx:258 7145 #: src/components/dms/ReportConversationPrompt.tsx:17 7146 - #: src/screens/Messages/components/RequestButtons.tsx:155 7147 - #: src/screens/Messages/components/RequestButtons.tsx:158 7148 msgid "Report conversation" 7149 msgstr "" 7150 ··· 7168 msgid "Report message" 7169 msgstr "" 7170 7171 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:654 7172 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:656 7173 msgid "Report post" 7174 msgstr "" 7175 ··· 7265 msgid "Reposts" 7266 msgstr "" 7267 7268 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:439 7269 msgid "Reposts of this post" 7270 msgstr "" 7271 ··· 7388 #: src/screens/Profile/ProfileFeed/index.tsx:93 7389 #: src/screens/ProfileList/components/ErrorScreen.tsx:35 7390 #: src/screens/Settings/components/ChangeHandleDialog.tsx:569 7391 - #: src/screens/VideoFeed/index.tsx:1147 7392 #: src/view/screens/NotFound.tsx:60 7393 msgid "Returns to previous page" 7394 msgstr "" ··· 7480 msgid "Say hello!" 7481 msgstr "" 7482 7483 - #: src/screens/Onboarding/index.tsx:49 7484 #: src/screens/Onboarding/state.ts:120 7485 msgid "Science" 7486 msgstr "" ··· 7957 msgid "Share anyway" 7958 msgstr "" 7959 7960 - #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:159 7961 - #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:162 7962 msgid "Share author DID" 7963 msgstr "" 7964 ··· 7973 msgid "Share link dialog" 7974 msgstr "" 7975 7976 - #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:150 7977 - #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:153 7978 msgid "Share post at:// URI" 7979 msgstr "" 7980 ··· 8016 8017 #: src/components/moderation/ContentHider.tsx:203 8018 #: src/components/moderation/LabelPreference.tsx:142 8019 - #: src/components/moderation/PostHider.tsx:134 8020 msgid "Show" 8021 msgstr "" 8022 ··· 8027 #: src/components/moderation/ScreenHider.tsx:178 8028 #: src/components/moderation/ScreenHider.tsx:181 8029 #: src/screens/List/ListHiddenScreen.tsx:190 8030 - #: src/screens/VideoFeed/index.tsx:631 8031 - #: src/screens/VideoFeed/index.tsx:637 8032 msgid "Show anyway" 8033 msgstr "" 8034 ··· 8045 msgid "Show customization options" 8046 msgstr "" 8047 8048 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:483 8049 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:485 8050 msgid "Show less like this" 8051 msgstr "" 8052 ··· 8058 msgid "Show More" 8059 msgstr "" 8060 8061 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:475 8062 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:477 8063 msgid "Show more like this" 8064 msgstr "" 8065 ··· 8089 msgid "Show replies by people you follow before all other replies" 8090 msgstr "" 8091 8092 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:562 8093 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:572 8094 msgid "Show reply for everyone" 8095 msgstr "" 8096 ··· 8112 msgid "Show warning and filter from feeds" 8113 msgstr "" 8114 8115 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:631 8116 msgid "Shows information about when this post was created" 8117 msgstr "" 8118 ··· 8121 msgstr "" 8122 8123 #: src/components/moderation/ContentHider.tsx:155 8124 - #: src/components/moderation/PostHider.tsx:89 8125 msgid "Shows the content" 8126 msgstr "" 8127 ··· 8171 msgid "Sign in to Bluesky or create a new account" 8172 msgstr "" 8173 8174 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:461 8175 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:463 8176 msgid "Sign in to view post" 8177 msgstr "" 8178 ··· 8211 msgid "Similar accounts" 8212 msgstr "" 8213 8214 - #: src/screens/Onboarding/StepFinished.tsx:379 8215 - #: src/screens/Onboarding/StepFinished.tsx:461 8216 #: src/screens/Onboarding/StepInterests/index.tsx:240 8217 #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:222 8218 #: src/screens/StarterPack/Wizard/index.tsx:218 8219 msgid "Skip" 8220 msgstr "" 8221 8222 - #: src/screens/Onboarding/StepFinished.tsx:372 8223 - #: src/screens/Onboarding/StepFinished.tsx:458 8224 msgid "Skip introduction and start using your account" 8225 msgstr "" 8226 ··· 8241 msgid "Social media you control." 8242 msgstr "" 8243 8244 - #: src/screens/Onboarding/index.tsx:53 8245 #: src/screens/Onboarding/state.ts:108 8246 msgid "Software Dev" 8247 msgstr "" ··· 8262 msgid "Someone reacted {0}" 8263 msgstr "" 8264 8265 - #: src/screens/Messages/components/ChatListItem.tsx:241 8266 msgid "Someone reacted {0} to {1}" 8267 msgstr "" 8268 ··· 8284 8285 #: src/components/ReportDialog/index.tsx:54 8286 #: src/screens/Moderation/index.tsx:112 8287 - #: src/screens/Profile/Sections/Labels.tsx:185 8288 msgid "Something went wrong, please try again." 8289 msgstr "" 8290 ··· 8338 msgid "Spam; excessive mentions or replies" 8339 msgstr "" 8340 8341 - #: src/screens/Onboarding/index.tsx:43 8342 #: src/screens/Onboarding/state.ts:121 8343 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:230 8344 msgid "Sports" ··· 8443 msgid "Subscribe" 8444 msgstr "" 8445 8446 - #: src/screens/Profile/Sections/Labels.tsx:232 8447 msgid "Subscribe to @{0} to use these labels:" 8448 msgstr "" 8449 ··· 8583 msgid "Teach our algorithm what you like" 8584 msgstr "" 8585 8586 - #: src/screens/Onboarding/index.tsx:52 8587 #: src/screens/Onboarding/state.ts:122 8588 msgid "Tech" 8589 msgstr "" ··· 8679 msgid "That's all, folks!" 8680 msgstr "" 8681 8682 - #: src/screens/VideoFeed/index.tsx:1119 8683 msgid "That's everything!" 8684 msgstr "" 8685 ··· 8748 8749 #: src/components/ageAssurance/useAgeAssuranceCopy.ts:14 8750 msgid "The laws in your location require you to verify you're an adult to access certain features. Tap to learn more." 8751 - msgstr "" 8752 - 8753 - #: src/components/LoggedOutCTA.tsx:63 8754 - msgid "The open social network." 8755 msgstr "" 8756 8757 #: src/view/com/composer/select-language/SuggestedLanguage.tsx:119 ··· 8857 msgid "There was an issue updating your feeds, please check your internet connection and try again." 8858 msgstr "" 8859 8860 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:365 8861 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:378 8862 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:388 8863 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:90 8864 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:101 8865 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:101 ··· 8962 msgid "This content is not viewable without a Bluesky account." 8963 msgstr "" 8964 8965 - #: src/screens/Messages/components/ChatListItem.tsx:362 8966 msgid "This conversation is with a deleted or a deactivated account. Press for options" 8967 msgstr "" 8968 ··· 9025 msgid "This label was applied by you." 9026 msgstr "" 9027 9028 - #: src/screens/Profile/Sections/Labels.tsx:219 9029 msgid "This labeler hasn't declared what labels it publishes, and may not be active." 9030 msgstr "" 9031 ··· 9049 msgid "This moderation service is unavailable. See below for more details. If this issue persists, contact us." 9050 msgstr "" 9051 9052 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:671 9053 msgid "This post claims to have been created on <0>{0}</0>, but was first seen by Bluesky on <1>{1}</1>." 9054 msgstr "" 9055 ··· 9057 msgid "This post has an unknown type of threadgate on it. Your app may be out of date." 9058 msgstr "" 9059 9060 - #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:140 9061 msgid "This post is only visible to logged-in users." 9062 msgstr "" 9063 ··· 9065 msgid "This post was deleted by its author" 9066 msgstr "" 9067 9068 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:712 9069 msgid "This post will be hidden from feeds and threads. This cannot be undone." 9070 msgstr "" 9071 ··· 9077 msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in." 9078 msgstr "" 9079 9080 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:747 9081 msgid "This reply will be sorted into a hidden section at the bottom of your thread and will mute notifications for subsequent replies - both for yourself and others." 9082 msgstr "" 9083 ··· 9138 msgid "This will remove @{0} from the quick access list." 9139 msgstr "" 9140 9141 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:737 9142 msgid "This will remove your post from this quote post for all users, and replace it with a placeholder." 9143 msgstr "" 9144 ··· 9217 9218 #: src/components/dms/MessageContextMenu.tsx:137 9219 #: src/components/dms/MessageContextMenu.tsx:139 9220 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:444 9221 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:446 9222 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:593 9223 - #: src/screens/PostThread/components/ThreadItemAnchor.tsx:596 9224 msgid "Translate" 9225 msgstr "" 9226 ··· 9367 msgid "Unfollow account" 9368 msgstr "" 9369 9370 - #: src/screens/VideoFeed/index.tsx:835 9371 msgid "Unfollows the user" 9372 msgstr "" 9373 ··· 9408 msgid "Unmute {tag}" 9409 msgstr "" 9410 9411 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:627 9412 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:633 9413 #: src/view/com/profile/ProfileMenu.tsx:379 9414 #: src/view/com/profile/ProfileMenu.tsx:385 9415 msgid "Unmute account" ··· 9424 msgid "Unmute list" 9425 msgstr "" 9426 9427 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:512 9428 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:516 9429 msgid "Unmute thread" 9430 msgstr "" 9431 ··· 9453 msgid "Unpin from home" 9454 msgstr "" 9455 9456 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:419 9457 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:426 9458 msgid "Unpin from profile" 9459 msgstr "" 9460 ··· 9533 msgid "Update your email" 9534 msgstr "" 9535 9536 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:312 9537 msgctxt "toast" 9538 msgid "Updating quote attachment failed" 9539 msgstr "" 9540 9541 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:343 9542 msgctxt "toast" 9543 msgid "Updating reply visibility failed" 9544 msgstr "" ··· 9819 msgid "Video from {0}: {text}" 9820 msgstr "" 9821 9822 - #: src/screens/Onboarding/index.tsx:55 9823 #: src/screens/Onboarding/state.ts:111 9824 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:234 9825 msgid "Video Games" 9826 msgstr "" 9827 9828 - #: src/screens/VideoFeed/index.tsx:1077 9829 msgid "Video is paused" 9830 msgstr "" 9831 9832 - #: src/screens/VideoFeed/index.tsx:1077 9833 msgid "Video is playing" 9834 msgstr "" 9835 ··· 9869 #: src/components/ProfileCard.tsx:124 9870 #: src/screens/Profile/components/ProfileFeedHeader.tsx:454 9871 #: src/screens/Search/components/SearchProfileCard.tsx:36 9872 - #: src/screens/VideoFeed/index.tsx:794 9873 #: src/view/com/notifications/NotificationFeedItem.tsx:599 9874 msgid "View {0}'s profile" 9875 msgstr "" ··· 9891 msgstr "" 9892 9893 #: src/components/ReportDialog/SelectReportOptionView.tsx:140 9894 - #: src/screens/VideoFeed/index.tsx:659 9895 - #: src/screens/VideoFeed/index.tsx:677 9896 msgid "View details" 9897 msgstr "" 9898 ··· 9978 msgstr "" 9979 9980 #: src/view/com/util/images/AutoSizedImage.tsx:206 9981 - #: src/view/com/util/images/AutoSizedImage.tsx:228 9982 msgid "Views full image" 9983 msgstr "" 9984 ··· 10050 msgid "We have sent another verification email to <0>{0}</0>." 10051 msgstr "" 10052 10053 - #: src/screens/Onboarding/StepFinished.tsx:531 10054 msgid "We hope you have a wonderful time. Remember, Bluesky is:" 10055 msgstr "" 10056 ··· 10285 msgid "Write your reply" 10286 msgstr "" 10287 10288 - #: src/screens/Onboarding/index.tsx:41 10289 #: src/screens/Onboarding/state.ts:124 10290 msgid "Writers" 10291 msgstr "" ··· 10312 msgid "Yes, delete this starter pack" 10313 msgstr "" 10314 10315 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:740 10316 msgid "Yes, detach" 10317 msgstr "" 10318 10319 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:750 10320 msgid "Yes, hide" 10321 msgstr "" 10322 ··· 10404 10405 #: src/screens/Messages/Settings.tsx:116 10406 msgid "You can continue ongoing conversations regardless of which setting you choose." 10407 msgstr "" 10408 10409 #: src/components/dialogs/nuxs/ActivitySubscriptions.tsx:148 ··· 10630 msgid "You reacted {0}" 10631 msgstr "" 10632 10633 - #: src/screens/Messages/components/ChatListItem.tsx:218 10634 msgid "You reacted {0} to {1}" 10635 msgstr "" 10636 ··· 10643 msgid "You will no longer receive notifications for {0}" 10644 msgstr "" 10645 10646 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:212 10647 msgid "You will no longer receive notifications for this thread" 10648 msgstr "" 10649 10650 - #: src/components/PostControls/PostMenu/PostMenuItems.tsx:208 10651 msgid "You will now receive notifications for this thread" 10652 msgstr "" 10653 ··· 10655 msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password." 10656 msgstr "" 10657 10658 - #: src/screens/Messages/components/ChatListItem.tsx:154 10659 msgid "You: {0}" 10660 msgstr "" 10661 10662 - #: src/screens/Messages/components/ChatListItem.tsx:183 10663 msgid "You: {defaultEmbeddedContentMessage}" 10664 msgstr "" 10665 10666 - #: src/screens/Messages/components/ChatListItem.tsx:176 10667 msgid "You: {short}" 10668 msgstr "" 10669 ··· 10695 msgid "You're in line" 10696 msgstr "" 10697 10698 - #: src/screens/Onboarding/StepFinished.tsx:528 10699 msgid "You're ready to go!" 10700 msgstr "" 10701 ··· 10737 msgid "You've reached your daily limit for video uploads (too many videos)" 10738 msgstr "" 10739 10740 - #: src/screens/VideoFeed/index.tsx:1128 10741 msgid "You've run out of videos to watch. Maybe it's a good time to take a break?" 10742 msgstr "" 10743 ··· 10867 msgid "Your posts were sent" 10868 msgstr "" 10869 10870 - #: src/screens/Onboarding/StepFinished.tsx:543 10871 msgid "Your posts, likes, and blocks are public. Mutes are private." 10872 msgstr "" 10873 ··· 10875 msgid "Your preferred language" 10876 msgstr "" 10877 10878 - #: src/screens/Onboarding/StepFinished.tsx:421 10879 msgid "Your profile picture" 10880 msgstr "" 10881 10882 - #: src/screens/Onboarding/StepFinished.tsx:349 10883 msgid "Your profile picture surrounded by concentric circles of other users' profile pictures" 10884 msgstr "" 10885
··· 18 msgid "\"{interestsDisplayName}\" category (active)" 19 msgstr "" 20 21 + #: src/screens/Messages/components/ChatListItem.tsx:163 22 msgid "(contains embedded content)" 23 msgstr "" 24 ··· 95 msgid "{0, plural, one {following} other {following}}" 96 msgstr "" 97 98 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:476 99 msgid "{0, plural, one {like} other {likes}}" 100 msgstr "" 101 ··· 103 msgid "{0, plural, one {post} other {posts}}" 104 msgstr "" 105 106 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:460 107 msgid "{0, plural, one {quote} other {quotes}}" 108 msgstr "" 109 110 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:442 111 msgid "{0, plural, one {repost} other {reposts}}" 112 msgstr "" 113 114 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:487 115 msgid "{0, plural, one {save} other {saves}}" 116 msgstr "" 117 ··· 171 msgid "{0} reacted {1}" 172 msgstr "" 173 174 + #: src/screens/Messages/components/ChatListItem.tsx:234 175 msgid "{0} reacted {1} to {2}" 176 msgstr "" 177 ··· 521 msgid "7 days" 522 msgstr "" 523 524 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:17 525 msgid "A collection of popular feeds you can find on Bluesky, including News, Booksky, Game Dev, Blacksky, and Fountain Pens" 526 msgstr "" 527 528 #. If last message does not contain text, fall back to "{user} reacted to {a message}" 529 + #: src/screens/Messages/components/ChatListItem.tsx:213 530 msgid "a message" 531 msgstr "" 532 ··· 555 msgstr "" 556 557 #. Accept a chat request 558 + #: src/screens/Messages/components/RequestButtons.tsx:255 559 msgid "Accept" 560 msgstr "" 561 562 + #: src/screens/Messages/components/RequestButtons.tsx:246 563 msgid "Accept chat request" 564 msgstr "" 565 ··· 590 msgid "Account" 591 msgstr "" 592 593 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:386 594 + #: src/screens/Messages/components/RequestButtons.tsx:90 595 #: src/view/com/profile/ProfileMenu.tsx:166 596 msgctxt "toast" 597 msgid "Account blocked" ··· 602 msgid "Account followed" 603 msgstr "" 604 605 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:409 606 #: src/view/com/profile/ProfileMenu.tsx:142 607 msgctxt "toast" 608 msgid "Account muted" ··· 636 msgid "Account unfollowed" 637 msgstr "" 638 639 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:399 640 #: src/view/com/profile/ProfileMenu.tsx:132 641 msgctxt "toast" 642 msgid "Account unmuted" ··· 1016 msgid "An error occurred while uploading the video." 1017 msgstr "" 1018 1019 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:35 1020 msgid "An illustration of several Bluesky posts alongside repost, like, and comment icons" 1021 msgstr "" 1022 ··· 1064 msgid "and" 1065 msgstr "" 1066 1067 + #: src/screens/Onboarding/index.tsx:42 1068 #: src/screens/Onboarding/state.ts:102 1069 msgid "Animals" 1070 msgstr "" ··· 1187 msgid "Apply Pull Request" 1188 msgstr "" 1189 1190 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:656 1191 msgid "Archived from {0}" 1192 msgstr "" 1193 1194 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:625 1195 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:664 1196 msgid "Archived post" 1197 msgstr "" 1198 ··· 1241 msgid "Are you writing in <0>{suggestedLanguageName}</0>?" 1242 msgstr "" 1243 1244 + #: src/screens/Onboarding/index.tsx:36 1245 #: src/screens/Onboarding/state.ts:103 1246 msgid "Art" 1247 msgstr "" ··· 1254 msgid "As a small team, we cannot justify building the expensive infrastructure this requirement demands while legal challenges to this law are pending." 1255 msgstr "" 1256 1257 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:522 1258 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:524 1259 msgid "Assign topic for algo" 1260 msgstr "" 1261 ··· 1317 msgid "Before creating a starter pack, you must first verify your email." 1318 msgstr "" 1319 1320 + #: src/screens/Messages/components/RequestButtons.tsx:232 1321 msgid "Before you can accept this chat request, you must first verify your email." 1322 msgstr "" 1323 ··· 1349 msgid "Birthday" 1350 msgstr "" 1351 1352 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:785 1353 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 1354 #: src/view/com/profile/ProfileMenu.tsx:495 1355 msgid "Block" ··· 1357 1358 #: src/components/dms/ConvoMenu.tsx:247 1359 #: src/components/dms/ConvoMenu.tsx:250 1360 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:670 1361 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:672 1362 + #: src/screens/Messages/components/RequestButtons.tsx:142 1363 #: src/screens/Messages/components/RequestButtons.tsx:144 1364 #: src/view/com/profile/ProfileMenu.tsx:401 1365 #: src/view/com/profile/ProfileMenu.tsx:408 1366 msgid "Block account" 1367 msgstr "" 1368 1369 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:780 1370 #: src/view/com/profile/ProfileMenu.tsx:478 1371 msgid "Block Account?" 1372 msgstr "" ··· 1418 msgid "Blocked Accounts" 1419 msgstr "" 1420 1421 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:782 1422 #: src/view/com/profile/ProfileMenu.tsx:490 1423 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." 1424 msgstr "" ··· 1427 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours." 1428 msgstr "" 1429 1430 + #: src/screens/Profile/Sections/Labels.tsx:202 1431 msgid "Blocking does not prevent this labeler from placing labels on your account." 1432 msgstr "" 1433 ··· 1448 msgid "Bluesky" 1449 msgstr "" 1450 1451 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:686 1452 msgid "Bluesky cannot confirm the authenticity of the claimed date." 1453 msgstr "" 1454 ··· 1510 msgid "Blur images and filter from feeds" 1511 msgstr "" 1512 1513 + #: src/screens/Onboarding/index.tsx:43 1514 #: src/screens/Onboarding/state.ts:104 1515 msgid "Books" 1516 msgstr "" ··· 1741 msgid "Chat" 1742 msgstr "" 1743 1744 + #: src/screens/Messages/components/RequestButtons.tsx:77 1745 + #: src/screens/Messages/components/RequestButtons.tsx:299 1746 msgctxt "toast" 1747 msgid "Chat deleted" 1748 msgstr "" ··· 1827 msgid "Choose Post Languages" 1828 msgstr "" 1829 1830 + #: src/screens/Onboarding/StepFinished/index.tsx:424 1831 msgid "Choose the algorithms that power your custom feeds." 1832 msgstr "" 1833 ··· 1900 msgid "Click to retry failed message" 1901 msgstr "" 1902 1903 + #: src/screens/Onboarding/index.tsx:45 1904 msgid "Climate" 1905 msgstr "" 1906 ··· 2037 msgid "Color theme" 2038 msgstr "" 2039 2040 + #: src/screens/Onboarding/index.tsx:51 2041 #: src/screens/Onboarding/state.ts:105 2042 msgid "Comedy" 2043 msgstr "" 2044 2045 + #: src/screens/Onboarding/index.tsx:37 2046 #: src/screens/Onboarding/state.ts:106 2047 msgid "Comics" 2048 msgstr "" ··· 2053 msgid "Community Guidelines" 2054 msgstr "" 2055 2056 + #: src/screens/Onboarding/StepFinished/index.tsx:339 2057 + #: src/screens/Onboarding/StepFinished/index.tsx:437 2058 msgid "Complete onboarding and start using your account" 2059 msgstr "" 2060 ··· 2243 msgid "Conversation deleted" 2244 msgstr "" 2245 2246 + #: src/screens/Messages/components/ChatListItem.tsx:199 2247 msgid "Conversation deleted" 2248 msgstr "" 2249 2250 + #: src/screens/Onboarding/index.tsx:54 2251 msgid "Cooking" 2252 msgstr "" 2253 ··· 2256 msgstr "" 2257 2258 #: src/components/dms/MessageContextMenu.tsx:55 2259 + #: src/components/PostControls/DiscoverDebug.tsx:36 2260 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:235 2261 #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:72 2262 #: src/lib/sharing.ts:25 2263 #: src/lib/sharing.ts:41 ··· 2302 msgid "Copy DID" 2303 msgstr "" 2304 2305 + #: src/screens/Settings/components/ChangeHandleDialog.tsx:433 2306 msgid "Copy host" 2307 msgstr "" 2308 ··· 2346 msgid "Copy post at:// URI" 2347 msgstr "" 2348 2349 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:477 2350 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:479 2351 msgid "Copy post text" 2352 msgstr "" 2353 ··· 2355 msgid "Copy QR code" 2356 msgstr "" 2357 2358 + #: src/screens/Settings/components/ChangeHandleDialog.tsx:454 2359 msgid "Copy TXT record value" 2360 msgstr "" 2361 ··· 2431 msgid "Create a starter pack for me" 2432 msgstr "" 2433 2434 #: src/components/WelcomeModal.tsx:155 2435 #: src/components/WelcomeModal.tsx:163 2436 #: src/view/com/auth/SplashScreen.tsx:72 ··· 2498 msgid "Creator has been blocked" 2499 msgstr "" 2500 2501 + #: src/screens/Onboarding/index.tsx:39 2502 #: src/screens/Onboarding/state.ts:107 2503 msgid "Culture" 2504 msgstr "" ··· 2567 msgstr "" 2568 2569 #: src/components/dms/MessageContextMenu.tsx:185 2570 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:729 2571 #: src/screens/Messages/components/ChatStatusInfo.tsx:55 2572 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:280 2573 #: src/screens/Settings/AppPasswords.tsx:212 ··· 2594 msgid "Delete app password?" 2595 msgstr "" 2596 2597 + #: src/screens/Messages/components/RequestButtons.tsx:311 2598 + #: src/screens/Messages/components/RequestButtons.tsx:317 2599 msgid "Delete chat" 2600 msgstr "" 2601 ··· 2605 2606 #: src/components/dms/ReportDialog.tsx:368 2607 #: src/components/dms/ReportDialog.tsx:371 2608 + #: src/screens/Messages/components/RequestButtons.tsx:134 2609 + #: src/screens/Messages/components/RequestButtons.tsx:137 2610 msgid "Delete conversation" 2611 msgstr "" 2612 ··· 2635 msgid "Delete my account" 2636 msgstr "" 2637 2638 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:710 2639 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:712 2640 #: src/view/com/composer/Composer.tsx:966 2641 msgid "Delete post" 2642 msgstr "" ··· 2654 msgid "Delete this list?" 2655 msgstr "" 2656 2657 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:724 2658 msgid "Delete this post?" 2659 msgstr "" 2660 ··· 2663 msgstr "" 2664 2665 #: src/components/dms/MessagesListHeader.tsx:121 2666 + #: src/screens/Messages/components/ChatListItem.tsx:131 2667 msgid "Deleted Account" 2668 msgstr "" 2669 ··· 2674 msgid "Deleted list" 2675 msgstr "" 2676 2677 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:436 2678 #: src/screens/Profile/Header/EditProfileDialog.tsx:363 2679 #: src/screens/Profile/Header/EditProfileDialog.tsx:370 2680 msgid "Description" ··· 2685 msgid "Descriptive alt text" 2686 msgstr "" 2687 2688 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:614 2689 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:624 2690 msgid "Detach quote" 2691 msgstr "" 2692 2693 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:760 2694 msgid "Detach quote post?" 2695 msgstr "" 2696 ··· 2813 msgid "Display name" 2814 msgstr "" 2815 2816 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:23 2817 msgid "Ditch the trolls and clickbait. Find real people and conversations that matter to you." 2818 msgstr "" 2819 ··· 2860 #: src/components/Select/index.tsx:192 2861 #: src/screens/Onboarding/StepProfile/index.tsx:333 2862 #: src/screens/Onboarding/StepProfile/index.tsx:336 2863 + #: src/screens/Settings/components/AddAppPasswordDialog.tsx:214 2864 + #: src/screens/Settings/components/AddAppPasswordDialog.tsx:221 2865 #: src/view/com/auth/server-input/index.tsx:232 2866 #: src/view/com/auth/server-input/index.tsx:233 2867 #: src/view/com/composer/labels/LabelsBtn.tsx:223 ··· 2890 msgid "Double tap to close the dialog" 2891 msgstr "" 2892 2893 + #: src/screens/VideoFeed/index.tsx:1087 2894 msgid "Double tap to like" 2895 msgstr "" 2896 ··· 2903 msgid "Download CAR file" 2904 msgstr "" 2905 2906 + #: src/view/com/composer/text-input/TextInput.web.tsx:375 2907 msgid "Drop to add images" 2908 msgstr "" 2909 ··· 2927 msgid "E.g. artistic nudes." 2928 msgstr "" 2929 2930 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:353 2931 msgid "e.g. Great Posters" 2932 msgstr "" 2933 2934 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:354 2935 + msgid "e.g. Spammers" 2936 + msgstr "" 2937 + 2938 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:357 2939 + msgid "e.g. The posters who never miss." 2940 + msgstr "" 2941 + 2942 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:358 2943 + msgid "e.g. Users that repeatedly reply with ads." 2944 msgstr "" 2945 2946 #: src/screens/Settings/AccountSettings.tsx:145 ··· 2972 msgid "Edit image" 2973 msgstr "" 2974 2975 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:691 2976 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:704 2977 msgid "Edit interaction settings" 2978 msgstr "" 2979 ··· 3042 msgid "Edit your starter pack" 3043 msgstr "" 3044 3045 + #: src/screens/Onboarding/index.tsx:44 3046 #: src/screens/Onboarding/state.ts:109 3047 msgid "Education" 3048 msgstr "" ··· 3332 msgid "Expand post text" 3333 msgstr "" 3334 3335 + #: src/screens/VideoFeed/index.tsx:972 3336 msgid "Expands or collapses post text" 3337 msgstr "" 3338 ··· 3411 msgid "External Media Preferences" 3412 msgstr "" 3413 3414 + #: src/screens/Messages/components/RequestButtons.tsx:217 3415 msgctxt "toast" 3416 msgid "Failed to accept chat" 3417 msgstr "" ··· 3442 msgid "Failed to create starter pack" 3443 msgstr "" 3444 3445 + #: src/screens/Messages/components/RequestButtons.tsx:63 3446 + #: src/screens/Messages/components/RequestButtons.tsx:286 3447 msgctxt "toast" 3448 msgid "Failed to delete chat" 3449 msgstr "" ··· 3452 msgid "Failed to delete message" 3453 msgstr "" 3454 3455 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:204 3456 msgid "Failed to delete post, please try again" 3457 msgstr "" 3458 ··· 3566 msgid "Failed to submit appeal, please try again." 3567 msgstr "" 3568 3569 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:224 3570 msgid "Failed to toggle thread mute, please try again" 3571 msgstr "" 3572 ··· 3645 msgid "Feedback" 3646 msgstr "" 3647 3648 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:275 3649 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:293 3650 msgctxt "toast" 3651 msgid "Feedback sent to feed operator" 3652 msgstr "" ··· 3704 msgid "Filter who you receive notifications from" 3705 msgstr "" 3706 3707 + #: src/screens/Onboarding/StepFinished/index.tsx:345 3708 + #: src/screens/Onboarding/StepFinished/index.tsx:440 3709 msgid "Finalizing" 3710 msgstr "" 3711 ··· 3729 msgid "Find posts, users, and feeds on Bluesky" 3730 msgstr "" 3731 3732 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:21 3733 msgid "Find your people" 3734 msgstr "" 3735 ··· 3737 msgid "Finish" 3738 msgstr "" 3739 3740 + #: src/screens/Onboarding/index.tsx:48 3741 msgid "Fitness" 3742 msgstr "" 3743 ··· 3756 msgid "Flat White" 3757 msgstr "" 3758 3759 + #: src/screens/Onboarding/StepFinished/index.tsx:420 3760 msgid "Flexible" 3761 msgstr "" 3762 ··· 3766 #: src/components/ProfileHoverCard/index.web.tsx:507 3767 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:131 3768 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:252 3769 + #: src/screens/VideoFeed/index.tsx:856 3770 msgid "Follow" 3771 msgstr "" 3772 ··· 3780 msgid "Follow {0}" 3781 msgstr "" 3782 3783 + #: src/screens/VideoFeed/index.tsx:833 3784 msgid "Follow {handle}" 3785 msgstr "" 3786 ··· 3855 #: src/components/ProfileHoverCard/index.web.tsx:506 3856 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:134 3857 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:248 3858 + #: src/screens/VideoFeed/index.tsx:854 3859 msgid "Following" 3860 msgstr "" 3861 ··· 3870 msgid "Following {0}" 3871 msgstr "" 3872 3873 + #: src/screens/VideoFeed/index.tsx:832 3874 msgid "Following {handle}" 3875 msgstr "" 3876 ··· 3900 msgid "Font size" 3901 msgstr "" 3902 3903 + #: src/screens/Onboarding/index.tsx:53 3904 #: src/screens/Onboarding/state.ts:110 3905 msgid "Food" 3906 msgstr "" ··· 3913 msgid "For security reasons, we'll need to send a confirmation code to your email address." 3914 msgstr "" 3915 3916 + #: src/screens/Settings/components/AddAppPasswordDialog.tsx:208 3917 msgid "For security reasons, you won't be able to view this again. If you lose this app password, you'll need to generate a new one." 3918 msgstr "" 3919 ··· 3930 msgid "Forever" 3931 msgstr "" 3932 3933 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:30 3934 msgid "Forget the noise" 3935 msgstr "" 3936 ··· 3947 msgid "Forgot?" 3948 msgstr "" 3949 3950 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:12 3951 msgid "Free your feed" 3952 msgstr "" 3953 ··· 4065 #: src/screens/ProfileList/components/ErrorScreen.tsx:34 4066 #: src/screens/ProfileList/components/ErrorScreen.tsx:40 4067 #: src/screens/VideoFeed/components/Header.tsx:163 4068 + #: src/screens/VideoFeed/index.tsx:1148 4069 + #: src/screens/VideoFeed/index.tsx:1152 4070 #: src/view/com/auth/LoggedOut.tsx:72 4071 #: src/view/screens/NotFound.tsx:57 4072 msgid "Go back" ··· 4085 #: src/components/dms/ReportDialog.tsx:197 4086 #: src/components/ReportDialog/SelectReportOptionView.tsx:81 4087 #: src/components/ReportDialog/SubmitView.tsx:110 4088 + #: src/screens/Onboarding/Layout.tsx:115 4089 + #: src/screens/Onboarding/Layout.tsx:211 4090 #: src/screens/Signup/BackNextButtons.tsx:35 4091 msgid "Go back to previous step" 4092 msgstr "" ··· 4132 msgid "Go to account settings" 4133 msgstr "" 4134 4135 + #: src/screens/Messages/components/ChatListItem.tsx:364 4136 msgid "Go to conversation with {0}" 4137 msgstr "" 4138 ··· 4232 msgid "Hidden" 4233 msgstr "" 4234 4235 + #: src/screens/VideoFeed/index.tsx:630 4236 msgid "Hidden by your moderation settings." 4237 msgstr "" 4238 ··· 4244 #: src/components/interstitials/TrendingVideos.tsx:138 4245 #: src/components/moderation/ContentHider.tsx:203 4246 #: src/components/moderation/LabelPreference.tsx:140 4247 + #: src/components/moderation/PostHider.tsx:137 4248 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:740 4249 #: src/lib/moderation/useLabelBehaviorDescription.ts:18 4250 #: src/lib/moderation/useLabelBehaviorDescription.ts:23 4251 #: src/lib/moderation/useLabelBehaviorDescription.ts:28 ··· 4263 msgid "Hide customization options" 4264 msgstr "" 4265 4266 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:571 4267 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:577 4268 msgid "Hide post for me" 4269 msgstr "" 4270 4271 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:588 4272 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:598 4273 msgid "Hide reply for everyone" 4274 msgstr "" 4275 4276 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:570 4277 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:576 4278 msgid "Hide reply for me" 4279 msgstr "" 4280 ··· 4282 msgid "Hide this card" 4283 msgstr "" 4284 4285 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:735 4286 msgid "Hide this post?" 4287 msgstr "" 4288 4289 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:735 4290 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:770 4291 msgid "Hide this reply?" 4292 msgstr "" 4293 ··· 4315 msgstr "" 4316 4317 #: src/components/moderation/ContentHider.tsx:154 4318 + #: src/components/moderation/PostHider.tsx:91 4319 msgid "Hides the content" 4320 msgstr "" 4321 ··· 4412 msgid "If you need to update your email, <0>click here</0>." 4413 msgstr "" 4414 4415 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:726 4416 msgid "If you remove this post, you won't be able to recover it." 4417 msgstr "" 4418 ··· 4560 msgid "Invalid handle. Please try a different one." 4561 msgstr "" 4562 4563 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:358 4564 + msgctxt "toast" 4565 + msgid "Invalid interaction settings." 4566 + msgstr "" 4567 + 4568 #: src/components/moderation/ReportDialog/index.tsx:73 4569 msgid "Invalid report subject" 4570 msgstr "" ··· 4618 msgid "Jobs" 4619 msgstr "" 4620 4621 #: src/screens/StarterPack/StarterPackLandingScreen.tsx:210 4622 #: src/screens/StarterPack/StarterPackLandingScreen.tsx:216 4623 #: src/screens/StarterPack/StarterPackScreen.tsx:466 ··· 4630 msgid "Join the conversation" 4631 msgstr "" 4632 4633 + #: src/screens/Onboarding/index.tsx:34 4634 #: src/screens/Onboarding/state.ts:112 4635 msgid "Journalism" 4636 msgstr "" ··· 4668 msgid "Labels added" 4669 msgstr "" 4670 4671 + #: src/screens/Profile/Sections/Labels.tsx:193 4672 msgid "Labels are annotations on users and content. They can be used to hide, warn, and categorize the network." 4673 msgstr "" 4674 ··· 4747 msgid "Learn more about these changes and how to share your thoughts with us by reading our blog post." 4748 msgstr "" 4749 4750 + #: src/components/moderation/PostHider.tsx:113 4751 #: src/components/moderation/ScreenHider.tsx:133 4752 msgid "Learn more about this warning" 4753 msgstr "" ··· 4811 msgid "Let's get your password reset!" 4812 msgstr "" 4813 4814 + #: src/screens/Onboarding/StepFinished/index.tsx:347 4815 + #: src/screens/Onboarding/StepFinished/index.tsx:440 4816 msgid "Let's go!" 4817 msgstr "" 4818 ··· 4897 msgid "Likes of your reposts notifications" 4898 msgstr "" 4899 4900 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:469 4901 msgid "Likes on this post" 4902 msgstr "" 4903 ··· 4910 msgid "List" 4911 msgstr "" 4912 4913 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:380 4914 msgid "List avatar" 4915 msgstr "" 4916 ··· 4941 msgid "List deleted" 4942 msgstr "" 4943 4944 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:429 4945 msgid "List description" 4946 msgstr "" 4947 4948 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:449 4949 msgid "List description is too long. {DESCRIPTION_MAX_GRAPHEMES, plural, other {The maximum number of characters is #.}}" 4950 msgstr "" 4951 ··· 4957 msgid "List Hidden" 4958 msgstr "" 4959 4960 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:421 4961 msgid "List must have a name." 4962 msgstr "" 4963 ··· 4966 msgid "List muted" 4967 msgstr "" 4968 4969 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:393 4970 msgid "List name" 4971 msgstr "" 4972 4973 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:413 4974 msgid "List name is too long. {DISPLAY_NAME_MAX_GRAPHEMES, plural, other {The maximum number of characters is #.}}" 4975 msgstr "" 4976 ··· 5162 msgid "Message deleted" 5163 msgstr "" 5164 5165 + #: src/screens/Messages/components/ChatListItem.tsx:200 5166 msgid "Message deleted" 5167 msgstr "" 5168 ··· 5314 msgid "Mute {tag}" 5315 msgstr "" 5316 5317 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:653 5318 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:659 5319 #: src/view/com/profile/ProfileMenu.tsx:380 5320 #: src/view/com/profile/ProfileMenu.tsx:387 5321 msgid "Mute account" ··· 5367 msgid "Mute this word until you unmute it" 5368 msgstr "" 5369 5370 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:537 5371 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:541 5372 msgid "Mute thread" 5373 msgstr "" 5374 5375 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:551 5376 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:553 5377 msgid "Mute words & tags" 5378 msgstr "" 5379 ··· 5411 msgid "My Feeds" 5412 msgstr "" 5413 5414 + #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:399 5415 msgid "Name" 5416 msgstr "" 5417 ··· 5426 msgid "Name or Description Violates Community Standards" 5427 msgstr "" 5428 5429 + #: src/screens/Onboarding/index.tsx:35 5430 #: src/screens/Onboarding/state.ts:115 5431 msgid "Nature" 5432 msgstr "" ··· 5458 msgid "Need to report a copyright violation?" 5459 msgstr "" 5460 5461 + #: src/screens/Onboarding/StepFinished/index.tsx:408 5462 msgid "Never lose access to your followers or data." 5463 msgstr "" 5464 ··· 5573 msgid "Newest replies first" 5574 msgstr "" 5575 5576 + #: src/screens/Onboarding/index.tsx:33 5577 #: src/screens/Onboarding/state.ts:116 5578 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:238 5579 msgid "News" ··· 5585 #: src/screens/Login/LoginForm.tsx:350 5586 #: src/screens/Login/SetNewPasswordForm.tsx:182 5587 #: src/screens/Login/SetNewPasswordForm.tsx:188 5588 + #: src/screens/Onboarding/StepFinished/index.tsx:340 5589 + #: src/screens/Onboarding/StepFinished/index.tsx:349 5590 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:157 5591 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:165 5592 #: src/screens/Signup/BackNextButtons.tsx:67 ··· 5606 msgid "Next image" 5607 msgstr "" 5608 5609 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:32 5610 msgid "No ads, no invasive tracking, no engagement traps. Bluesky respects your time and attention." 5611 msgstr "" 5612 ··· 5645 msgid "No longer following {0}" 5646 msgstr "" 5647 5648 + #: src/screens/Messages/components/ChatListItem.tsx:142 5649 msgid "No messages yet" 5650 msgstr "" 5651 5652 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:14 5653 msgid "No more doomscrolling junk-filled algorithms. Find feeds that work for you, not against you." 5654 msgstr "" 5655 ··· 5871 msgstr "" 5872 5873 #: src/screens/Login/PasswordUpdatedForm.tsx:37 5874 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:691 5875 msgid "Okay" 5876 msgstr "" 5877 ··· 5945 msgid "Oops!" 5946 msgstr "" 5947 5948 + #: src/screens/Onboarding/StepFinished/index.tsx:404 5949 msgid "Open" 5950 msgstr "" 5951 ··· 5953 msgid "Open avatar creator" 5954 msgstr "" 5955 5956 + #: src/screens/Messages/components/ChatListItem.tsx:374 5957 + #: src/screens/Messages/components/ChatListItem.tsx:378 5958 msgid "Open conversation options" 5959 msgstr "" 5960 ··· 6236 msgid "Person toggle" 6237 msgstr "" 6238 6239 + #: src/screens/Onboarding/index.tsx:41 6240 #: src/screens/Onboarding/state.ts:117 6241 msgid "Pets" 6242 msgstr "" ··· 6268 msgid "Pin to Home" 6269 msgstr "" 6270 6271 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:445 6272 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:452 6273 msgid "Pin to your profile" 6274 msgstr "" 6275 ··· 6465 msgid "Please write your message below:" 6466 msgstr "" 6467 6468 + #: src/screens/Onboarding/index.tsx:47 6469 #: src/screens/Onboarding/state.ts:119 6470 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:232 6471 msgid "Politics" ··· 6475 msgid "Porn" 6476 msgstr "" 6477 6478 + #: src/screens/PostThread/index.tsx:500 6479 msgctxt "description" 6480 msgid "Post" 6481 msgstr "" ··· 6501 msgid "Post by @{0}" 6502 msgstr "" 6503 6504 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:184 6505 msgctxt "toast" 6506 msgid "Post deleted" 6507 msgstr "" ··· 6510 msgid "Post failed to upload. Please check your Internet connection and try again." 6511 msgstr "" 6512 6513 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:133 6514 #: src/screens/PostThread/components/ThreadItemPost.tsx:111 6515 #: src/screens/PostThread/components/ThreadItemTreePost.tsx:107 6516 + #: src/screens/VideoFeed/index.tsx:534 6517 msgid "Post has been deleted" 6518 msgstr "" 6519 ··· 6676 msgid "Profile updated" 6677 msgstr "" 6678 6679 + #: src/screens/Onboarding/StepFinished/index.tsx:390 6680 msgid "Public" 6681 msgstr "" 6682 ··· 6747 msgid "Quote post" 6748 msgstr "" 6749 6750 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:313 6751 msgid "Quote post was re-attached" 6752 msgstr "" 6753 6754 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:312 6755 msgid "Quote post was successfully detached" 6756 msgstr "" 6757 ··· 6773 msgid "Quotes" 6774 msgstr "" 6775 6776 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:453 6777 msgid "Quotes of this post" 6778 msgstr "" 6779 ··· 6781 msgid "Rate limit exceeded – you've tried to change your handle too many times in a short period. Please wait a minute before trying again." 6782 msgstr "" 6783 6784 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:613 6785 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:623 6786 msgid "Re-attach quote" 6787 msgstr "" 6788 ··· 6803 msgid "Read blog post" 6804 msgstr "" 6805 6806 + #: src/screens/VideoFeed/index.tsx:973 6807 msgid "Read less" 6808 msgstr "" 6809 6810 + #: src/screens/VideoFeed/index.tsx:973 6811 msgid "Read more" 6812 msgstr "" 6813 ··· 6876 msgstr "" 6877 6878 #. Reject a chat request, this opens a menu with options 6879 + #: src/screens/Messages/components/RequestButtons.tsx:122 6880 msgid "Reject" 6881 msgstr "" 6882 6883 + #: src/screens/Messages/components/RequestButtons.tsx:111 6884 msgid "Reject chat request" 6885 msgstr "" 6886 ··· 7130 msgid "Reply sorting" 7131 msgstr "" 7132 7133 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:344 7134 msgctxt "toast" 7135 msgid "Reply visibility updated" 7136 msgstr "" 7137 7138 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:343 7139 msgid "Reply was successfully hidden" 7140 msgstr "" 7141 ··· 7153 #: src/components/dms/ConvoMenu.tsx:255 7154 #: src/components/dms/ConvoMenu.tsx:258 7155 #: src/components/dms/ReportConversationPrompt.tsx:17 7156 + #: src/screens/Messages/components/RequestButtons.tsx:153 7157 + #: src/screens/Messages/components/RequestButtons.tsx:156 7158 msgid "Report conversation" 7159 msgstr "" 7160 ··· 7178 msgid "Report message" 7179 msgstr "" 7180 7181 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:679 7182 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:681 7183 msgid "Report post" 7184 msgstr "" 7185 ··· 7275 msgid "Reposts" 7276 msgstr "" 7277 7278 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:435 7279 msgid "Reposts of this post" 7280 msgstr "" 7281 ··· 7398 #: src/screens/Profile/ProfileFeed/index.tsx:93 7399 #: src/screens/ProfileList/components/ErrorScreen.tsx:35 7400 #: src/screens/Settings/components/ChangeHandleDialog.tsx:569 7401 + #: src/screens/VideoFeed/index.tsx:1149 7402 #: src/view/screens/NotFound.tsx:60 7403 msgid "Returns to previous page" 7404 msgstr "" ··· 7490 msgid "Say hello!" 7491 msgstr "" 7492 7493 + #: src/screens/Onboarding/index.tsx:46 7494 #: src/screens/Onboarding/state.ts:120 7495 msgid "Science" 7496 msgstr "" ··· 7967 msgid "Share anyway" 7968 msgstr "" 7969 7970 + #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:161 7971 + #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:164 7972 msgid "Share author DID" 7973 msgstr "" 7974 ··· 7983 msgid "Share link dialog" 7984 msgstr "" 7985 7986 + #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:152 7987 + #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:155 7988 msgid "Share post at:// URI" 7989 msgstr "" 7990 ··· 8026 8027 #: src/components/moderation/ContentHider.tsx:203 8028 #: src/components/moderation/LabelPreference.tsx:142 8029 + #: src/components/moderation/PostHider.tsx:137 8030 msgid "Show" 8031 msgstr "" 8032 ··· 8037 #: src/components/moderation/ScreenHider.tsx:178 8038 #: src/components/moderation/ScreenHider.tsx:181 8039 #: src/screens/List/ListHiddenScreen.tsx:190 8040 + #: src/screens/VideoFeed/index.tsx:633 8041 + #: src/screens/VideoFeed/index.tsx:639 8042 msgid "Show anyway" 8043 msgstr "" 8044 ··· 8055 msgid "Show customization options" 8056 msgstr "" 8057 8058 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:508 8059 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:510 8060 msgid "Show less like this" 8061 msgstr "" 8062 ··· 8068 msgid "Show More" 8069 msgstr "" 8070 8071 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:500 8072 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:502 8073 msgid "Show more like this" 8074 msgstr "" 8075 ··· 8099 msgid "Show replies by people you follow before all other replies" 8100 msgstr "" 8101 8102 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:587 8103 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:597 8104 msgid "Show reply for everyone" 8105 msgstr "" 8106 ··· 8122 msgid "Show warning and filter from feeds" 8123 msgstr "" 8124 8125 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:627 8126 msgid "Shows information about when this post was created" 8127 msgstr "" 8128 ··· 8131 msgstr "" 8132 8133 #: src/components/moderation/ContentHider.tsx:155 8134 + #: src/components/moderation/PostHider.tsx:91 8135 msgid "Shows the content" 8136 msgstr "" 8137 ··· 8181 msgid "Sign in to Bluesky or create a new account" 8182 msgstr "" 8183 8184 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:486 8185 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:488 8186 msgid "Sign in to view post" 8187 msgstr "" 8188 ··· 8221 msgid "Similar accounts" 8222 msgstr "" 8223 8224 + #: src/screens/Onboarding/StepFinished/index.tsx:306 8225 + #: src/screens/Onboarding/StepFinished/index.tsx:328 8226 #: src/screens/Onboarding/StepInterests/index.tsx:240 8227 #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:222 8228 #: src/screens/StarterPack/Wizard/index.tsx:218 8229 msgid "Skip" 8230 msgstr "" 8231 8232 + #: src/screens/Onboarding/StepFinished/index.tsx:299 8233 + #: src/screens/Onboarding/StepFinished/index.tsx:325 8234 msgid "Skip introduction and start using your account" 8235 msgstr "" 8236 ··· 8251 msgid "Social media you control." 8252 msgstr "" 8253 8254 + #: src/screens/Onboarding/index.tsx:50 8255 #: src/screens/Onboarding/state.ts:108 8256 msgid "Software Dev" 8257 msgstr "" ··· 8272 msgid "Someone reacted {0}" 8273 msgstr "" 8274 8275 + #: src/screens/Messages/components/ChatListItem.tsx:244 8276 msgid "Someone reacted {0} to {1}" 8277 msgstr "" 8278 ··· 8294 8295 #: src/components/ReportDialog/index.tsx:54 8296 #: src/screens/Moderation/index.tsx:112 8297 + #: src/screens/Profile/Sections/Labels.tsx:183 8298 msgid "Something went wrong, please try again." 8299 msgstr "" 8300 ··· 8348 msgid "Spam; excessive mentions or replies" 8349 msgstr "" 8350 8351 + #: src/screens/Onboarding/index.tsx:40 8352 #: src/screens/Onboarding/state.ts:121 8353 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:230 8354 msgid "Sports" ··· 8453 msgid "Subscribe" 8454 msgstr "" 8455 8456 + #: src/screens/Profile/Sections/Labels.tsx:230 8457 msgid "Subscribe to @{0} to use these labels:" 8458 msgstr "" 8459 ··· 8593 msgid "Teach our algorithm what you like" 8594 msgstr "" 8595 8596 + #: src/screens/Onboarding/index.tsx:49 8597 #: src/screens/Onboarding/state.ts:122 8598 msgid "Tech" 8599 msgstr "" ··· 8689 msgid "That's all, folks!" 8690 msgstr "" 8691 8692 + #: src/screens/VideoFeed/index.tsx:1121 8693 msgid "That's everything!" 8694 msgstr "" 8695 ··· 8758 8759 #: src/components/ageAssurance/useAgeAssuranceCopy.ts:14 8760 msgid "The laws in your location require you to verify you're an adult to access certain features. Tap to learn more." 8761 msgstr "" 8762 8763 #: src/view/com/composer/select-language/SuggestedLanguage.tsx:119 ··· 8863 msgid "There was an issue updating your feeds, please check your internet connection and try again." 8864 msgstr "" 8865 8866 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:390 8867 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:403 8868 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:413 8869 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:90 8870 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:101 8871 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:101 ··· 8968 msgid "This content is not viewable without a Bluesky account." 8969 msgstr "" 8970 8971 + #: src/screens/Messages/components/ChatListItem.tsx:366 8972 msgid "This conversation is with a deleted or a deactivated account. Press for options" 8973 msgstr "" 8974 ··· 9031 msgid "This label was applied by you." 9032 msgstr "" 9033 9034 + #: src/screens/Profile/Sections/Labels.tsx:217 9035 msgid "This labeler hasn't declared what labels it publishes, and may not be active." 9036 msgstr "" 9037 ··· 9055 msgid "This moderation service is unavailable. See below for more details. If this issue persists, contact us." 9056 msgstr "" 9057 9058 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:667 9059 msgid "This post claims to have been created on <0>{0}</0>, but was first seen by Bluesky on <1>{1}</1>." 9060 msgstr "" 9061 ··· 9063 msgid "This post has an unknown type of threadgate on it. Your app may be out of date." 9064 msgstr "" 9065 9066 + #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:142 9067 msgid "This post is only visible to logged-in users." 9068 msgstr "" 9069 ··· 9071 msgid "This post was deleted by its author" 9072 msgstr "" 9073 9074 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:737 9075 msgid "This post will be hidden from feeds and threads. This cannot be undone." 9076 msgstr "" 9077 ··· 9083 msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in." 9084 msgstr "" 9085 9086 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:772 9087 msgid "This reply will be sorted into a hidden section at the bottom of your thread and will mute notifications for subsequent replies - both for yourself and others." 9088 msgstr "" 9089 ··· 9144 msgid "This will remove @{0} from the quick access list." 9145 msgstr "" 9146 9147 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:762 9148 msgid "This will remove your post from this quote post for all users, and replace it with a placeholder." 9149 msgstr "" 9150 ··· 9223 9224 #: src/components/dms/MessageContextMenu.tsx:137 9225 #: src/components/dms/MessageContextMenu.tsx:139 9226 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:469 9227 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:471 9228 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:589 9229 + #: src/screens/PostThread/components/ThreadItemAnchor.tsx:592 9230 msgid "Translate" 9231 msgstr "" 9232 ··· 9373 msgid "Unfollow account" 9374 msgstr "" 9375 9376 + #: src/screens/VideoFeed/index.tsx:837 9377 msgid "Unfollows the user" 9378 msgstr "" 9379 ··· 9414 msgid "Unmute {tag}" 9415 msgstr "" 9416 9417 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:652 9418 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:658 9419 #: src/view/com/profile/ProfileMenu.tsx:379 9420 #: src/view/com/profile/ProfileMenu.tsx:385 9421 msgid "Unmute account" ··· 9430 msgid "Unmute list" 9431 msgstr "" 9432 9433 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:537 9434 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:541 9435 msgid "Unmute thread" 9436 msgstr "" 9437 ··· 9459 msgid "Unpin from home" 9460 msgstr "" 9461 9462 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:444 9463 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:451 9464 msgid "Unpin from profile" 9465 msgstr "" 9466 ··· 9539 msgid "Update your email" 9540 msgstr "" 9541 9542 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:317 9543 msgctxt "toast" 9544 msgid "Updating quote attachment failed" 9545 msgstr "" 9546 9547 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:363 9548 msgctxt "toast" 9549 msgid "Updating reply visibility failed" 9550 msgstr "" ··· 9825 msgid "Video from {0}: {text}" 9826 msgstr "" 9827 9828 + #: src/screens/Onboarding/index.tsx:52 9829 #: src/screens/Onboarding/state.ts:111 9830 #: src/screens/Search/modules/ExploreTrendingTopics.tsx:234 9831 msgid "Video Games" 9832 msgstr "" 9833 9834 + #: src/screens/VideoFeed/index.tsx:1079 9835 msgid "Video is paused" 9836 msgstr "" 9837 9838 + #: src/screens/VideoFeed/index.tsx:1079 9839 msgid "Video is playing" 9840 msgstr "" 9841 ··· 9875 #: src/components/ProfileCard.tsx:124 9876 #: src/screens/Profile/components/ProfileFeedHeader.tsx:454 9877 #: src/screens/Search/components/SearchProfileCard.tsx:36 9878 + #: src/screens/VideoFeed/index.tsx:796 9879 #: src/view/com/notifications/NotificationFeedItem.tsx:599 9880 msgid "View {0}'s profile" 9881 msgstr "" ··· 9897 msgstr "" 9898 9899 #: src/components/ReportDialog/SelectReportOptionView.tsx:140 9900 + #: src/screens/VideoFeed/index.tsx:661 9901 + #: src/screens/VideoFeed/index.tsx:679 9902 msgid "View details" 9903 msgstr "" 9904 ··· 9984 msgstr "" 9985 9986 #: src/view/com/util/images/AutoSizedImage.tsx:206 9987 + #: src/view/com/util/images/AutoSizedImage.tsx:229 9988 msgid "Views full image" 9989 msgstr "" 9990 ··· 10056 msgid "We have sent another verification email to <0>{0}</0>." 10057 msgstr "" 10058 10059 + #: src/screens/Onboarding/StepFinished/index.tsx:382 10060 msgid "We hope you have a wonderful time. Remember, Bluesky is:" 10061 msgstr "" 10062 ··· 10291 msgid "Write your reply" 10292 msgstr "" 10293 10294 + #: src/screens/Onboarding/index.tsx:38 10295 #: src/screens/Onboarding/state.ts:124 10296 msgid "Writers" 10297 msgstr "" ··· 10318 msgid "Yes, delete this starter pack" 10319 msgstr "" 10320 10321 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:765 10322 msgid "Yes, detach" 10323 msgstr "" 10324 10325 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:775 10326 msgid "Yes, hide" 10327 msgstr "" 10328 ··· 10410 10411 #: src/screens/Messages/Settings.tsx:116 10412 msgid "You can continue ongoing conversations regardless of which setting you choose." 10413 + msgstr "" 10414 + 10415 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:350 10416 + msgctxt "toast" 10417 + msgid "You can hide a maximum of {MAX_HIDDEN_REPLIES} replies." 10418 msgstr "" 10419 10420 #: src/components/dialogs/nuxs/ActivitySubscriptions.tsx:148 ··· 10641 msgid "You reacted {0}" 10642 msgstr "" 10643 10644 + #: src/screens/Messages/components/ChatListItem.tsx:221 10645 msgid "You reacted {0} to {1}" 10646 msgstr "" 10647 ··· 10654 msgid "You will no longer receive notifications for {0}" 10655 msgstr "" 10656 10657 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:217 10658 msgid "You will no longer receive notifications for this thread" 10659 msgstr "" 10660 10661 + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:213 10662 msgid "You will now receive notifications for this thread" 10663 msgstr "" 10664 ··· 10666 msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password." 10667 msgstr "" 10668 10669 + #: src/screens/Messages/components/ChatListItem.tsx:157 10670 msgid "You: {0}" 10671 msgstr "" 10672 10673 + #: src/screens/Messages/components/ChatListItem.tsx:186 10674 msgid "You: {defaultEmbeddedContentMessage}" 10675 msgstr "" 10676 10677 + #: src/screens/Messages/components/ChatListItem.tsx:179 10678 msgid "You: {short}" 10679 msgstr "" 10680 ··· 10706 msgid "You're in line" 10707 msgstr "" 10708 10709 + #: src/screens/Onboarding/StepFinished/index.tsx:379 10710 msgid "You're ready to go!" 10711 msgstr "" 10712 ··· 10748 msgid "You've reached your daily limit for video uploads (too many videos)" 10749 msgstr "" 10750 10751 + #: src/screens/VideoFeed/index.tsx:1130 10752 msgid "You've run out of videos to watch. Maybe it's a good time to take a break?" 10753 msgstr "" 10754 ··· 10878 msgid "Your posts were sent" 10879 msgstr "" 10880 10881 + #: src/screens/Onboarding/StepFinished/index.tsx:394 10882 msgid "Your posts, likes, and blocks are public. Mutes are private." 10883 msgstr "" 10884 ··· 10886 msgid "Your preferred language" 10887 msgstr "" 10888 10889 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.tsx:100 10890 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.web.tsx:53 10891 msgid "Your profile picture" 10892 msgstr "" 10893 10894 + #: src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx:26 10895 msgid "Your profile picture surrounded by concentric circles of other users' profile pictures" 10896 msgstr "" 10897
+1
src/logger/sentry/setup/index.ts
··· 29 * @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace 30 */ 31 attachStacktrace: false, 32 })
··· 29 * @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace 30 */ 31 attachStacktrace: false, 32 + sampleRate: env.IS_INTERNAL ? 1.0 : 0.1, 33 })
+191 -173
src/screens/Messages/components/ChatListItem.tsx
··· 42 import {Link} from '#/components/Link' 43 import {useMenuControl} from '#/components/Menu' 44 import {PostAlerts} from '#/components/moderation/PostAlerts' 45 import {Text} from '#/components/Typography' 46 import {useSimpleVerificationState} from '#/components/verification' 47 import {VerificationCheck} from '#/components/verification/VerificationCheck' 48 import type * as bsky from '#/types/bsky' 49 50 export let ChatListItem = ({ 51 convo, ··· 331 const hasUnread = convo.unreadCount > 0 && !isDeletedAccount 332 333 return ( 334 - <GestureActionView actions={actions}> 335 - <View 336 - onMouseEnter={onMouseEnter} 337 - onMouseLeave={onMouseLeave} 338 - // @ts-expect-error web only 339 - onFocus={onFocus} 340 - onBlur={onMouseLeave} 341 - style={[a.relative, t.atoms.bg]}> 342 <View 343 - style={[ 344 - a.z_10, 345 - a.absolute, 346 - {top: tokens.space.md, left: tokens.space.lg}, 347 - ]}> 348 - <PreviewableUserAvatar 349 - profile={profile} 350 - size={52} 351 - moderation={moderation.ui('avatar')} 352 - /> 353 - </View> 354 355 - <Link 356 - to={`/messages/${convo.id}`} 357 - label={displayName} 358 - accessibilityHint={ 359 - !isDeletedAccount 360 - ? _(msg`Go to conversation with ${profile.handle}`) 361 - : _( 362 - msg`This conversation is with a deleted or a deactivated account. Press for options`, 363 - ) 364 - } 365 - accessibilityActions={ 366 - isNative 367 - ? [ 368 - {name: 'magicTap', label: _(msg`Open conversation options`)}, 369 - {name: 'longpress', label: _(msg`Open conversation options`)}, 370 - ] 371 - : undefined 372 - } 373 - onPress={onPress} 374 - onLongPress={isNative ? onLongPress : undefined} 375 - onAccessibilityAction={onLongPress}> 376 - {({hovered, pressed, focused}) => ( 377 - <View 378 - style={[ 379 - a.flex_row, 380 - isDeletedAccount ? a.align_center : a.align_start, 381 - a.flex_1, 382 - a.px_lg, 383 - a.py_md, 384 - a.gap_md, 385 - (hovered || pressed || focused) && t.atoms.bg_contrast_25, 386 - ]}> 387 - {/* Avatar goes here */} 388 - <View style={{width: 52, height: 52}} /> 389 390 - <View 391 - style={[a.flex_1, a.justify_center, web({paddingRight: 45})]}> 392 - <View style={[a.w_full, a.flex_row, a.align_end, a.pb_2xs]}> 393 - <View style={[a.flex_shrink]}> 394 <Text 395 - emoji 396 numberOfLines={1} 397 style={[ 398 - a.text_md, 399 - t.atoms.text, 400 - a.font_semi_bold, 401 - {lineHeight: 21}, 402 - isDimStyle && t.atoms.text_contrast_medium, 403 - ]}> 404 - {displayName} 405 - </Text> 406 - </View> 407 - {verification.showBadge && ( 408 - <View style={[a.pl_xs, a.self_center]}> 409 - <VerificationCheck 410 - width={14} 411 - verifier={verification.role === 'verifier'} 412 - /> 413 - </View> 414 - )} 415 - {lastMessageSentAt && ( 416 - <View style={[a.pl_xs]}> 417 - <TimeElapsed timestamp={lastMessageSentAt}> 418 - {({timeElapsed}) => ( 419 - <Text 420 - style={[ 421 - a.text_sm, 422 - {lineHeight: 21}, 423 - t.atoms.text_contrast_medium, 424 - web({whiteSpace: 'preserve nowrap'}), 425 - ]}> 426 - &middot; {timeElapsed} 427 - </Text> 428 - )} 429 - </TimeElapsed> 430 - </View> 431 - )} 432 - {(convo.muted || moderation.blocked) && ( 433 - <Text 434 - style={[ 435 a.text_sm, 436 - {lineHeight: 21}, 437 t.atoms.text_contrast_medium, 438 - web({whiteSpace: 'preserve nowrap'}), 439 ]}> 440 - {' '} 441 - &middot;{' '} 442 - <BellStroke 443 - size="xs" 444 - style={[t.atoms.text_contrast_medium]} 445 - /> 446 </Text> 447 )} 448 - </View> 449 450 - {!isDeletedAccount && ( 451 <Text 452 - numberOfLines={1} 453 - style={[a.text_sm, t.atoms.text_contrast_medium, a.pb_xs]}> 454 - @{profile.handle} 455 </Text> 456 - )} 457 458 - <Text 459 - emoji 460 - numberOfLines={2} 461 - style={[ 462 - a.text_sm, 463 - a.leading_snug, 464 - hasUnread ? a.font_semi_bold : t.atoms.text_contrast_high, 465 - isDimStyle && t.atoms.text_contrast_medium, 466 - ]}> 467 - {lastMessage} 468 - </Text> 469 470 - <PostAlerts 471 - modui={moderation.ui('contentList')} 472 - size="lg" 473 - style={[a.pt_xs]} 474 - /> 475 476 - {children} 477 </View> 478 479 - {hasUnread && ( 480 - <View 481 - style={[ 482 - a.absolute, 483 - a.rounded_full, 484 - { 485 - backgroundColor: isDimStyle 486 - ? t.palette.contrast_200 487 - : t.palette.primary_500, 488 - height: 7, 489 - width: 7, 490 - top: 15, 491 - right: 12, 492 - }, 493 - ]} 494 - /> 495 - )} 496 - </View> 497 - )} 498 - </Link> 499 500 - {showMenu && ( 501 - <ConvoMenu 502 - convo={convo} 503 - profile={profile} 504 - control={menuControl} 505 currentScreen="list" 506 - showMarkAsRead={convo.unreadCount > 0} 507 - hideTrigger={isNative} 508 - blockInfo={blockInfo} 509 - style={[ 510 - a.absolute, 511 - a.h_full, 512 - a.self_end, 513 - a.justify_center, 514 - { 515 - right: tokens.space.lg, 516 - opacity: !gtMobile || showActions || menuControl.isOpen ? 1 : 0, 517 - }, 518 - ]} 519 - latestReportableMessage={latestReportableMessage} 520 /> 521 - )} 522 - <LeaveConvoPrompt 523 - control={leaveConvoControl} 524 - convoId={convo.id} 525 - currentScreen="list" 526 - /> 527 - </View> 528 - </GestureActionView> 529 ) 530 }
··· 42 import {Link} from '#/components/Link' 43 import {useMenuControl} from '#/components/Menu' 44 import {PostAlerts} from '#/components/moderation/PostAlerts' 45 + import {createPortalGroup} from '#/components/Portal' 46 import {Text} from '#/components/Typography' 47 import {useSimpleVerificationState} from '#/components/verification' 48 import {VerificationCheck} from '#/components/verification/VerificationCheck' 49 import type * as bsky from '#/types/bsky' 50 + 51 + export const ChatListItemPortal = createPortalGroup() 52 53 export let ChatListItem = ({ 54 convo, ··· 334 const hasUnread = convo.unreadCount > 0 && !isDeletedAccount 335 336 return ( 337 + <ChatListItemPortal.Provider> 338 + <GestureActionView actions={actions}> 339 <View 340 + onMouseEnter={onMouseEnter} 341 + onMouseLeave={onMouseLeave} 342 + // @ts-expect-error web only 343 + onFocus={onFocus} 344 + onBlur={onMouseLeave} 345 + style={[a.relative, t.atoms.bg]}> 346 + <View 347 + style={[ 348 + a.z_10, 349 + a.absolute, 350 + {top: tokens.space.md, left: tokens.space.lg}, 351 + ]}> 352 + <PreviewableUserAvatar 353 + profile={profile} 354 + size={52} 355 + moderation={moderation.ui('avatar')} 356 + /> 357 + </View> 358 + 359 + <Link 360 + to={`/messages/${convo.id}`} 361 + label={displayName} 362 + accessibilityHint={ 363 + !isDeletedAccount 364 + ? _(msg`Go to conversation with ${profile.handle}`) 365 + : _( 366 + msg`This conversation is with a deleted or a deactivated account. Press for options`, 367 + ) 368 + } 369 + accessibilityActions={ 370 + isNative 371 + ? [ 372 + { 373 + name: 'magicTap', 374 + label: _(msg`Open conversation options`), 375 + }, 376 + { 377 + name: 'longpress', 378 + label: _(msg`Open conversation options`), 379 + }, 380 + ] 381 + : undefined 382 + } 383 + onPress={onPress} 384 + onLongPress={isNative ? onLongPress : undefined} 385 + onAccessibilityAction={onLongPress}> 386 + {({hovered, pressed, focused}) => ( 387 + <View 388 + style={[ 389 + a.flex_row, 390 + isDeletedAccount ? a.align_center : a.align_start, 391 + a.flex_1, 392 + a.px_lg, 393 + a.py_md, 394 + a.gap_md, 395 + (hovered || pressed || focused) && t.atoms.bg_contrast_25, 396 + ]}> 397 + {/* Avatar goes here */} 398 + <View style={{width: 52, height: 52}} /> 399 400 + <View 401 + style={[a.flex_1, a.justify_center, web({paddingRight: 45})]}> 402 + <View style={[a.w_full, a.flex_row, a.align_end, a.pb_2xs]}> 403 + <View style={[a.flex_shrink]}> 404 + <Text 405 + emoji 406 + numberOfLines={1} 407 + style={[ 408 + a.text_md, 409 + t.atoms.text, 410 + a.font_semi_bold, 411 + {lineHeight: 21}, 412 + isDimStyle && t.atoms.text_contrast_medium, 413 + ]}> 414 + {displayName} 415 + </Text> 416 + </View> 417 + {verification.showBadge && ( 418 + <View style={[a.pl_xs, a.self_center]}> 419 + <VerificationCheck 420 + width={14} 421 + verifier={verification.role === 'verifier'} 422 + /> 423 + </View> 424 + )} 425 + {lastMessageSentAt && ( 426 + <View style={[a.pl_xs]}> 427 + <TimeElapsed timestamp={lastMessageSentAt}> 428 + {({timeElapsed}) => ( 429 + <Text 430 + style={[ 431 + a.text_sm, 432 + {lineHeight: 21}, 433 + t.atoms.text_contrast_medium, 434 + web({whiteSpace: 'preserve nowrap'}), 435 + ]}> 436 + &middot; {timeElapsed} 437 + </Text> 438 + )} 439 + </TimeElapsed> 440 + </View> 441 + )} 442 + {(convo.muted || moderation.blocked) && ( 443 + <Text 444 + style={[ 445 + a.text_sm, 446 + {lineHeight: 21}, 447 + t.atoms.text_contrast_medium, 448 + web({whiteSpace: 'preserve nowrap'}), 449 + ]}> 450 + {' '} 451 + &middot;{' '} 452 + <BellStroke 453 + size="xs" 454 + style={[t.atoms.text_contrast_medium]} 455 + /> 456 + </Text> 457 + )} 458 + </View> 459 460 + {!isDeletedAccount && ( 461 <Text 462 numberOfLines={1} 463 style={[ 464 a.text_sm, 465 t.atoms.text_contrast_medium, 466 + a.pb_xs, 467 ]}> 468 + @{profile.handle} 469 </Text> 470 )} 471 472 <Text 473 + emoji 474 + numberOfLines={2} 475 + style={[ 476 + a.text_sm, 477 + a.leading_snug, 478 + hasUnread ? a.font_semi_bold : t.atoms.text_contrast_high, 479 + isDimStyle && t.atoms.text_contrast_medium, 480 + ]}> 481 + {lastMessage} 482 </Text> 483 484 + <PostAlerts 485 + modui={moderation.ui('contentList')} 486 + size="lg" 487 + style={[a.pt_xs]} 488 + /> 489 490 + {children} 491 + </View> 492 493 + {hasUnread && ( 494 + <View 495 + style={[ 496 + a.absolute, 497 + a.rounded_full, 498 + { 499 + backgroundColor: isDimStyle 500 + ? t.palette.contrast_200 501 + : t.palette.primary_500, 502 + height: 7, 503 + width: 7, 504 + top: 15, 505 + right: 12, 506 + }, 507 + ]} 508 + /> 509 + )} 510 </View> 511 + )} 512 + </Link> 513 514 + <ChatListItemPortal.Outlet /> 515 516 + {showMenu && ( 517 + <ConvoMenu 518 + convo={convo} 519 + profile={profile} 520 + control={menuControl} 521 + currentScreen="list" 522 + showMarkAsRead={convo.unreadCount > 0} 523 + hideTrigger={isNative} 524 + blockInfo={blockInfo} 525 + style={[ 526 + a.absolute, 527 + a.h_full, 528 + a.self_end, 529 + a.justify_center, 530 + { 531 + right: tokens.space.lg, 532 + opacity: 533 + !gtMobile || showActions || menuControl.isOpen ? 1 : 0, 534 + }, 535 + ]} 536 + latestReportableMessage={latestReportableMessage} 537 + /> 538 + )} 539 + <LeaveConvoPrompt 540 + control={leaveConvoControl} 541 + convoId={convo.id} 542 currentScreen="list" 543 /> 544 + </View> 545 + </GestureActionView> 546 + </ChatListItemPortal.Provider> 547 ) 548 }
+2 -3
src/screens/Messages/components/ChatStatusInfo.tsx
··· 46 label={_(msg`Block or report`)} 47 convo={convoState.convo} 48 profile={otherUser} 49 - color="negative" 50 size="small" 51 currentScreen="conversation" 52 /> ··· 70 <AcceptChatButton 71 onAcceptConvo={onAcceptChat} 72 convo={convoState.convo} 73 - color="primary" 74 - variant="outline" 75 size="small" 76 currentScreen="conversation" 77 />
··· 46 label={_(msg`Block or report`)} 47 convo={convoState.convo} 48 profile={otherUser} 49 + color="negative_subtle" 50 size="small" 51 currentScreen="conversation" 52 /> ··· 70 <AcceptChatButton 71 onAcceptConvo={onAcceptChat} 72 convo={convoState.convo} 73 + color="primary_subtle" 74 size="small" 75 currentScreen="conversation" 76 />
+1 -7
src/screens/Messages/components/RequestButtons.tsx
··· 36 convo, 37 profile, 38 size = 'tiny', 39 - variant = 'outline', 40 color = 'secondary', 41 label, 42 showDeleteConvo, ··· 117 label={triggerProps.accessibilityLabel} 118 style={[a.flex_1]} 119 color={color} 120 - variant={variant} 121 size={size}> 122 <ButtonText> 123 {label || ( ··· 129 </Button> 130 )} 131 </Menu.Trigger> 132 - <Menu.Outer> 133 <Menu.Group> 134 {showDeleteConvo && ( 135 <Menu.Item ··· 181 export function AcceptChatButton({ 182 convo, 183 size = 'tiny', 184 - variant = 'solid', 185 color = 'secondary_inverted', 186 label, 187 currentScreen, ··· 248 {...props} 249 label={label || _(msg`Accept chat request`)} 250 size={size} 251 - variant={variant} 252 color={color} 253 style={a.flex_1} 254 onPress={onPressAccept}> ··· 266 export function DeleteChatButton({ 267 convo, 268 size = 'tiny', 269 - variant = 'outline', 270 color = 'secondary', 271 label, 272 currentScreen, ··· 315 <Button 316 label={label || _(msg`Delete chat`)} 317 size={size} 318 - variant={variant} 319 color={color} 320 style={a.flex_1} 321 onPress={onPressDelete}
··· 36 convo, 37 profile, 38 size = 'tiny', 39 color = 'secondary', 40 label, 41 showDeleteConvo, ··· 116 label={triggerProps.accessibilityLabel} 117 style={[a.flex_1]} 118 color={color} 119 size={size}> 120 <ButtonText> 121 {label || ( ··· 127 </Button> 128 )} 129 </Menu.Trigger> 130 + <Menu.Outer showCancel> 131 <Menu.Group> 132 {showDeleteConvo && ( 133 <Menu.Item ··· 179 export function AcceptChatButton({ 180 convo, 181 size = 'tiny', 182 color = 'secondary_inverted', 183 label, 184 currentScreen, ··· 245 {...props} 246 label={label || _(msg`Accept chat request`)} 247 size={size} 248 color={color} 249 style={a.flex_1} 250 onPress={onPressAccept}> ··· 262 export function DeleteChatButton({ 263 convo, 264 size = 'tiny', 265 color = 'secondary', 266 label, 267 currentScreen, ··· 310 <Button 311 label={label || _(msg`Delete chat`)} 312 size={size} 313 color={color} 314 style={a.flex_1} 315 onPress={onPressDelete}
+34 -31
src/screens/Messages/components/RequestListItem.tsx
··· 7 import {atoms as a, tokens} from '#/alf' 8 import {KnownFollowers} from '#/components/KnownFollowers' 9 import {Text} from '#/components/Typography' 10 - import {ChatListItem} from './ChatListItem' 11 import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons' 12 13 export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) { ··· 42 <Trans comment="Accept a chat request">Accept Request</Trans> 43 </Text> 44 </View> 45 </ChatListItem> 46 - <View 47 - style={[ 48 - a.absolute, 49 - a.pr_md, 50 - a.w_full, 51 - a.flex_row, 52 - a.align_center, 53 - a.gap_sm, 54 - { 55 - bottom: tokens.space.md, 56 - paddingLeft: tokens.space.lg + 52 + tokens.space.md, 57 - }, 58 - ]}> 59 - {!isDeletedAccount ? ( 60 - <> 61 - <AcceptChatButton convo={convo} currentScreen="list" /> 62 - <RejectMenu 63 - convo={convo} 64 - profile={otherUser} 65 - showDeleteConvo 66 - currentScreen="list" 67 - /> 68 - </> 69 - ) : ( 70 - <> 71 - <DeleteChatButton convo={convo} currentScreen="list" /> 72 - <View style={a.flex_1} /> 73 - </> 74 - )} 75 - </View> 76 </View> 77 ) 78 }
··· 7 import {atoms as a, tokens} from '#/alf' 8 import {KnownFollowers} from '#/components/KnownFollowers' 9 import {Text} from '#/components/Typography' 10 + import {ChatListItem, ChatListItemPortal} from './ChatListItem' 11 import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons' 12 13 export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) { ··· 42 <Trans comment="Accept a chat request">Accept Request</Trans> 43 </Text> 44 </View> 45 + {/* then, this gets absolutely positioned on top of the spacer */} 46 + <ChatListItemPortal.Portal> 47 + <View 48 + style={[ 49 + a.absolute, 50 + a.pr_md, 51 + a.w_full, 52 + a.flex_row, 53 + a.align_center, 54 + a.gap_sm, 55 + { 56 + bottom: tokens.space.md, 57 + paddingLeft: tokens.space.lg + 52 + tokens.space.md, 58 + }, 59 + ]}> 60 + {!isDeletedAccount ? ( 61 + <> 62 + <AcceptChatButton convo={convo} currentScreen="list" /> 63 + <RejectMenu 64 + convo={convo} 65 + profile={otherUser} 66 + showDeleteConvo 67 + currentScreen="list" 68 + /> 69 + </> 70 + ) : ( 71 + <> 72 + <DeleteChatButton convo={convo} currentScreen="list" /> 73 + <View style={a.flex_1} /> 74 + </> 75 + )} 76 + </View> 77 + </ChatListItemPortal.Portal> 78 </ChatListItem> 79 </View> 80 ) 81 }
+7 -10
src/screens/Onboarding/Layout.tsx
··· 5 import {msg} from '@lingui/macro' 6 import {useLingui} from '@lingui/react' 7 8 - import {isWeb} from '#/platform/detection' 9 import {useOnboardingDispatch} from '#/state/shell' 10 import {Context} from '#/screens/Onboarding/state' 11 import { ··· 59 aria-label={dialogLabel} 60 accessibilityLabel={dialogLabel} 61 accessibilityHint={_(msg`Customizes your Bluesky experience`)} 62 - style={[ 63 - // @ts-ignore web only -prf 64 - isWeb ? a.fixed : a.absolute, 65 - a.inset_0, 66 - a.flex_1, 67 - t.atoms.bg, 68 - ]}> 69 {__DEV__ && ( 70 <Button 71 variant="ghost" ··· 135 <ScrollView 136 ref={scrollview} 137 style={[a.h_full, a.w_full, {paddingTop: insets.top}]} 138 - contentContainerStyle={{borderWidth: 0}} 139 scrollIndicatorInsets={{bottom: footerHeight - insets.bottom}} 140 // @ts-expect-error web only --prf 141 dataSet={{'stable-gutters': 1}}> ··· 173 </View> 174 </View> 175 176 - <View style={[a.w_full, a.mb_5xl, a.pt_md]}>{children}</View> 177 178 <View style={{height: 100 + footerHeight}} /> 179 </View>
··· 5 import {msg} from '@lingui/macro' 6 import {useLingui} from '@lingui/react' 7 8 + import {isAndroid, isWeb} from '#/platform/detection' 9 import {useOnboardingDispatch} from '#/state/shell' 10 import {Context} from '#/screens/Onboarding/state' 11 import { ··· 59 aria-label={dialogLabel} 60 accessibilityLabel={dialogLabel} 61 accessibilityHint={_(msg`Customizes your Bluesky experience`)} 62 + style={[isWeb ? a.fixed : a.absolute, a.inset_0, a.flex_1, t.atoms.bg]}> 63 {__DEV__ && ( 64 <Button 65 variant="ghost" ··· 129 <ScrollView 130 ref={scrollview} 131 style={[a.h_full, a.w_full, {paddingTop: insets.top}]} 132 + contentContainerStyle={{borderWidth: 0, minHeight: '100%'}} 133 + showsVerticalScrollIndicator={!isAndroid} 134 scrollIndicatorInsets={{bottom: footerHeight - insets.bottom}} 135 // @ts-expect-error web only --prf 136 dataSet={{'stable-gutters': 1}}> ··· 168 </View> 169 </View> 170 171 + <View style={[a.w_full, a.h_full, a.mb_5xl, a.pt_md]}> 172 + {children} 173 + </View> 174 175 <View style={{height: 100 + footerHeight}} /> 176 </View>
+9 -158
src/screens/Onboarding/StepFinished.tsx src/screens/Onboarding/StepFinished/index.tsx
··· 1 import {useCallback, useContext, useState} from 'react' 2 import {View} from 'react-native' 3 - import Animated, { 4 - Easing, 5 - LayoutAnimationConfig, 6 - SlideInRight, 7 - SlideOutLeft, 8 - } from 'react-native-reanimated' 9 - import {Image} from 'expo-image' 10 import { 11 type AppBskyActorDefs, 12 type AppBskyActorProfile, ··· 29 import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' 30 import {logEvent, useGate} from '#/lib/statsig/statsig' 31 import {logger} from '#/logger' 32 - import {isNative} from '#/platform/detection' 33 import {useSetHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs' 34 import {getAllListMembers} from '#/state/queries/list-members' 35 import {preferencesQueryKey} from '#/state/queries/preferences' ··· 49 } from '#/screens/Onboarding/Layout' 50 import {Context, type OnboardingState} from '#/screens/Onboarding/state' 51 import {bulkWriteFollows} from '#/screens/Onboarding/util' 52 - import { 53 - atoms as a, 54 - native, 55 - platform, 56 - tokens, 57 - useBreakpoints, 58 - useTheme, 59 - } from '#/alf' 60 import {Button, ButtonIcon, ButtonText} from '#/components/Button' 61 import {IconCircle} from '#/components/IconCircle' 62 import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRight} from '#/components/icons/Arrow' ··· 67 import {Loader} from '#/components/Loader' 68 import {Text} from '#/components/Typography' 69 import * as bsky from '#/types/bsky' 70 71 export function StepFinished() { 72 const {state, dispatch} = useContext(Context) ··· 275 ) 276 } 277 278 - const PROP_1 = { 279 - light: platform({ 280 - native: require('../../../assets/images/onboarding/value_prop_1_light.webp'), 281 - web: require('../../../assets/images/onboarding/value_prop_1_light_borderless.webp'), 282 - }), 283 - dim: platform({ 284 - native: require('../../../assets/images/onboarding/value_prop_1_dim.webp'), 285 - web: require('../../../assets/images/onboarding/value_prop_1_dim_borderless.webp'), 286 - }), 287 - dark: platform({ 288 - native: require('../../../assets/images/onboarding/value_prop_1_dark.webp'), 289 - web: require('../../../assets/images/onboarding/value_prop_1_dark_borderless.webp'), 290 - }), 291 - } as const 292 - 293 - const PROP_2 = { 294 - light: require('../../../assets/images/onboarding/value_prop_2_light.webp'), 295 - dim: require('../../../assets/images/onboarding/value_prop_2_dim.webp'), 296 - dark: require('../../../assets/images/onboarding/value_prop_2_dark.webp'), 297 - } as const 298 - 299 - const PROP_3 = { 300 - light: require('../../../assets/images/onboarding/value_prop_3_light.webp'), 301 - dim: require('../../../assets/images/onboarding/value_prop_3_dim.webp'), 302 - dark: require('../../../assets/images/onboarding/value_prop_3_dark.webp'), 303 - } as const 304 - 305 function ValueProposition({ 306 finishOnboarding, 307 saving, ··· 312 state: OnboardingState 313 }) { 314 const [subStep, setSubStep] = useState<0 | 1 | 2>(0) 315 - const t = useTheme() 316 const {_} = useLingui() 317 const {gtMobile} = useBreakpoints() 318 319 - const image = [PROP_1[t.name], PROP_2[t.name], PROP_3[t.name]][subStep] 320 - 321 const onPress = () => { 322 if (subStep === 2) { 323 finishOnboarding() // has its own metrics ··· 330 } 331 } 332 333 - const {title, description, alt} = [ 334 - { 335 - title: _(msg`Free your feed`), 336 - description: _( 337 - msg`No more doomscrolling junk-filled algorithms. Find feeds that work for you, not against you.`, 338 - ), 339 - alt: _( 340 - msg`A collection of popular feeds you can find on Bluesky, including News, Booksky, Game Dev, Blacksky, and Fountain Pens`, 341 - ), 342 - }, 343 - { 344 - title: _(msg`Find your people`), 345 - description: _( 346 - msg`Ditch the trolls and clickbait. Find real people and conversations that matter to you.`, 347 - ), 348 - alt: _( 349 - msg`Your profile picture surrounded by concentric circles of other users' profile pictures`, 350 - ), 351 - }, 352 - { 353 - title: _(msg`Forget the noise`), 354 - description: _( 355 - msg`No ads, no invasive tracking, no engagement traps. Bluesky respects your time and attention.`, 356 - ), 357 - alt: _( 358 - msg`An illustration of several Bluesky posts alongside repost, like, and comment icons`, 359 - ), 360 - }, 361 - ][subStep] 362 - 363 return ( 364 <> 365 {!gtMobile && ( ··· 382 </OnboardingHeaderSlot.Portal> 383 )} 384 385 - <LayoutAnimationConfig skipEntering skipExiting> 386 - <Animated.View 387 - key={subStep} 388 - entering={native( 389 - SlideInRight.easing(Easing.out(Easing.exp)).duration(500), 390 - )} 391 - exiting={native( 392 - SlideOutLeft.easing(Easing.out(Easing.exp)).duration(500), 393 - )}> 394 - <View 395 - style={[ 396 - a.relative, 397 - a.align_center, 398 - a.justify_center, 399 - isNative && {marginHorizontal: tokens.space.xl * -1}, 400 - a.pointer_events_none, 401 - ]}> 402 - <Image 403 - source={image} 404 - style={[a.w_full, {aspectRatio: 1}]} 405 - alt={alt} 406 - accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background 407 - /> 408 - {subStep === 1 && ( 409 - <Image 410 - source={state.profileStepResults.imageUri} 411 - style={[ 412 - a.z_10, 413 - a.absolute, 414 - a.rounded_full, 415 - { 416 - width: `${(80 / 393) * 100}%`, 417 - height: `${(80 / 393) * 100}%`, 418 - }, 419 - ]} 420 - accessibilityIgnoresInvertColors 421 - alt={_(msg`Your profile picture`)} 422 - /> 423 - )} 424 - </View> 425 - 426 - <View style={[a.mt_4xl, a.gap_2xl, a.align_center]}> 427 - <View style={[a.flex_row, a.gap_sm]}> 428 - <Dot active={subStep === 0} /> 429 - <Dot active={subStep === 1} /> 430 - <Dot active={subStep === 2} /> 431 - </View> 432 - 433 - <View style={[a.gap_sm]}> 434 - <Text style={[a.font_bold, a.text_3xl, a.text_center]}> 435 - {title} 436 - </Text> 437 - <Text 438 - style={[ 439 - t.atoms.text_contrast_medium, 440 - a.text_md, 441 - a.leading_snug, 442 - a.text_center, 443 - ]}> 444 - {description} 445 - </Text> 446 - </View> 447 - </View> 448 - </Animated.View> 449 - </LayoutAnimationConfig> 450 451 <OnboardingControls.Portal> 452 <View style={gtMobile && [a.gap_md, a.flex_row]}> 453 - {gtMobile && ( 454 <Button 455 disabled={saving} 456 color="secondary" ··· 489 </View> 490 </OnboardingControls.Portal> 491 </> 492 - ) 493 - } 494 - 495 - function Dot({active}: {active: boolean}) { 496 - const t = useTheme() 497 - 498 - return ( 499 - <View 500 - style={[ 501 - a.rounded_full, 502 - {width: 8, height: 8}, 503 - active 504 - ? {backgroundColor: t.palette.primary_500} 505 - : t.atoms.bg_contrast_50, 506 - ]} 507 - /> 508 ) 509 } 510
··· 1 import {useCallback, useContext, useState} from 'react' 2 import {View} from 'react-native' 3 import { 4 type AppBskyActorDefs, 5 type AppBskyActorProfile, ··· 22 import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' 23 import {logEvent, useGate} from '#/lib/statsig/statsig' 24 import {logger} from '#/logger' 25 + import {isWeb} from '#/platform/detection' 26 import {useSetHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs' 27 import {getAllListMembers} from '#/state/queries/list-members' 28 import {preferencesQueryKey} from '#/state/queries/preferences' ··· 42 } from '#/screens/Onboarding/Layout' 43 import {Context, type OnboardingState} from '#/screens/Onboarding/state' 44 import {bulkWriteFollows} from '#/screens/Onboarding/util' 45 + import {atoms as a, useBreakpoints, useTheme} from '#/alf' 46 import {Button, ButtonIcon, ButtonText} from '#/components/Button' 47 import {IconCircle} from '#/components/IconCircle' 48 import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRight} from '#/components/icons/Arrow' ··· 53 import {Loader} from '#/components/Loader' 54 import {Text} from '#/components/Typography' 55 import * as bsky from '#/types/bsky' 56 + import {ValuePropositionPager} from './ValuePropositionPager' 57 58 export function StepFinished() { 59 const {state, dispatch} = useContext(Context) ··· 262 ) 263 } 264 265 function ValueProposition({ 266 finishOnboarding, 267 saving, ··· 272 state: OnboardingState 273 }) { 274 const [subStep, setSubStep] = useState<0 | 1 | 2>(0) 275 const {_} = useLingui() 276 const {gtMobile} = useBreakpoints() 277 278 const onPress = () => { 279 if (subStep === 2) { 280 finishOnboarding() // has its own metrics ··· 287 } 288 } 289 290 return ( 291 <> 292 {!gtMobile && ( ··· 309 </OnboardingHeaderSlot.Portal> 310 )} 311 312 + <ValuePropositionPager 313 + step={subStep} 314 + setStep={ss => setSubStep(ss)} 315 + avatarUri={state.profileStepResults.imageUri} 316 + /> 317 318 <OnboardingControls.Portal> 319 <View style={gtMobile && [a.gap_md, a.flex_row]}> 320 + {gtMobile && (isWeb ? subStep !== 2 : true) && ( 321 <Button 322 disabled={saving} 323 color="secondary" ··· 356 </View> 357 </OnboardingControls.Portal> 358 </> 359 ) 360 } 361
+55
src/screens/Onboarding/StepFinished/ValuePropositionPager.shared.tsx
···
··· 1 + import {View} from 'react-native' 2 + import {msg} from '@lingui/macro' 3 + import {useLingui} from '@lingui/react' 4 + 5 + import {atoms as a, useTheme} from '#/alf' 6 + 7 + export function useValuePropText(step: 0 | 1 | 2) { 8 + const {_} = useLingui() 9 + 10 + return [ 11 + { 12 + title: _(msg`Free your feed`), 13 + description: _( 14 + msg`No more doomscrolling junk-filled algorithms. Find feeds that work for you, not against you.`, 15 + ), 16 + alt: _( 17 + msg`A collection of popular feeds you can find on Bluesky, including News, Booksky, Game Dev, Blacksky, and Fountain Pens`, 18 + ), 19 + }, 20 + { 21 + title: _(msg`Find your people`), 22 + description: _( 23 + msg`Ditch the trolls and clickbait. Find real people and conversations that matter to you.`, 24 + ), 25 + alt: _( 26 + msg`Your profile picture surrounded by concentric circles of other users' profile pictures`, 27 + ), 28 + }, 29 + { 30 + title: _(msg`Forget the noise`), 31 + description: _( 32 + msg`No ads, no invasive tracking, no engagement traps. Bluesky respects your time and attention.`, 33 + ), 34 + alt: _( 35 + msg`An illustration of several Bluesky posts alongside repost, like, and comment icons`, 36 + ), 37 + }, 38 + ][step] 39 + } 40 + 41 + export function Dot({active}: {active: boolean}) { 42 + const t = useTheme() 43 + 44 + return ( 45 + <View 46 + style={[ 47 + a.rounded_full, 48 + {width: 8, height: 8}, 49 + active 50 + ? {backgroundColor: t.palette.primary_500} 51 + : t.atoms.bg_contrast_50, 52 + ]} 53 + /> 54 + ) 55 + }
+127
src/screens/Onboarding/StepFinished/ValuePropositionPager.tsx
···
··· 1 + import {useRef, useState} from 'react' 2 + import {View} from 'react-native' 3 + import PagerView from 'react-native-pager-view' 4 + import {Image} from 'expo-image' 5 + import {msg} from '@lingui/macro' 6 + import {useLingui} from '@lingui/react' 7 + 8 + import {atoms as a, tokens, useTheme} from '#/alf' 9 + import {Text} from '#/components/Typography' 10 + import {PROP_1, PROP_2, PROP_3} from './images' 11 + import {Dot, useValuePropText} from './ValuePropositionPager.shared' 12 + 13 + export function ValuePropositionPager({ 14 + step, 15 + setStep, 16 + avatarUri, 17 + }: { 18 + step: 0 | 1 | 2 19 + setStep: (step: 0 | 1 | 2) => void 20 + avatarUri?: string 21 + }) { 22 + const t = useTheme() 23 + const [activePage, setActivePage] = useState(step) 24 + const ref = useRef<PagerView>(null) 25 + 26 + if (step !== activePage) { 27 + setActivePage(step) 28 + ref.current?.setPage(step) 29 + } 30 + 31 + const images = [PROP_1[t.name], PROP_2[t.name], PROP_3[t.name]] 32 + 33 + return ( 34 + <View style={[a.h_full, {marginHorizontal: tokens.space.xl * -1}]}> 35 + <PagerView 36 + ref={ref} 37 + style={[a.flex_1]} 38 + initialPage={step} 39 + onPageSelected={evt => { 40 + const page = evt.nativeEvent.position as 0 | 1 | 2 41 + if (step !== page) { 42 + setActivePage(page) 43 + setStep(page) 44 + } 45 + }}> 46 + {([0, 1, 2] as const).map(page => ( 47 + <Page 48 + key={page} 49 + page={page} 50 + image={images[page]} 51 + avatarUri={avatarUri} 52 + /> 53 + ))} 54 + </PagerView> 55 + </View> 56 + ) 57 + } 58 + 59 + function Page({ 60 + page, 61 + image, 62 + avatarUri, 63 + }: { 64 + page: 0 | 1 | 2 65 + image: string 66 + avatarUri?: string 67 + }) { 68 + const {_} = useLingui() 69 + const t = useTheme() 70 + const {title, description, alt} = useValuePropText(page) 71 + 72 + return ( 73 + <View key={page}> 74 + <View 75 + style={[ 76 + a.relative, 77 + a.align_center, 78 + a.justify_center, 79 + a.pointer_events_none, 80 + ]}> 81 + <Image 82 + source={image} 83 + style={[a.w_full, a.aspect_square]} 84 + alt={alt} 85 + accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background 86 + /> 87 + {page === 1 && ( 88 + <Image 89 + source={avatarUri} 90 + style={[ 91 + a.z_10, 92 + a.absolute, 93 + a.rounded_full, 94 + { 95 + width: `${(80 / 393) * 100}%`, 96 + height: `${(80 / 393) * 100}%`, 97 + }, 98 + ]} 99 + accessibilityIgnoresInvertColors 100 + alt={_(msg`Your profile picture`)} 101 + /> 102 + )} 103 + </View> 104 + 105 + <View style={[a.mt_4xl, a.gap_2xl, a.px_xl, a.align_center]}> 106 + <View style={[a.flex_row, a.gap_sm]}> 107 + <Dot active={page === 0} /> 108 + <Dot active={page === 1} /> 109 + <Dot active={page === 2} /> 110 + </View> 111 + 112 + <View style={[a.gap_sm]}> 113 + <Text style={[a.font_bold, a.text_3xl, a.text_center]}>{title}</Text> 114 + <Text 115 + style={[ 116 + t.atoms.text_contrast_medium, 117 + a.text_md, 118 + a.leading_snug, 119 + a.text_center, 120 + ]}> 121 + {description} 122 + </Text> 123 + </View> 124 + </View> 125 + </View> 126 + ) 127 + }
+80
src/screens/Onboarding/StepFinished/ValuePropositionPager.web.tsx
···
··· 1 + import {View} from 'react-native' 2 + import {Image} from 'expo-image' 3 + import {msg} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 5 + 6 + import {atoms as a, useTheme} from '#/alf' 7 + import {Text} from '#/components/Typography' 8 + import {PROP_1, PROP_2, PROP_3} from './images' 9 + import {Dot, useValuePropText} from './ValuePropositionPager.shared' 10 + 11 + export function ValuePropositionPager({ 12 + step, 13 + avatarUri, 14 + }: { 15 + step: 0 | 1 | 2 16 + avatarUri?: string 17 + }) { 18 + const t = useTheme() 19 + const {_} = useLingui() 20 + 21 + const image = [PROP_1[t.name], PROP_2[t.name], PROP_3[t.name]][step] 22 + 23 + const {title, description, alt} = useValuePropText(step) 24 + 25 + return ( 26 + <View> 27 + <View 28 + style={[ 29 + a.relative, 30 + a.align_center, 31 + a.justify_center, 32 + a.pointer_events_none, 33 + ]}> 34 + <Image 35 + source={image} 36 + style={[a.w_full, {aspectRatio: 1}]} 37 + alt={alt} 38 + accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background 39 + /> 40 + {step === 1 && ( 41 + <Image 42 + source={avatarUri} 43 + style={[ 44 + a.z_10, 45 + a.absolute, 46 + a.rounded_full, 47 + { 48 + width: `${(80 / 393) * 100}%`, 49 + height: `${(80 / 393) * 100}%`, 50 + }, 51 + ]} 52 + accessibilityIgnoresInvertColors 53 + alt={_(msg`Your profile picture`)} 54 + /> 55 + )} 56 + </View> 57 + 58 + <View style={[a.mt_4xl, a.gap_2xl, a.align_center]}> 59 + <View style={[a.flex_row, a.gap_sm]}> 60 + <Dot active={step === 0} /> 61 + <Dot active={step === 1} /> 62 + <Dot active={step === 2} /> 63 + </View> 64 + 65 + <View style={[a.gap_sm]}> 66 + <Text style={[a.font_bold, a.text_3xl, a.text_center]}>{title}</Text> 67 + <Text 68 + style={[ 69 + t.atoms.text_contrast_medium, 70 + a.text_md, 71 + a.leading_snug, 72 + a.text_center, 73 + ]}> 74 + {description} 75 + </Text> 76 + </View> 77 + </View> 78 + </View> 79 + ) 80 + }
+28
src/screens/Onboarding/StepFinished/images.ts
···
··· 1 + import {platform} from '#/alf' 2 + 3 + export const PROP_1 = { 4 + light: platform({ 5 + native: require('../../../../assets/images/onboarding/value_prop_1_light.webp'), 6 + web: require('../../../../assets/images/onboarding/value_prop_1_light_borderless.webp'), 7 + }), 8 + dim: platform({ 9 + native: require('../../../../assets/images/onboarding/value_prop_1_dim.webp'), 10 + web: require('../../../../assets/images/onboarding/value_prop_1_dim_borderless.webp'), 11 + }), 12 + dark: platform({ 13 + native: require('../../../../assets/images/onboarding/value_prop_1_dark.webp'), 14 + web: require('../../../../assets/images/onboarding/value_prop_1_dark_borderless.webp'), 15 + }), 16 + } as const 17 + 18 + export const PROP_2 = { 19 + light: require('../../../../assets/images/onboarding/value_prop_2_light.webp'), 20 + dim: require('../../../../assets/images/onboarding/value_prop_2_dim.webp'), 21 + dark: require('../../../../assets/images/onboarding/value_prop_2_dark.webp'), 22 + } as const 23 + 24 + export const PROP_3 = { 25 + light: require('../../../../assets/images/onboarding/value_prop_3_light.webp'), 26 + dim: require('../../../../assets/images/onboarding/value_prop_3_dim.webp'), 27 + dark: require('../../../../assets/images/onboarding/value_prop_3_dark.webp'), 28 + } as const
+6 -9
src/screens/Onboarding/index.tsx
··· 2 import {msg} from '@lingui/macro' 3 import {useLingui} from '@lingui/react' 4 5 - import {useGate} from '#/lib/statsig/statsig' 6 import { 7 Layout, 8 OnboardingControls, ··· 13 import {StepInterests} from '#/screens/Onboarding/StepInterests' 14 import {StepProfile} from '#/screens/Onboarding/StepProfile' 15 import {Portal} from '#/components/Portal' 16 - import {ENV} from '#/env' 17 import {StepSuggestedAccounts} from './StepSuggestedAccounts' 18 19 export function Onboarding() { 20 const {_} = useLingui() 21 - const gate = useGate() 22 - const showValueProp = ENV !== 'e2e' && gate('onboarding_value_prop') 23 - const showSuggestedAccounts = 24 - ENV !== 'e2e' && gate('onboarding_suggested_accounts') 25 const [state, dispatch] = useReducer(reducer, { 26 ...initialState, 27 - totalSteps: showSuggestedAccounts ? 4 : 3, 28 experiments: { 29 - onboarding_suggested_accounts: showSuggestedAccounts, 30 - onboarding_value_prop: showValueProp, 31 }, 32 }) 33
··· 2 import {msg} from '@lingui/macro' 3 import {useLingui} from '@lingui/react' 4 5 import { 6 Layout, 7 OnboardingControls, ··· 12 import {StepInterests} from '#/screens/Onboarding/StepInterests' 13 import {StepProfile} from '#/screens/Onboarding/StepProfile' 14 import {Portal} from '#/components/Portal' 15 import {StepSuggestedAccounts} from './StepSuggestedAccounts' 16 17 export function Onboarding() { 18 const {_} = useLingui() 19 + 20 const [state, dispatch] = useReducer(reducer, { 21 ...initialState, 22 + totalSteps: 4, 23 experiments: { 24 + // let's leave this flag logic in for now to avoid rebase churn 25 + // TODO: remove this flag logic once we've finished with all experiments -sfn 26 + onboarding_suggested_accounts: true, 27 + onboarding_value_prop: true, 28 }, 29 }) 30
+2 -6
src/screens/PostThread/components/ThreadItemAnchor.tsx
··· 43 OUTER_SPACE, 44 REPLY_LINE_WIDTH, 45 } from '#/screens/PostThread/const' 46 - import {atoms as a, useBreakpoints, useTheme} from '#/alf' 47 import {colors} from '#/components/Admonition' 48 import {Button} from '#/components/Button' 49 import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock' 50 import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' 51 import {InlineLinkText, Link} from '#/components/Link' 52 - import {LoggedOutCTA} from '#/components/LoggedOutCTA' 53 import {ContentHider} from '#/components/moderation/ContentHider' 54 import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe' 55 import {PostAlerts} from '#/components/moderation/PostAlerts' ··· 184 const {_} = useLingui() 185 const {openComposer} = useOpenComposer() 186 const {currentAccount, hasSession} = useSession() 187 - const {gtTablet} = useBreakpoints() 188 const feedFeedback = useFeedFeedback(postSource?.feedSourceInfo, hasSession) 189 const formatPostStatCount = useFormatPostStatCount() 190 ··· 325 }, 326 isRoot && [a.pt_lg], 327 ]}> 328 - {/* Show CTA for logged-out visitors - hide on desktop and check gate */} 329 - {!gtTablet && <LoggedOutCTA gateName="cta_above_post_heading" />} 330 <View style={[a.flex_row, a.gap_md, a.pb_md]}> 331 <View collapsable={false}> 332 <PreviewableUserAvatar ··· 405 enableTags 406 selectable 407 value={richText} 408 - style={[a.flex_1, a.text_xl]} 409 authorHandle={post.author.handle} 410 shouldProxyLinks={true} 411 />
··· 43 OUTER_SPACE, 44 REPLY_LINE_WIDTH, 45 } from '#/screens/PostThread/const' 46 + import {atoms as a, useTheme} from '#/alf' 47 import {colors} from '#/components/Admonition' 48 import {Button} from '#/components/Button' 49 import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock' 50 import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' 51 import {InlineLinkText, Link} from '#/components/Link' 52 import {ContentHider} from '#/components/moderation/ContentHider' 53 import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe' 54 import {PostAlerts} from '#/components/moderation/PostAlerts' ··· 183 const {_} = useLingui() 184 const {openComposer} = useOpenComposer() 185 const {currentAccount, hasSession} = useSession() 186 const feedFeedback = useFeedFeedback(postSource?.feedSourceInfo, hasSession) 187 const formatPostStatCount = useFormatPostStatCount() 188 ··· 323 }, 324 isRoot && [a.pt_lg], 325 ]}> 326 <View style={[a.flex_row, a.gap_md, a.pb_md]}> 327 <View collapsable={false}> 328 <PreviewableUserAvatar ··· 401 enableTags 402 selectable 403 value={richText} 404 + style={[a.flex_1, a.text_lg]} 405 authorHandle={post.author.handle} 406 shouldProxyLinks={true} 407 />
+8 -9
src/screens/PostThread/components/ThreadItemPost.tsx
··· 41 import {PostControls} from '#/components/PostControls' 42 import {RichText} from '#/components/RichText' 43 import * as Skele from '#/components/Skeleton' 44 - import {SubtleWebHover} from '#/components/SubtleWebHover' 45 import {Text} from '#/components/Typography' 46 47 export type ThreadItemPostProps = { ··· 132 <View 133 style={[ 134 showTopBorder && [a.border_t, t.atoms.border_contrast_low], 135 - { 136 - paddingHorizontal: OUTER_SPACE, 137 - }, 138 // If there's no next child, add a little padding to bottom 139 !item.ui.showChildReplyLine && 140 !item.ui.precedesChildReadMore && { ··· 248 const {isActive: live} = useActorStatus(post.author) 249 250 return ( 251 - <SubtleHover> 252 <ThreadItemPostOuterWrapper item={item} overrides={overrides}> 253 <PostHider 254 testID={`postThreadItem-by-${post.author.handle}`} 255 href={postHref} 256 disabled={overrides?.moderation === true} 257 modui={moderation.ui('contentList')} 258 iconSize={LINEAR_AVI_WIDTH} 259 - iconStyles={{marginLeft: 2, marginRight: 2}} 260 profile={post.author} 261 interpretFilterAsBlur> 262 <ThreadItemPostParentReplyLine item={item} /> ··· 340 </View> 341 </PostHider> 342 </ThreadItemPostOuterWrapper> 343 - </SubtleHover> 344 ) 345 }) 346 347 - function SubtleHover({children}: {children: ReactNode}) { 348 const { 349 state: hover, 350 onIn: onHoverIn, ··· 355 onPointerEnter={onHoverIn} 356 onPointerLeave={onHoverOut} 357 style={a.pointer}> 358 - <SubtleWebHover hover={hover} /> 359 {children} 360 </View> 361 )
··· 41 import {PostControls} from '#/components/PostControls' 42 import {RichText} from '#/components/RichText' 43 import * as Skele from '#/components/Skeleton' 44 + import {SubtleHover} from '#/components/SubtleHover' 45 import {Text} from '#/components/Typography' 46 47 export type ThreadItemPostProps = { ··· 132 <View 133 style={[ 134 showTopBorder && [a.border_t, t.atoms.border_contrast_low], 135 + {paddingHorizontal: OUTER_SPACE}, 136 // If there's no next child, add a little padding to bottom 137 !item.ui.showChildReplyLine && 138 !item.ui.precedesChildReadMore && { ··· 246 const {isActive: live} = useActorStatus(post.author) 247 248 return ( 249 + <SubtleHoverWrapper> 250 <ThreadItemPostOuterWrapper item={item} overrides={overrides}> 251 <PostHider 252 testID={`postThreadItem-by-${post.author.handle}`} 253 href={postHref} 254 disabled={overrides?.moderation === true} 255 modui={moderation.ui('contentList')} 256 + hiderStyle={[a.pl_0, a.pr_2xs, a.bg_transparent]} 257 iconSize={LINEAR_AVI_WIDTH} 258 + iconStyles={[a.mr_xs]} 259 profile={post.author} 260 interpretFilterAsBlur> 261 <ThreadItemPostParentReplyLine item={item} /> ··· 339 </View> 340 </PostHider> 341 </ThreadItemPostOuterWrapper> 342 + </SubtleHoverWrapper> 343 ) 344 }) 345 346 + function SubtleHoverWrapper({children}: {children: ReactNode}) { 347 const { 348 state: hover, 349 onIn: onHoverIn, ··· 354 onPointerEnter={onHoverIn} 355 onPointerLeave={onHoverOut} 356 style={a.pointer}> 357 + <SubtleHover hover={hover} /> 358 {children} 359 </View> 360 )
+5 -5
src/screens/PostThread/components/ThreadItemTreePost.tsx
··· 40 import {PostControls} from '#/components/PostControls' 41 import {RichText} from '#/components/RichText' 42 import * as Skele from '#/components/Skeleton' 43 - import {SubtleWebHover} from '#/components/SubtleWebHover' 44 import {Text} from '#/components/Typography' 45 46 /** ··· 310 311 return ( 312 <ThreadItemTreePostOuterWrapper item={item}> 313 - <SubtleHover> 314 <PostHider 315 testID={`postThreadItem-by-${post.author.handle}`} 316 href={postHref} ··· 381 </View> 382 </ThreadItemTreePostInnerWrapper> 383 </PostHider> 384 - </SubtleHover> 385 </ThreadItemTreePostOuterWrapper> 386 ) 387 }) 388 389 - function SubtleHover({children}: {children: React.ReactNode}) { 390 const { 391 state: hover, 392 onIn: onHoverIn, ··· 397 onPointerEnter={onHoverIn} 398 onPointerLeave={onHoverOut} 399 style={[a.flex_1, a.pointer]}> 400 - <SubtleWebHover hover={hover} /> 401 {children} 402 </View> 403 )
··· 40 import {PostControls} from '#/components/PostControls' 41 import {RichText} from '#/components/RichText' 42 import * as Skele from '#/components/Skeleton' 43 + import {SubtleHover} from '#/components/SubtleHover' 44 import {Text} from '#/components/Typography' 45 46 /** ··· 310 311 return ( 312 <ThreadItemTreePostOuterWrapper item={item}> 313 + <SubtleHoverWrapper> 314 <PostHider 315 testID={`postThreadItem-by-${post.author.handle}`} 316 href={postHref} ··· 381 </View> 382 </ThreadItemTreePostInnerWrapper> 383 </PostHider> 384 + </SubtleHoverWrapper> 385 </ThreadItemTreePostOuterWrapper> 386 ) 387 }) 388 389 + function SubtleHoverWrapper({children}: {children: React.ReactNode}) { 390 const { 391 state: hover, 392 onIn: onHoverIn, ··· 397 onPointerEnter={onHoverIn} 398 onPointerLeave={onHoverOut} 399 style={[a.flex_1, a.pointer]}> 400 + <SubtleHover hover={hover} /> 401 {children} 402 </View> 403 )
-3
src/screens/PostThread/index.tsx
··· 38 import {atoms as a, native, platform, useBreakpoints, web} from '#/alf' 39 import * as Layout from '#/components/Layout' 40 import {ListFooter} from '#/components/Lists' 41 - import {LoggedOutCTA} from '#/components/LoggedOutCTA' 42 43 const PARENT_CHUNK_SIZE = 5 44 const CHILDREN_CHUNK_SIZE = 50 ··· 410 onPostSuccess={optimisticOnPostReply} 411 postSource={anchorPostSource} 412 /> 413 - {/* Show CTA for logged-out visitors */} 414 - <LoggedOutCTA style={a.px_lg} gateName="cta_above_post_replies" /> 415 </View> 416 ) 417 } else {
··· 38 import {atoms as a, native, platform, useBreakpoints, web} from '#/alf' 39 import * as Layout from '#/components/Layout' 40 import {ListFooter} from '#/components/Lists' 41 42 const PARENT_CHUNK_SIZE = 5 43 const CHILDREN_CHUNK_SIZE = 50 ··· 409 onPostSuccess={optimisticOnPostReply} 410 postSource={anchorPostSource} 411 /> 412 </View> 413 ) 414 } else {
+2 -4
src/screens/Profile/Sections/Labels.tsx
··· 48 const t = useTheme() 49 50 const onScrollToTop = useCallback(() => { 51 - // @ts-expect-error TODO fix this 52 - scrollElRef.current?.scrollTo({ 53 animated: isNative, 54 - x: 0, 55 - y: -headerHeight, 56 }) 57 }, [scrollElRef, headerHeight]) 58
··· 48 const t = useTheme() 49 50 const onScrollToTop = useCallback(() => { 51 + scrollElRef.current?.scrollToOffset({ 52 animated: isNative, 53 + offset: -headerHeight, 54 }) 55 }, [scrollElRef, headerHeight]) 56
+1 -1
src/screens/Search/modules/ExploreTrendingTopics.tsx
··· 194 case 'new': { 195 Icon = TrendingIcon 196 text = _(msg`New`) 197 - color = t.palette.positive_700 198 backgroundColor = t.palette.positive_50 199 break 200 }
··· 194 case 'new': { 195 Icon = TrendingIcon 196 text = _(msg`New`) 197 + color = t.palette.positive_600 198 backgroundColor = t.palette.positive_50 199 break 200 }
-1
src/screens/Settings/components/AddAppPasswordDialog.tsx
··· 195 value={data.password} 196 label={_(msg`Copy App Password`)} 197 size="large" 198 - variant="solid" 199 color="secondary"> 200 <ButtonText>{data.password}</ButtonText> 201 <ButtonIcon icon={CopyIcon} />
··· 195 value={data.password} 196 label={_(msg`Copy App Password`)} 197 size="large" 198 color="secondary"> 199 <ButtonText>{data.password}</ButtonText> 200 <ButtonIcon icon={CopyIcon} />
+3 -3
src/screens/Settings/components/ChangeHandleDialog.tsx
··· 428 </Text> 429 <View style={[a.py_xs]}> 430 <CopyButton 431 - variant="solid" 432 color="secondary" 433 value="_atproto" 434 label={_(msg`Copy host`)} 435 hoverStyle={[a.bg_transparent]} 436 hitSlop={HITSLOP_10}> 437 <Text style={[a.text_md, a.flex_1]}>_atproto</Text> ··· 449 </Text> 450 <View style={[a.py_xs]}> 451 <CopyButton 452 - variant="solid" 453 color="secondary" 454 value={'did=' + currentAccount?.did} 455 label={_(msg`Copy TXT record value`)} 456 hoverStyle={[a.bg_transparent]} 457 hitSlop={HITSLOP_10}> 458 <Text style={[a.text_md, a.flex_1]}> ··· 636 a.rounded_full, 637 a.align_center, 638 a.justify_center, 639 - {backgroundColor: t.palette.positive_600}, 640 ]}> 641 <CheckIcon fill={t.palette.white} size="xs" /> 642 </View>
··· 428 </Text> 429 <View style={[a.py_xs]}> 430 <CopyButton 431 color="secondary" 432 value="_atproto" 433 label={_(msg`Copy host`)} 434 + style={[a.bg_transparent]} 435 hoverStyle={[a.bg_transparent]} 436 hitSlop={HITSLOP_10}> 437 <Text style={[a.text_md, a.flex_1]}>_atproto</Text> ··· 449 </Text> 450 <View style={[a.py_xs]}> 451 <CopyButton 452 color="secondary" 453 value={'did=' + currentAccount?.did} 454 label={_(msg`Copy TXT record value`)} 455 + style={[a.bg_transparent]} 456 hoverStyle={[a.bg_transparent]} 457 hitSlop={HITSLOP_10}> 458 <Text style={[a.text_md, a.flex_1]}> ··· 636 a.rounded_full, 637 a.align_center, 638 a.justify_center, 639 + {backgroundColor: t.palette.positive_500}, 640 ]}> 641 <CheckIcon fill={t.palette.white} size="xs" /> 642 </View>
+2 -2
src/screens/Settings/components/CopyButton.tsx
··· 58 pointerEvents="none"> 59 <Text 60 style={[ 61 - a.font_semi_bold, 62 a.text_right, 63 - a.text_md, 64 t.atoms.text_contrast_high, 65 ]}> 66 <Trans>Copied!</Trans>
··· 58 pointerEvents="none"> 59 <Text 60 style={[ 61 + a.font_medium, 62 a.text_right, 63 + a.text_sm, 64 t.atoms.text_contrast_high, 65 ]}> 66 <Trans>Copied!</Trans>
+1 -1
src/screens/Signup/StepHandle/index.tsx
··· 169 {isHandleAvailable?.available && ( 170 <CheckIcon 171 testID="handleAvailableCheck" 172 - style={[{color: t.palette.positive_600}, a.z_20]} 173 /> 174 )} 175 </TextField.Root>
··· 169 {isHandleAvailable?.available && ( 170 <CheckIcon 171 testID="handleAvailableCheck" 172 + style={[{color: t.palette.positive_500}, a.z_20]} 173 /> 174 )} 175 </TextField.Root>
+2
src/screens/VideoFeed/index.tsx
··· 93 import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check' 94 import {EyeSlash_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/EyeSlash' 95 import {Leaf_Stroke2_Corner0_Rounded as LeafIcon} from '#/components/icons/Leaf' 96 import * as Layout from '#/components/Layout' 97 import {Link} from '#/components/Link' 98 import {ListFooter} from '#/components/Lists' ··· 150 return ( 151 <ThemeProvider theme="dark"> 152 <Layout.Screen noInsetTop style={{backgroundColor: 'black'}}> 153 <SystemBars style={{statusBar: 'light', navigationBar: 'light'}} /> 154 <View 155 style={[
··· 93 import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check' 94 import {EyeSlash_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/EyeSlash' 95 import {Leaf_Stroke2_Corner0_Rounded as LeafIcon} from '#/components/icons/Leaf' 96 + import {KeepAwake} from '#/components/KeepAwake' 97 import * as Layout from '#/components/Layout' 98 import {Link} from '#/components/Link' 99 import {ListFooter} from '#/components/Lists' ··· 151 return ( 152 <ThemeProvider theme="dark"> 153 <Layout.Screen noInsetTop style={{backgroundColor: 'black'}}> 154 + <KeepAwake /> 155 <SystemBars style={{statusBar: 'light', navigationBar: 'light'}} /> 156 <View 157 style={[
+34
src/state/queries/threadgate/index.ts
··· 25 export * from '#/state/queries/threadgate/types' 26 export * from '#/state/queries/threadgate/util' 27 28 export const threadgateRecordQueryKeyRoot = 'threadgate-record' 29 export const createThreadgateRecordQueryKey = (uri: string) => [ 30 threadgateRecordQueryKeyRoot, ··· 205 }) 206 const next = await callback(prev) 207 if (!next) return 208 await writeThreadgateRecord({ 209 agent, 210 postUri, ··· 358 }, 359 }) 360 }
··· 25 export * from '#/state/queries/threadgate/types' 26 export * from '#/state/queries/threadgate/util' 27 28 + /** 29 + * Must match the threadgate lexicon record definition. 30 + */ 31 + export const MAX_HIDDEN_REPLIES = 300 32 + 33 export const threadgateRecordQueryKeyRoot = 'threadgate-record' 34 export const createThreadgateRecordQueryKey = (uri: string) => [ 35 threadgateRecordQueryKeyRoot, ··· 210 }) 211 const next = await callback(prev) 212 if (!next) return 213 + validateThreadgateRecordOrThrow(next) 214 await writeThreadgateRecord({ 215 agent, 216 postUri, ··· 364 }, 365 }) 366 } 367 + 368 + export class MaxHiddenRepliesError extends Error { 369 + constructor(message?: string) { 370 + super(message || 'Maximum number of hidden replies reached') 371 + this.name = 'MaxHiddenRepliesError' 372 + } 373 + } 374 + 375 + export class InvalidInteractionSettingsError extends Error { 376 + constructor(message?: string) { 377 + super(message || 'Invalid interaction settings') 378 + this.name = 'InvalidInteractionSettingsError' 379 + } 380 + } 381 + 382 + export function validateThreadgateRecordOrThrow( 383 + record: AppBskyFeedThreadgate.Record, 384 + ) { 385 + const result = AppBskyFeedThreadgate.validateRecord(record) 386 + 387 + if (result.success) { 388 + if ((result.value.hiddenReplies?.length ?? 0) > MAX_HIDDEN_REPLIES) { 389 + throw new MaxHiddenRepliesError() 390 + } 391 + } else { 392 + throw new InvalidInteractionSettingsError() 393 + } 394 + }
+21 -7
src/view/com/composer/text-input/TextInput.web.tsx
··· 211 const isNotSelection = view.state.selection.empty 212 if (isNotSelection) { 213 const cursorPosition = view.state.selection.$anchor.pos 214 - const textBefore = view.state.doc.textBetween(0, cursorPosition) 215 const graphemes = new Graphemer().splitGraphemes(textBefore) 216 217 if (graphemes.length > 0) { 218 const lastGrapheme = graphemes[graphemes.length - 1] 219 - const deleteFrom = cursorPosition - lastGrapheme.length 220 - editor?.commands.deleteRange({ 221 - from: deleteFrom, 222 - to: cursorPosition, 223 - }) 224 - return true 225 } 226 } 227 }
··· 211 const isNotSelection = view.state.selection.empty 212 if (isNotSelection) { 213 const cursorPosition = view.state.selection.$anchor.pos 214 + const textBefore = view.state.doc.textBetween( 215 + 0, 216 + cursorPosition, 217 + // important - use \n as a block separator, otherwise 218 + // all the lines get mushed together -sfn 219 + '\n', 220 + ) 221 const graphemes = new Graphemer().splitGraphemes(textBefore) 222 223 if (graphemes.length > 0) { 224 const lastGrapheme = graphemes[graphemes.length - 1] 225 + // deleteRange doesn't work on newlines, because tiptap 226 + // treats them as separate 'blocks' and we're using \n 227 + // as a stand-in. bail out if the last grapheme is a newline 228 + // to let the default behavior handle it -sfn 229 + if (lastGrapheme !== '\n') { 230 + // otherwise, delete the last grapheme using deleteRange, 231 + // so that emojis are deleted as a whole 232 + const deleteFrom = cursorPosition - lastGrapheme.length 233 + editor?.commands.deleteRange({ 234 + from: deleteFrom, 235 + to: cursorPosition, 236 + }) 237 + return true 238 + } 239 } 240 } 241 }
+4 -4
src/view/com/notifications/NotificationFeedItem.tsx
··· 66 import * as MediaPreview from '#/components/MediaPreview' 67 import {ProfileHoverCard} from '#/components/ProfileHoverCard' 68 import {Notification as StarterPackCard} from '#/components/StarterPack/StarterPackCard' 69 - import {SubtleWebHover} from '#/components/SubtleWebHover' 70 import {Text} from '#/components/Typography' 71 import {useSimpleVerificationState} from '#/components/verification' 72 import {VerificationCheck} from '#/components/verification/VerificationCheck' ··· 307 ) : ( 308 <Trans>{firstAuthorLink} reposted your post</Trans> 309 ) 310 - icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} /> 311 } else if (item.type === 'follow') { 312 let isFollowBack = false 313 ··· 519 ) : ( 520 <Trans>{firstAuthorLink} reposted your repost</Trans> 521 ) 522 - icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} /> 523 } else if (item.type === 'subscribed-post') { 524 const postsCount = 1 + (item.additional?.length || 0) 525 a11yLabel = hasMultipleAuthors ··· 613 }}> 614 {({hovered}) => ( 615 <> 616 - <SubtleWebHover hover={hovered} /> 617 <View style={[styles.layoutIcon, a.pr_sm]}> 618 {/* TODO: Prevent conditional rendering and move toward composable 619 notifications for clearer accessibility labeling */}
··· 66 import * as MediaPreview from '#/components/MediaPreview' 67 import {ProfileHoverCard} from '#/components/ProfileHoverCard' 68 import {Notification as StarterPackCard} from '#/components/StarterPack/StarterPackCard' 69 + import {SubtleHover} from '#/components/SubtleHover' 70 import {Text} from '#/components/Typography' 71 import {useSimpleVerificationState} from '#/components/verification' 72 import {VerificationCheck} from '#/components/verification/VerificationCheck' ··· 307 ) : ( 308 <Trans>{firstAuthorLink} reposted your post</Trans> 309 ) 310 + icon = <RepostIcon size="xl" style={{color: t.palette.positive_500}} /> 311 } else if (item.type === 'follow') { 312 let isFollowBack = false 313 ··· 519 ) : ( 520 <Trans>{firstAuthorLink} reposted your repost</Trans> 521 ) 522 + icon = <RepostIcon size="xl" style={{color: t.palette.positive_500}} /> 523 } else if (item.type === 'subscribed-post') { 524 const postsCount = 1 + (item.additional?.length || 0) 525 a11yLabel = hasMultipleAuthors ··· 613 }}> 614 {({hovered}) => ( 615 <> 616 + <SubtleHover hover={hovered} /> 617 <View style={[styles.layoutIcon, a.pr_sm]}> 618 {/* TODO: Prevent conditional rendering and move toward composable 619 notifications for clearer accessibility labeling */}
+2 -2
src/view/com/post/Post.tsx
··· 35 import {ShowMoreTextButton} from '#/components/Post/ShowMoreTextButton' 36 import {PostControls} from '#/components/PostControls' 37 import {RichText} from '#/components/RichText' 38 - import {SubtleWebHover} from '#/components/SubtleWebHover' 39 import * as bsky from '#/types/bsky' 40 41 export function Post({ ··· 167 onPointerLeave={() => { 168 setHover(false) 169 }}> 170 - <SubtleWebHover hover={hover} /> 171 {showReplyLine && <View style={styles.replyLine} />} 172 <View style={styles.layout}> 173 <View style={styles.layoutAvi}>
··· 35 import {ShowMoreTextButton} from '#/components/Post/ShowMoreTextButton' 36 import {PostControls} from '#/components/PostControls' 37 import {RichText} from '#/components/RichText' 38 + import {SubtleHover} from '#/components/SubtleHover' 39 import * as bsky from '#/types/bsky' 40 41 export function Post({ ··· 167 onPointerLeave={() => { 168 setHover(false) 169 }}> 170 + <SubtleHover hover={hover} /> 171 {showReplyLine && <View style={styles.replyLine} />} 172 <View style={styles.layout}> 173 <View style={styles.layoutAvi}>
+2 -2
src/view/com/posts/PostFeedItem.tsx
··· 58 import {DiscoverDebug} from '#/components/PostControls/DiscoverDebug' 59 import {ProfileHoverCard} from '#/components/ProfileHoverCard' 60 import {RichText} from '#/components/RichText' 61 - import {SubtleWebHover} from '#/components/SubtleWebHover' 62 import * as bsky from '#/types/bsky' 63 64 interface FeedItemProps { ··· 321 onPointerLeave={() => { 322 setHover(false) 323 }}> 324 - <SubtleWebHover hover={hover} /> 325 <View style={{flexDirection: 'row', gap: 10, paddingLeft: 8}}> 326 <View style={{width: isCarouselItem ? 0 : 42}}> 327 {isThreadChild && (
··· 58 import {DiscoverDebug} from '#/components/PostControls/DiscoverDebug' 59 import {ProfileHoverCard} from '#/components/ProfileHoverCard' 60 import {RichText} from '#/components/RichText' 61 + import {SubtleHover} from '#/components/SubtleHover' 62 import * as bsky from '#/types/bsky' 63 64 interface FeedItemProps { ··· 321 onPointerLeave={() => { 322 setHover(false) 323 }}> 324 + <SubtleHover hover={hover} /> 325 <View style={{flexDirection: 'row', gap: 10, paddingLeft: 8}}> 326 <View style={{width: isCarouselItem ? 0 : 42}}> 327 {isThreadChild && (
+2 -2
src/view/com/posts/ViewFullThread.tsx
··· 8 import {usePalette} from '#/lib/hooks/usePalette' 9 import {makeProfileLink} from '#/lib/routes/links' 10 import {useInteractionState} from '#/components/hooks/useInteractionState' 11 - import {SubtleWebHover} from '#/components/SubtleWebHover' 12 import {Link} from '../util/Link' 13 import {Text} from '../util/text/Text' 14 ··· 33 noFeedback 34 onPointerEnter={onHoverIn} 35 onPointerLeave={onHoverOut}> 36 - <SubtleWebHover 37 hover={hover} 38 // adjust position for visual alignment - the actual box has lots of top padding and not much bottom padding -sfn 39 style={{top: 8, bottom: -5}}
··· 8 import {usePalette} from '#/lib/hooks/usePalette' 9 import {makeProfileLink} from '#/lib/routes/links' 10 import {useInteractionState} from '#/components/hooks/useInteractionState' 11 + import {SubtleHover} from '#/components/SubtleHover' 12 import {Link} from '../util/Link' 13 import {Text} from '../util/text/Text' 14 ··· 33 noFeedback 34 onPointerEnter={onHoverIn} 35 onPointerLeave={onHoverOut}> 36 + <SubtleHover 37 hover={hover} 38 // adjust position for visual alignment - the actual box has lots of top padding and not much bottom padding -sfn 39 style={{top: 8, bottom: -5}}
+13 -20
src/view/com/util/LoadingPlaceholder.tsx
··· 7 type ViewStyle, 8 } from 'react-native' 9 10 - import {usePalette} from '#/lib/hooks/usePalette' 11 import {s} from '#/lib/styles' 12 - import {useTheme} from '#/lib/ThemeContext' 13 - import {atoms as a, useTheme as useTheme_NEW} from '#/alf' 14 import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' 15 import { 16 Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, ··· 27 height: DimensionValue | undefined 28 style?: StyleProp<ViewStyle> 29 }) { 30 - const theme = useTheme() 31 return ( 32 <View 33 style={[ ··· 35 { 36 width, 37 height, 38 - backgroundColor: theme.palette.default.backgroundLight, 39 }, 40 style, 41 ]} ··· 48 }: { 49 style?: StyleProp<ViewStyle> 50 }) { 51 - const t = useTheme_NEW() 52 - const pal = usePalette('default') 53 return ( 54 - <View style={[styles.post, pal.view, style]}> 55 <LoadingPlaceholder 56 width={42} 57 height={42} ··· 137 }: { 138 style?: StyleProp<ViewStyle> 139 }) { 140 - const pal = usePalette('default') 141 return ( 142 - <View style={[styles.notification, pal.view, style]}> 143 <View style={[{width: 60}, a.align_end, a.pr_sm, a.pt_2xs]}> 144 - <HeartIconFilled 145 - size="xl" 146 - style={{color: pal.colors.backgroundLight}} 147 - /> 148 </View> 149 <View style={{flex: 1}}> 150 <View style={[a.flex_row, s.mb10]}> ··· 184 }: { 185 style?: StyleProp<ViewStyle> 186 }) { 187 - const pal = usePalette('default') 188 return ( 189 - <View style={[styles.profileCard, pal.view, style]}> 190 <LoadingPlaceholder 191 width={40} 192 height={40} ··· 228 showTopBorder?: boolean 229 showLowerPlaceholder?: boolean 230 }) { 231 - const pal = usePalette('default') 232 return ( 233 <View 234 style={[ ··· 236 padding: 16, 237 borderTopWidth: showTopBorder ? StyleSheet.hairlineWidth : 0, 238 }, 239 - pal.border, 240 style, 241 ]}> 242 - <View style={[pal.view, {flexDirection: 'row'}]}> 243 <LoadingPlaceholder 244 width={36} 245 height={36} ··· 282 }: { 283 style?: StyleProp<ViewStyle> 284 }) { 285 - const t = useTheme_NEW() 286 const random = useMemo(() => Math.random(), []) 287 return ( 288 <View style={[a.flex_row, a.gap_md, a.px_lg, a.mt_lg, t.atoms.bg, style]}>
··· 7 type ViewStyle, 8 } from 'react-native' 9 10 import {s} from '#/lib/styles' 11 + import {atoms as a, useTheme} from '#/alf' 12 import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' 13 import { 14 Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, ··· 25 height: DimensionValue | undefined 26 style?: StyleProp<ViewStyle> 27 }) { 28 + const t = useTheme() 29 return ( 30 <View 31 style={[ ··· 33 { 34 width, 35 height, 36 + backgroundColor: t.palette.contrast_50, 37 }, 38 style, 39 ]} ··· 46 }: { 47 style?: StyleProp<ViewStyle> 48 }) { 49 + const t = useTheme() 50 return ( 51 + <View style={[styles.post, style]}> 52 <LoadingPlaceholder 53 width={42} 54 height={42} ··· 134 }: { 135 style?: StyleProp<ViewStyle> 136 }) { 137 + const t = useTheme() 138 return ( 139 + <View style={[styles.notification, style]}> 140 <View style={[{width: 60}, a.align_end, a.pr_sm, a.pt_2xs]}> 141 + <HeartIconFilled size="xl" style={{color: t.palette.contrast_50}} /> 142 </View> 143 <View style={{flex: 1}}> 144 <View style={[a.flex_row, s.mb10]}> ··· 178 }: { 179 style?: StyleProp<ViewStyle> 180 }) { 181 return ( 182 + <View style={[styles.profileCard, style]}> 183 <LoadingPlaceholder 184 width={40} 185 height={40} ··· 221 showTopBorder?: boolean 222 showLowerPlaceholder?: boolean 223 }) { 224 + const t = useTheme() 225 return ( 226 <View 227 style={[ ··· 229 padding: 16, 230 borderTopWidth: showTopBorder ? StyleSheet.hairlineWidth : 0, 231 }, 232 + t.atoms.border_contrast_low, 233 style, 234 ]}> 235 + <View style={[{flexDirection: 'row'}]}> 236 <LoadingPlaceholder 237 width={36} 238 height={36} ··· 275 }: { 276 style?: StyleProp<ViewStyle> 277 }) { 278 + const t = useTheme() 279 const random = useMemo(() => Math.random(), []) 280 return ( 281 <View style={[a.flex_row, a.gap_md, a.px_lg, a.mt_lg, t.atoms.bg, style]}>
+2
src/view/com/util/images/AutoSizedImage.tsx
··· 209 // alt here is what screen readers actually use 210 accessibilityLabel={image.alt} 211 accessibilityHint={_(msg`Views full image`)} 212 style={[ 213 a.w_full, 214 a.rounded_md, ··· 231 // alt here is what screen readers actually use 232 accessibilityLabel={image.alt} 233 accessibilityHint={_(msg`Views full image`)} 234 style={[a.h_full]}> 235 {contents} 236 </Pressable>
··· 209 // alt here is what screen readers actually use 210 accessibilityLabel={image.alt} 211 accessibilityHint={_(msg`Views full image`)} 212 + accessibilityRole="button" 213 style={[ 214 a.w_full, 215 a.rounded_md, ··· 232 // alt here is what screen readers actually use 233 accessibilityLabel={image.alt} 234 accessibilityHint={_(msg`Views full image`)} 235 + accessibilityRole="button" 236 style={[a.h_full]}> 237 {contents} 238 </Pressable>
+6 -9
src/view/com/util/images/ImageLayoutGrid.tsx
··· 3 import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated' 4 import {type AppBskyEmbedImages} from '@atproto/api' 5 6 - import {isAndroid} from '#/platform/detection' 7 import {atoms as a, useBreakpoints} from '#/alf' 8 import {PostEmbedViewContext} from '#/components/Post/Embed/types' 9 import {type Dimensions} from '../../lightbox/ImageViewing/@types' ··· 63 const containerRef4 = useAnimatedRef() 64 const thumbDimsRef = React.useRef<(Dimensions | null)[]>([]) 65 66 - const outerFlex = isAndroid ? a.flex_1 : a.flex_shrink 67 - 68 switch (count) { 69 case 2: { 70 const containerRefs = [containerRef1, containerRef2] 71 return ( 72 - <View style={[outerFlex, a.flex_row, gap]}> 73 - <View style={[a.flex_1, {aspectRatio: 1}]}> 74 <GalleryItem 75 {...props} 76 index={0} ··· 79 thumbDimsRef={thumbDimsRef} 80 /> 81 </View> 82 - <View style={[a.flex_1, {aspectRatio: 1}]}> 83 <GalleryItem 84 {...props} 85 index={1} ··· 95 case 3: { 96 const containerRefs = [containerRef1, containerRef2, containerRef3] 97 return ( 98 - <View style={[outerFlex, a.flex_row, gap]}> 99 - <View style={[a.flex_1, {aspectRatio: 1}]}> 100 <GalleryItem 101 {...props} 102 index={0} ··· 105 thumbDimsRef={thumbDimsRef} 106 /> 107 </View> 108 - <View style={[a.flex_1, {aspectRatio: 1}, gap]}> 109 <View style={[a.flex_1]}> 110 <GalleryItem 111 {...props}
··· 3 import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated' 4 import {type AppBskyEmbedImages} from '@atproto/api' 5 6 import {atoms as a, useBreakpoints} from '#/alf' 7 import {PostEmbedViewContext} from '#/components/Post/Embed/types' 8 import {type Dimensions} from '../../lightbox/ImageViewing/@types' ··· 62 const containerRef4 = useAnimatedRef() 63 const thumbDimsRef = React.useRef<(Dimensions | null)[]>([]) 64 65 switch (count) { 66 case 2: { 67 const containerRefs = [containerRef1, containerRef2] 68 return ( 69 + <View style={[a.flex_1, a.flex_row, gap]}> 70 + <View style={[a.flex_1, a.aspect_square]}> 71 <GalleryItem 72 {...props} 73 index={0} ··· 76 thumbDimsRef={thumbDimsRef} 77 /> 78 </View> 79 + <View style={[a.flex_1, a.aspect_square]}> 80 <GalleryItem 81 {...props} 82 index={1} ··· 92 case 3: { 93 const containerRefs = [containerRef1, containerRef2, containerRef3] 94 return ( 95 + <View style={[a.flex_1, a.flex_row, gap]}> 96 + <View style={[a.flex_1, a.aspect_square]}> 97 <GalleryItem 98 {...props} 99 index={0} ··· 102 thumbDimsRef={thumbDimsRef} 103 /> 104 </View> 105 + <View style={[a.flex_1, a.aspect_square, gap]}> 106 <View style={[a.flex_1]}> 107 <GalleryItem 108 {...props}
+2 -2
src/view/com/util/load-latest/LoadLatestBtn.tsx
··· 14 import {useInteractionState} from '#/components/hooks/useInteractionState' 15 import {ArrowTop_Stroke2_Corner0_Rounded as ArrowIcon} from '#/components/icons/Arrow' 16 import {CENTER_COLUMN_OFFSET} from '#/components/Layout' 17 - import {SubtleWebHover} from '#/components/SubtleWebHover' 18 19 export function LoadLatestBtn({ 20 onPress, ··· 91 targetScale={0.9} 92 onPointerEnter={onHoverIn} 93 onPointerLeave={onHoverOut}> 94 - <SubtleWebHover hover={hovered} style={[a.rounded_full]} /> 95 <ArrowIcon 96 size="md" 97 style={[
··· 14 import {useInteractionState} from '#/components/hooks/useInteractionState' 15 import {ArrowTop_Stroke2_Corner0_Rounded as ArrowIcon} from '#/components/icons/Arrow' 16 import {CENTER_COLUMN_OFFSET} from '#/components/Layout' 17 + import {SubtleHover} from '#/components/SubtleHover' 18 19 export function LoadLatestBtn({ 20 onPress, ··· 91 targetScale={0.9} 92 onPointerEnter={onHoverIn} 93 onPointerLeave={onHoverOut}> 94 + <SubtleHover hover={hovered} style={[a.rounded_full]} /> 95 <ArrowIcon 96 size="md" 97 style={[
+5 -5
yarn.lock
··· 3678 resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" 3679 integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== 3680 3681 - "@bsky.app/alf@^0.1.2": 3682 - version "0.1.2" 3683 - resolved "https://registry.yarnpkg.com/@bsky.app/alf/-/alf-0.1.2.tgz#8e3b3cd0b27f1dfe359d99edd2afd7d123b7ab69" 3684 - integrity sha512-lIidmkoHsqXwj07BY4fYIu/JyWGXRAGLfh65qhGzWpXLTK1DGyoQUjz5CwsqTDSQWpCfBC7eEaOtYjjv9cAjSQ== 3685 dependencies: 3686 react-responsive "^10.0.1" 3687 ··· 11297 resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.15.0.tgz#6723574814b9e6b0a90e4e23662be76123ab6ae9" 11298 integrity sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ== 11299 11300 - expo-keep-awake@~15.0.7: 11301 version "15.0.7" 11302 resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz#4eada556e1cca6c9c2e5aa39478fd01816cd0bc9" 11303 integrity sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA==
··· 3678 resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" 3679 integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== 3680 3681 + "@bsky.app/alf@^0.1.5": 3682 + version "0.1.5" 3683 + resolved "https://registry.yarnpkg.com/@bsky.app/alf/-/alf-0.1.5.tgz#8de3e128a3a490625fa24dae89f8febfe4a668b2" 3684 + integrity sha512-1FGsLTUxv4UpbO3tW/oXIEzR8If/FPkFwWkTOBvpcA9cfR73QZiXXitUojCZbiXEIl0WiL+8j3zHjpNaaxiOAA== 3685 dependencies: 3686 react-responsive "^10.0.1" 3687 ··· 11297 resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.15.0.tgz#6723574814b9e6b0a90e4e23662be76123ab6ae9" 11298 integrity sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ== 11299 11300 + expo-keep-awake@^15.0.7, expo-keep-awake@~15.0.7: 11301 version "15.0.7" 11302 resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz#4eada556e1cca6c9c2e5aa39478fd01816cd0bc9" 11303 integrity sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA==