run codemod on every file
This commit is contained in:
@@ -9,8 +9,7 @@ import {
|
||||
} from 'react'
|
||||
import {Dimensions, View} from 'react-native'
|
||||
import * as Linking from 'expo-linking'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {retry} from '#/lib/async/retry'
|
||||
@@ -132,7 +131,7 @@ export function Provider({children}: {children?: React.ReactNode}) {
|
||||
|
||||
export function RedirectOverlay() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {isOpen} = useRedirectOverlayContext()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
|
||||
@@ -162,7 +161,7 @@ export function RedirectOverlay() {
|
||||
<View
|
||||
role="dialog"
|
||||
aria-role="dialog"
|
||||
aria-label={_(msg`Verifying your age assurance status`)}>
|
||||
aria-label={l`Verifying your age assurance status`}>
|
||||
<View style={[a.pb_3xl, {width: 300}]}>
|
||||
<Inner />
|
||||
</View>
|
||||
@@ -175,7 +174,7 @@ export function RedirectOverlay() {
|
||||
function Inner() {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const agent = useAgent()
|
||||
const polling = useRef(false)
|
||||
const unmounted = useRef(false)
|
||||
@@ -262,7 +261,7 @@ function Inner() {
|
||||
|
||||
<View style={[a.w_full, a.pt_lg]}>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
@@ -318,7 +317,7 @@ function Inner() {
|
||||
{error && (
|
||||
<View style={[a.w_full, a.pt_lg]}>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
|
||||
@@ -83,7 +83,7 @@ function createLogger(
|
||||
warn: logger.warn.bind(logger),
|
||||
error: logger.error.bind(logger),
|
||||
useChild: (context: Exclude<Logger['context'], undefined>) => {
|
||||
return useMemo(() => createLogger(context, metadata), [context, metadata])
|
||||
return useMemo(() => createLogger(context, metadata), [context])
|
||||
},
|
||||
Context: Logger.Context,
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {Fragment, useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {isJwtExpired} from '#/lib/jwt'
|
||||
@@ -33,7 +32,7 @@ export function AccountList({
|
||||
}) {
|
||||
const {currentAccount, accounts} = useSession()
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {data: profiles} = useProfilesQuery({
|
||||
handles: accounts.map(acc => acc.did),
|
||||
})
|
||||
@@ -67,7 +66,7 @@ export function AccountList({
|
||||
testID="chooseAddAccountBtn"
|
||||
style={[a.flex_1]}
|
||||
onPress={pendingDid ? undefined : onPressAddAccount}
|
||||
label={_(msg`Sign in to account that is not listed`)}>
|
||||
label={l`Sign in to account that is not listed`}>
|
||||
{({hovered, pressed}) => (
|
||||
<View
|
||||
style={[
|
||||
@@ -114,7 +113,7 @@ function AccountItem({
|
||||
isPendingAccount: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {isActive: live} = useActorStatus(profile)
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
@@ -131,8 +130,8 @@ function AccountItem({
|
||||
onPress={onPress}
|
||||
label={
|
||||
isCurrentAccount
|
||||
? _(msg`Continue as ${account.handle} (currently signed in)`)
|
||||
: _(msg`Sign in as ${account.handle}`)
|
||||
? l`Continue as ${account.handle} (currently signed in)`
|
||||
: l`Sign in as ${account.handle}`
|
||||
}>
|
||||
{({hovered, pressed}) => (
|
||||
<View
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {useCallback} from 'react'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {sanitizeAppLanguageSetting} from '#/locale/helpers'
|
||||
@@ -14,7 +13,7 @@ import {Earth_Stroke2_Corner2_Rounded as EarthIcon} from './icons/Globe'
|
||||
|
||||
export function AppLanguageDropdown() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
@@ -38,7 +37,7 @@ export function AppLanguageDropdown() {
|
||||
<Select.Root
|
||||
value={sanitizeAppLanguageSetting(langPrefs.appLanguage)}
|
||||
onValueChange={onChangeAppLanguage}>
|
||||
<Select.Trigger label={_(msg`Change app language`)}>
|
||||
<Select.Trigger label={l`Change app language`}>
|
||||
{({props}) => (
|
||||
<Button
|
||||
{...props}
|
||||
@@ -60,7 +59,7 @@ export function AppLanguageDropdown() {
|
||||
]}>
|
||||
<ButtonIcon icon={EarthIcon} size="md" />
|
||||
<Select.ValueText
|
||||
placeholder={_(msg`Select an app language`)}
|
||||
placeholder={l`Select an app language`}
|
||||
style={[t.atoms.text_contrast_medium]}
|
||||
/>
|
||||
<Select.Icon style={[t.atoms.text_contrast_medium]} />
|
||||
@@ -68,7 +67,7 @@ export function AppLanguageDropdown() {
|
||||
)}
|
||||
</Select.Trigger>
|
||||
<Select.Content
|
||||
label={_(msg`Select language`)}
|
||||
label={l`Select language`}
|
||||
renderItem={({label, value}) => (
|
||||
<Select.Item value={value} label={label} style={web([a.pointer])}>
|
||||
<Select.ItemIndicator />
|
||||
|
||||
@@ -7,8 +7,7 @@ import Animated, {
|
||||
useAnimatedStyle,
|
||||
} from 'react-native-reanimated'
|
||||
import {BlurView} from 'expo-blur'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useContextMenuContext} from './context'
|
||||
@@ -32,7 +31,7 @@ export function Backdrop(props: Props) {
|
||||
}
|
||||
|
||||
function BlurredBackdrop({animation, intensity = 50, onPress}: Props) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const animatedProps = useAnimatedProps(() => ({
|
||||
intensity: interpolate(
|
||||
@@ -50,8 +49,8 @@ function BlurredBackdrop({animation, intensity = 50, onPress}: Props) {
|
||||
tint="systemMaterialDark">
|
||||
<Pressable
|
||||
style={a.flex_1}
|
||||
accessibilityLabel={_(msg`Close menu`)}
|
||||
accessibilityHint={_(msg`Tap to close context menu`)}
|
||||
accessibilityLabel={l`Close menu`}
|
||||
accessibilityHint={l`Tap to close context menu`}
|
||||
onPress={onPress}
|
||||
/>
|
||||
</AnimatedBlurView>
|
||||
@@ -60,7 +59,7 @@ function BlurredBackdrop({animation, intensity = 50, onPress}: Props) {
|
||||
|
||||
function OpacityBackdrop({animation, onPress}: Props) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => ({
|
||||
opacity: interpolate(
|
||||
@@ -76,8 +75,8 @@ function OpacityBackdrop({animation, onPress}: Props) {
|
||||
style={[a.absolute, a.inset_0, t.atoms.bg_contrast_975, animatedStyle]}>
|
||||
<Pressable
|
||||
style={a.flex_1}
|
||||
accessibilityLabel={_(msg`Close menu`)}
|
||||
accessibilityHint={_(msg`Tap to close context menu`)}
|
||||
accessibilityLabel={l`Close menu`}
|
||||
accessibilityHint={l`Tap to close context menu`}
|
||||
onPress={onPress}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
||||
@@ -5,8 +5,7 @@ import Animated, {
|
||||
type SharedValue,
|
||||
useAnimatedStyle,
|
||||
} from 'react-native-reanimated'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useContextMenuContext} from './context'
|
||||
@@ -21,7 +20,7 @@ export function Backdrop({
|
||||
onPress?: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {mode} = useContextMenuContext()
|
||||
|
||||
const reduced = mode === 'auxiliary-only'
|
||||
@@ -42,8 +41,8 @@ export function Backdrop({
|
||||
style={[a.absolute, a.inset_0, t.atoms.bg_contrast_975, animatedStyle]}>
|
||||
<Pressable
|
||||
style={a.flex_1}
|
||||
accessibilityLabel={_(msg`Close menu`)}
|
||||
accessibilityHint={_(msg`Tap to close context menu`)}
|
||||
accessibilityLabel={l`Close menu`}
|
||||
accessibilityHint={l`Tap to close context menu`}
|
||||
onPress={onPress}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
||||
@@ -45,8 +45,7 @@ import {
|
||||
import {captureRef} from 'react-native-view-shot'
|
||||
import {scheduleOnRN} from 'react-native-worklets'
|
||||
import {Image, type ImageErrorEventData} from 'expo-image'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useIsFocused} from '@react-navigation/native'
|
||||
import flattenReactChildren from 'react-keyed-flatten-children'
|
||||
|
||||
@@ -453,7 +452,7 @@ function TriggerClone({
|
||||
onDisplay: () => void
|
||||
label: string
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const animatedStyles = useAnimatedStyle(() => {
|
||||
const anim = animation.get()
|
||||
@@ -504,7 +503,7 @@ function TriggerClone({
|
||||
height: measurement.height,
|
||||
}}
|
||||
accessibilityLabel={label}
|
||||
accessibilityHint={_(msg`The subject of the context menu`)}
|
||||
accessibilityHint={l`The subject of the context menu`}
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
cachePolicy="none"
|
||||
/>
|
||||
|
||||
@@ -26,8 +26,7 @@ import Animated, {
|
||||
} from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {scheduleOnRN} from 'react-native-worklets'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||
import {logger} from '#/logger'
|
||||
@@ -386,7 +385,7 @@ export function Handle({
|
||||
fill?: string
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {screenReaderEnabled} = useA11y()
|
||||
const {close} = useDialogContext()
|
||||
|
||||
@@ -395,8 +394,8 @@ export function Handle({
|
||||
<Pressable
|
||||
accessible={screenReaderEnabled}
|
||||
onPress={() => close()}
|
||||
accessibilityLabel={_(msg`Dismiss`)}
|
||||
accessibilityHint={_(msg`Double tap to close the dialog`)}>
|
||||
accessibilityLabel={l`Dismiss`}
|
||||
accessibilityHint={l`Double tap to close the dialog`}>
|
||||
<View
|
||||
style={[
|
||||
a.rounded_sm,
|
||||
|
||||
@@ -17,8 +17,7 @@ import {
|
||||
View,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {DismissableLayer, FocusGuards, FocusScope} from 'radix-ui/internal'
|
||||
import {RemoveScrollBar} from 'react-remove-scroll-bar'
|
||||
|
||||
@@ -55,7 +54,7 @@ export function Outer({
|
||||
onClose,
|
||||
webOptions,
|
||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const {setDialogIsOpen} = useDialogStateControlContext()
|
||||
@@ -126,7 +125,7 @@ export function Outer({
|
||||
<RemoveScrollBar />
|
||||
<Pressable
|
||||
accessibilityHint={undefined}
|
||||
accessibilityLabel={_(msg`Close active dialog`)}
|
||||
accessibilityLabel={l`Close active dialog`}
|
||||
onPress={handleBackgroundPress}>
|
||||
<View
|
||||
style={[
|
||||
@@ -321,7 +320,7 @@ export function FlatListFooter({
|
||||
}
|
||||
|
||||
export function Close() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {close} = useContext(Context)
|
||||
return (
|
||||
<View
|
||||
@@ -339,7 +338,7 @@ export function Close() {
|
||||
color="secondary"
|
||||
shape="round"
|
||||
onPress={() => close()}
|
||||
label={_(msg`Close active dialog`)}>
|
||||
label={l`Close active dialog`}>
|
||||
<ButtonIcon icon={X} size="md" />
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
@@ -14,8 +14,7 @@ import {
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useA11y} from '#/state/a11y'
|
||||
|
||||
@@ -40,7 +39,7 @@ export function FocusScope({children}: {children: React.ReactNode}) {
|
||||
* remain within the active content section.
|
||||
*/
|
||||
function FocusTrap({children}: {children: React.ReactNode}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const child = useRef<View>(null)
|
||||
|
||||
/*
|
||||
@@ -84,12 +83,8 @@ function FocusTrap({children}: {children: React.ReactNode}) {
|
||||
<>
|
||||
<Pressable
|
||||
accessible
|
||||
accessibilityLabel={_(
|
||||
msg`You've reached the start of the active content.`,
|
||||
)}
|
||||
accessibilityHint={_(
|
||||
msg`Please go back, or activate this element to return to the start of the active content.`,
|
||||
)}
|
||||
accessibilityLabel={l`You've reached the start of the active content.`}
|
||||
accessibilityHint={l`Please go back, or activate this element to return to the start of the active content.`}
|
||||
accessibilityActions={[{name: 'activate', label: 'activate'}]}
|
||||
onAccessibilityAction={event => {
|
||||
switch (event.nativeEvent.actionName) {
|
||||
@@ -108,12 +103,8 @@ function FocusTrap({children}: {children: React.ReactNode}) {
|
||||
{decoratedChildren}
|
||||
</View>
|
||||
<Pressable
|
||||
accessibilityLabel={_(
|
||||
msg`You've reached the end of the active content.`,
|
||||
)}
|
||||
accessibilityHint={_(
|
||||
msg`Please go back, or activate this element to return to the start of the active content.`,
|
||||
)}
|
||||
accessibilityLabel={l`You've reached the end of the active content.`}
|
||||
accessibilityHint={l`Please go back, or activate this element to return to the start of the active content.`}
|
||||
accessibilityActions={[{name: 'activate', label: 'activate'}]}
|
||||
onAccessibilityAction={event => {
|
||||
switch (event.nativeEvent.actionName) {
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
View,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView'
|
||||
@@ -46,7 +45,7 @@ export function InterestTabs({
|
||||
gutterWidth?: number
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const listRef = useRef<ScrollView>(null)
|
||||
const [totalWidth, setTotalWidth] = useState(0)
|
||||
const [scrollX, setScrollX] = useState(0)
|
||||
@@ -255,7 +254,7 @@ export function InterestTabs({
|
||||
}),
|
||||
]}>
|
||||
<Button
|
||||
label={_(msg`Scroll left`)}
|
||||
label={l`Scroll left`}
|
||||
onPress={scrollLeft}
|
||||
onPressIn={() => startContinuousScroll('left')}
|
||||
onPressOut={stopContinuousScroll}
|
||||
@@ -289,7 +288,7 @@ export function InterestTabs({
|
||||
}),
|
||||
]}>
|
||||
<Button
|
||||
label={_(msg`Scroll right`)}
|
||||
label={l`Scroll right`}
|
||||
onPress={scrollRight}
|
||||
onPressIn={() => startContinuousScroll('right')}
|
||||
onPressOut={stopContinuousScroll}
|
||||
@@ -327,22 +326,18 @@ function Tab({
|
||||
onLayout: (index: number, x: number, width: number) => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const label = active
|
||||
? _(
|
||||
msg({
|
||||
message: `"${interestsDisplayName}" category (active)`,
|
||||
comment:
|
||||
'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is currently selected.',
|
||||
}),
|
||||
)
|
||||
: _(
|
||||
msg({
|
||||
message: `Select "${interestsDisplayName}" category`,
|
||||
comment:
|
||||
'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is not currently active and can be selected.',
|
||||
}),
|
||||
)
|
||||
? l({
|
||||
message: `"${interestsDisplayName}" category (active)`,
|
||||
comment:
|
||||
'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is currently selected.',
|
||||
})
|
||||
: l({
|
||||
message: `Select "${interestsDisplayName}" category`,
|
||||
comment:
|
||||
'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is not currently active and can be selected.',
|
||||
})
|
||||
|
||||
return (
|
||||
<View
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {Fragment, useMemo} from 'react'
|
||||
import {Text as RNText} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {
|
||||
type CountryCode,
|
||||
@@ -28,7 +27,7 @@ export function InternationalPhoneCodeSelect({
|
||||
value?: CountryCode
|
||||
onChange: (value: CountryCode) => void
|
||||
}) {
|
||||
const {_, i18n} = useLingui()
|
||||
const {t: l, i18n} = useLingui()
|
||||
const location = useGeolocation()
|
||||
|
||||
const defaultCountry = useMemo(() => {
|
||||
@@ -65,7 +64,7 @@ export function InternationalPhoneCodeSelect({
|
||||
|
||||
return (
|
||||
<Select.Root value={value} onValueChange={onChange as (v: string) => void}>
|
||||
<Select.Trigger label={_(msg`Select telephone code`)}>
|
||||
<Select.Trigger label={l`Select telephone code`}>
|
||||
<Select.ValueText placeholder="+..." webOverrideValue={selected}>
|
||||
{selected => (
|
||||
<>
|
||||
@@ -77,7 +76,7 @@ export function InternationalPhoneCodeSelect({
|
||||
<Select.Icon />
|
||||
</Select.Trigger>
|
||||
<Select.Content
|
||||
label={_(msg`Country code`)}
|
||||
label={l`Country code`}
|
||||
items={items}
|
||||
renderItem={item => (
|
||||
<Fragment key={item.value}>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
|
||||
import {getLabelingServiceTitle} from '#/lib/moderation'
|
||||
@@ -52,14 +51,14 @@ export function Title({value}: {value: string}) {
|
||||
}
|
||||
|
||||
export function Description({value, handle}: {value?: string; handle: string}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
return value ? (
|
||||
<Text numberOfLines={2}>
|
||||
<RichText value={value} />
|
||||
</Text>
|
||||
) : (
|
||||
<Text emoji style={[a.leading_snug]}>
|
||||
{_(msg`By ${sanitizeHandle(handle, '@')}`)}
|
||||
{l`By ${sanitizeHandle(handle, '@')}`}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
@@ -150,7 +149,7 @@ export function Link({
|
||||
children,
|
||||
labeler,
|
||||
}: LabelingServiceProps & Pick<LinkProps, 'children'>) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<InternalLink
|
||||
@@ -160,9 +159,7 @@ export function Link({
|
||||
name: labeler.creator.did,
|
||||
},
|
||||
}}
|
||||
label={_(
|
||||
msg`View the labeling service provided by @${labeler.creator.handle}`,
|
||||
)}>
|
||||
label={l`View the labeling service provided by @${labeler.creator.handle}`}>
|
||||
{children}
|
||||
</InternalLink>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {sanitizeAppLanguageSetting} from '#/locale/helpers'
|
||||
import {APP_LANGUAGES} from '#/locale/languages'
|
||||
@@ -21,7 +20,7 @@ export function LanguageSelect({
|
||||
label?: string
|
||||
disabledBlueskySupportedLanguageSanitization?: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const selectValue =
|
||||
value && !disabledBlueskySupportedLanguageSanitization
|
||||
? sanitizeAppLanguageSetting(value)
|
||||
@@ -38,8 +37,8 @@ export function LanguageSelect({
|
||||
|
||||
return (
|
||||
<Select.Root value={selectValue} onValueChange={handleOnChange}>
|
||||
<Select.Trigger label={_(msg`Select language`)}>
|
||||
<Select.ValueText placeholder={_(msg`Select language`)} />
|
||||
<Select.Trigger label={l`Select language`}>
|
||||
<Select.ValueText placeholder={l`Select language`} />
|
||||
<Select.Icon />
|
||||
</Select.Trigger>
|
||||
<Select.Content
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {createContext, useCallback, useContext} from 'react'
|
||||
import {type GestureResponderEvent, Keyboard, View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
@@ -112,7 +111,7 @@ export function Slot({children}: {children?: React.ReactNode}) {
|
||||
}
|
||||
|
||||
export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const onPressBack = useCallback(
|
||||
@@ -131,7 +130,7 @@ export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
||||
return (
|
||||
<Slot>
|
||||
<Button
|
||||
label={_(msg`Go back`)}
|
||||
label={l`Go back`}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
@@ -151,7 +150,7 @@ export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
||||
}
|
||||
|
||||
export function MenuButton() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const setDrawerOpen = useSetDrawerOpen()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -165,7 +164,7 @@ export function MenuButton() {
|
||||
return gtMobile ? null : (
|
||||
<Slot>
|
||||
<Button
|
||||
label={_(msg`Open drawer menu`)}
|
||||
label={l`Open drawer menu`}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {type AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
@@ -27,7 +26,7 @@ function keyExtractor(item: GetLikes.Like) {
|
||||
}
|
||||
|
||||
export function LikedByList({uri}: {uri: string}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const [isPTRing, setIsPTRing] = useState(false)
|
||||
|
||||
@@ -81,10 +80,8 @@ export function LikedByList({uri}: {uri: string}) {
|
||||
isLoading={isUriLoading || isLikedByLoading}
|
||||
isError={isError}
|
||||
emptyType="results"
|
||||
emptyTitle={_(msg`No likes yet`)}
|
||||
emptyMessage={_(
|
||||
msg`Nobody has liked this yet. Maybe you should be the first!`,
|
||||
)}
|
||||
emptyTitle={l`No likes yet`}
|
||||
emptyMessage={l`Nobody has liked this yet. Maybe you should be the first!`}
|
||||
errorMessage={cleanError(resolveError || error)}
|
||||
onRetry={isError ? refetch : undefined}
|
||||
topBorder={false}
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
moderateUserList,
|
||||
type ModerationUI,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
@@ -115,7 +114,7 @@ export function TitleAndByline({
|
||||
modUi?: ModerationUI
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
return (
|
||||
@@ -142,15 +141,14 @@ export function TitleAndByline({
|
||||
</Text>
|
||||
</Hider.Content>
|
||||
</Hider.Outer>
|
||||
|
||||
{creator && (
|
||||
<Text
|
||||
emoji
|
||||
style={[a.leading_snug, t.atoms.text_contrast_medium]}
|
||||
numberOfLines={1}>
|
||||
{purpose === MODLIST
|
||||
? _(msg`Moderation list by ${sanitizeHandle(creator.handle, '@')}`)
|
||||
: _(msg`List by ${sanitizeHandle(creator.handle, '@')}`)}
|
||||
? l`Moderation list by ${sanitizeHandle(creator.handle, '@')}`
|
||||
: l`List by ${sanitizeHandle(creator.handle, '@')}`}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {memo} from 'react'
|
||||
import {type StyleProp, View, type ViewStyle} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
@@ -75,7 +74,7 @@ function ListFooterMaybeError({
|
||||
onRetry?: () => Promise<unknown>
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
if (!error) return null
|
||||
|
||||
@@ -101,7 +100,7 @@ function ListFooterMaybeError({
|
||||
</Text>
|
||||
<Button
|
||||
variant="solid"
|
||||
label={_(msg`Press to retry`)}
|
||||
label={l`Press to retry`}
|
||||
style={[
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
@@ -156,7 +155,7 @@ let ListMaybePlaceholder = ({
|
||||
useEmptyState?: boolean
|
||||
}): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {gtMobile, gtTablet} = useBreakpoints()
|
||||
|
||||
if (isLoading) {
|
||||
@@ -181,8 +180,8 @@ let ListMaybePlaceholder = ({
|
||||
if (isError) {
|
||||
return (
|
||||
<Error
|
||||
title={errorTitle ?? _(msg`Oops!`)}
|
||||
message={errorMessage ?? _(msg`Something went wrong!`)}
|
||||
title={errorTitle ?? l`Oops!`}
|
||||
message={errorMessage ?? l`Something went wrong!`}
|
||||
onRetry={onRetry}
|
||||
onGoBack={onGoBack}
|
||||
hideBackButton={hideBackButton}
|
||||
@@ -199,9 +198,7 @@ let ListMaybePlaceholder = ({
|
||||
icon={emptyStateIcon}
|
||||
message={
|
||||
emptyMessage ??
|
||||
(emptyType === 'results'
|
||||
? _(msg`No results found`)
|
||||
: _(msg`Page not found`))
|
||||
(emptyType === 'results' ? l`No results found` : l`Page not found`)
|
||||
}
|
||||
button={emptyStateButton}
|
||||
/>
|
||||
@@ -214,13 +211,11 @@ let ListMaybePlaceholder = ({
|
||||
<Error
|
||||
title={
|
||||
emptyTitle ??
|
||||
(emptyType === 'results'
|
||||
? _(msg`No results found`)
|
||||
: _(msg`Page not found`))
|
||||
(emptyType === 'results' ? l`No results found` : l`Page not found`)
|
||||
}
|
||||
message={
|
||||
emptyMessage ??
|
||||
_(msg`We're sorry! We can't find the page you were looking for.`)
|
||||
l`We're sorry! We can't find the page you were looking for.`
|
||||
}
|
||||
onRetry={onRetry}
|
||||
onGoBack={onGoBack}
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
View,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {DropdownMenu} from 'radix-ui'
|
||||
|
||||
import {useA11y} from '#/state/a11y'
|
||||
@@ -62,7 +61,7 @@ export function Root({
|
||||
}: React.PropsWithChildren<{
|
||||
control?: Dialog.DialogControlProps
|
||||
}>) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const defaultControl = useMenuControl()
|
||||
const context = useMemo<ContextType>(
|
||||
() => ({
|
||||
@@ -89,9 +88,7 @@ export function Root({
|
||||
style={[a.fixed, a.inset_0, a.z_50]}
|
||||
onPress={() => context.control.close()}
|
||||
accessibilityHint=""
|
||||
accessibilityLabel={_(
|
||||
msg`Context menu backdrop, click to close the menu.`,
|
||||
)}
|
||||
accessibilityLabel={l`Context menu backdrop, click to close the menu.`}
|
||||
/>
|
||||
</Portal>
|
||||
)}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs, moderateProfile} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {differenceInSeconds} from 'date-fns'
|
||||
|
||||
@@ -28,7 +27,7 @@ export function NewskieDialog({
|
||||
disabled?: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const control = useDialogControl()
|
||||
|
||||
const createdAt = profile.createdAt
|
||||
@@ -45,9 +44,7 @@ export function NewskieDialog({
|
||||
<View style={[a.pr_2xs]}>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
label={_(
|
||||
msg`This user is new here. Press for more info about when they joined.`,
|
||||
)}
|
||||
label={l`This user is new here. Press for more info about when they joined.`}
|
||||
hitSlop={HITSLOP_10}
|
||||
onPress={control.open}>
|
||||
{({hovered, pressed}) => (
|
||||
@@ -60,7 +57,6 @@ export function NewskieDialog({
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<DialogInner profile={profile} createdAt={createdAt} now={now} />
|
||||
@@ -79,7 +75,7 @@ function DialogInner({
|
||||
now: number
|
||||
}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const {currentAccount} = useSession()
|
||||
@@ -100,26 +96,22 @@ function DialogInner({
|
||||
|
||||
if (isMe) {
|
||||
if (profile.joinedViaStarterPack) {
|
||||
return _(
|
||||
msg`You joined Bluesky using a starter pack ${timeAgoString} ago`,
|
||||
)
|
||||
return l`You joined Bluesky using a starter pack ${timeAgoString} ago`
|
||||
} else {
|
||||
return _(msg`You joined Bluesky ${timeAgoString} ago`)
|
||||
return l`You joined Bluesky ${timeAgoString} ago`
|
||||
}
|
||||
} else {
|
||||
if (profile.joinedViaStarterPack) {
|
||||
return _(
|
||||
msg`${profileName} joined Bluesky using a starter pack ${timeAgoString} ago`,
|
||||
)
|
||||
return l`${profileName} joined Bluesky using a starter pack ${timeAgoString} ago`
|
||||
} else {
|
||||
return _(msg`${profileName} joined Bluesky ${timeAgoString} ago`)
|
||||
return l`${profileName} joined Bluesky ${timeAgoString} ago`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`New user info dialog`)}
|
||||
label={l`New user info dialog`}
|
||||
style={web({maxWidth: 400})}>
|
||||
<View style={[a.gap_md]}>
|
||||
<View style={[a.align_center]}>
|
||||
@@ -166,7 +158,7 @@ function DialogInner({
|
||||
|
||||
{IS_NATIVE && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
color="secondary"
|
||||
size="small"
|
||||
style={[a.mt_sm]}
|
||||
@@ -177,7 +169,6 @@ function DialogInner({
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useA11y} from '#/state/a11y'
|
||||
@@ -16,7 +15,7 @@ import {IS_ANDROID} from '#/env'
|
||||
|
||||
export function Content({state}: {state: PolicyUpdateState}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {screenReaderEnabled} = useA11y()
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
@@ -28,27 +27,27 @@ export function Content({state}: {state: PolicyUpdateState}) {
|
||||
terms: {
|
||||
overridePresentation: false,
|
||||
to: `https://bsky.social/about/support/tos`,
|
||||
label: _(msg`Terms of Service`),
|
||||
label: l`Terms of Service`,
|
||||
},
|
||||
privacy: {
|
||||
overridePresentation: false,
|
||||
to: `https://bsky.social/about/support/privacy-policy`,
|
||||
label: _(msg`Privacy Policy`),
|
||||
label: l`Privacy Policy`,
|
||||
},
|
||||
copyright: {
|
||||
overridePresentation: false,
|
||||
to: `https://bsky.social/about/support/copyright`,
|
||||
label: _(msg`Copyright Policy`),
|
||||
label: l`Copyright Policy`,
|
||||
},
|
||||
guidelines: {
|
||||
overridePresentation: false,
|
||||
to: `https://bsky.social/about/support/community-guidelines`,
|
||||
label: _(msg`Community Guidelines`),
|
||||
label: l`Community Guidelines`,
|
||||
},
|
||||
blog: {
|
||||
overridePresentation: false,
|
||||
to: `https://bsky.social/about/blog/08-14-2025-updated-terms-and-policies`,
|
||||
label: _(msg`Our blog post`),
|
||||
label: l`Our blog post`,
|
||||
},
|
||||
}
|
||||
const linkButtonStyles = {
|
||||
@@ -58,10 +57,8 @@ export function Content({state}: {state: PolicyUpdateState}) {
|
||||
} as const
|
||||
|
||||
const label = IS_ANDROID
|
||||
? _(
|
||||
msg`We’re updating our Terms of Service, Privacy Policy, and Copyright Policy, effective September 15th, 2025. We're also updating our Community Guidelines, and we want your input! These new guidelines will take effect on October 15th, 2025. Learn more about these changes and how to share your thoughts with us by reading our blog post.`,
|
||||
)
|
||||
: _(msg`We're updating our policies`)
|
||||
? l`We’re updating our Terms of Service, Privacy Policy, and Copyright Policy, effective September 15th, 2025. We're also updating our Community Guidelines, and we want your input! These new guidelines will take effect on October 15th, 2025. Learn more about these changes and how to share your thoughts with us by reading our blog post.`
|
||||
: l`We're updating our policies`
|
||||
|
||||
return (
|
||||
<Overlay label={label}>
|
||||
@@ -160,10 +157,8 @@ export function Content({state}: {state: PolicyUpdateState}) {
|
||||
|
||||
<View style={[a.w_full, a.gap_md]}>
|
||||
<Button
|
||||
label={_(msg`Continue`)}
|
||||
accessibilityHint={_(
|
||||
msg`Tap to acknowledge that you understand and agree to these updates and continue using Bluesky`,
|
||||
)}
|
||||
label={l`Continue`}
|
||||
accessibilityHint={l`Tap to acknowledge that you understand and agree to these updates and continue using Bluesky`}
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={handleClose}>
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {type AppBskyEmbedExternal} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||
@@ -27,7 +26,7 @@ export function ExternalGif({
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const externalEmbedsPrefs = useExternalEmbedsPrefs()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const consentDialogControl = useDialogControl()
|
||||
|
||||
// Tracking if the placer has been activated
|
||||
@@ -106,8 +105,8 @@ export function ExternalGif({
|
||||
]}
|
||||
onPress={onPlayPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint={_(msg`Plays the GIF`)}
|
||||
accessibilityLabel={_(msg`Play ${link.title}`)}>
|
||||
accessibilityHint={l`Plays the GIF`}
|
||||
accessibilityLabel={l`Play ${link.title}`}>
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
|
||||
@@ -16,8 +16,7 @@ import {WebView} from 'react-native-webview'
|
||||
import {scheduleOnRN} from 'react-native-worklets'
|
||||
import {Image} from 'expo-image'
|
||||
import {type AppBskyEmbedExternal} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
@@ -49,7 +48,7 @@ function PlaceholderOverlay({
|
||||
isPlayerActive: boolean
|
||||
onPress: (event: GestureResponderEvent) => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
// If the player is active and not loading, we don't want to show the overlay.
|
||||
if (isPlayerActive && !isLoading) return null
|
||||
@@ -58,8 +57,8 @@ function PlaceholderOverlay({
|
||||
<View style={[a.absolute, a.inset_0, {zIndex: 2}]}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Play Video`)}
|
||||
accessibilityHint={_(msg`Plays the video`)}
|
||||
accessibilityLabel={l`Play Video`}
|
||||
accessibilityHint={l`Plays the video`}
|
||||
onPress={onPress}
|
||||
style={[a.flex_1, a.justify_center, a.align_center]}>
|
||||
{!isPlayerActive ? (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useRef, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||
import {useAutoplayDisabled} from '#/state/preferences'
|
||||
@@ -27,7 +26,7 @@ export function GifEmbed({
|
||||
hideAlt?: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const autoplayDisabled = useAutoplayDisabled()
|
||||
|
||||
const playerRef = useRef<GifView>(null)
|
||||
@@ -82,7 +81,7 @@ export function GifEmbed({
|
||||
autoplay={!autoplayDisabled}
|
||||
onPlayerStateChange={onPlayerStateChange}
|
||||
ref={playerRef}
|
||||
accessibilityHint={_(msg`Animated GIF`)}
|
||||
accessibilityHint={l`Animated GIF`}
|
||||
accessibilityLabel={altText}
|
||||
/>
|
||||
{!playerState.isPlaying && (
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useMemo} from 'react'
|
||||
import {type StyleProp, View, type ViewStyle} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {type AppBskyEmbedExternal} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {parseAltFromGIFDescription} from '#/lib/gif-alt-text'
|
||||
import {useHaptics} from '#/lib/haptics'
|
||||
@@ -35,7 +34,7 @@ export const ExternalEmbed = ({
|
||||
style?: StyleProp<ViewStyle>
|
||||
hideAlt?: boolean
|
||||
}) => {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const playHaptic = useHaptics()
|
||||
const externalEmbedPrefs = useExternalEmbedsPrefs()
|
||||
@@ -85,7 +84,7 @@ export const ExternalEmbed = ({
|
||||
|
||||
return (
|
||||
<Link
|
||||
label={link.title || _(msg`Open link to ${niceUrl}`)}
|
||||
label={link.title || l`Open link to ${niceUrl}`}
|
||||
to={link.uri}
|
||||
shouldProxy={true}
|
||||
peek
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {ActivityIndicator, View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
@@ -22,15 +21,15 @@ export function GifPresentationControls({
|
||||
isLoading?: boolean
|
||||
altText?: string
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const largeBadge = useLargeAltBadgeEnabled()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
label={isPlaying ? _(msg`Pause GIF`) : _(msg`Play GIF`)}
|
||||
accessibilityHint={_(msg`Plays or pauses the GIF`)}
|
||||
label={isPlaying ? l`Pause GIF` : l`Play GIF`}
|
||||
accessibilityHint={l`Plays or pauses the GIF`}
|
||||
style={[
|
||||
a.absolute,
|
||||
a.align_center,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {type StyleProp, type ViewStyle} from 'react-native'
|
||||
import {View} from 'react-native'
|
||||
import {msg, plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Text} from '#/components/Typography'
|
||||
@@ -18,7 +18,7 @@ export function TimeIndicator({
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
if (isNaN(time)) {
|
||||
return null
|
||||
@@ -30,12 +30,10 @@ export function TimeIndicator({
|
||||
return (
|
||||
<View
|
||||
pointerEvents="none"
|
||||
accessibilityLabel={_(
|
||||
msg`Time remaining: ${plural(Number(time) || 0, {
|
||||
one: '# second',
|
||||
other: '# seconds',
|
||||
})}`,
|
||||
)}
|
||||
accessibilityLabel={l`Time remaining: ${plural(Number(time) || 0, {
|
||||
one: '# second',
|
||||
other: '# seconds',
|
||||
})}`}
|
||||
accessibilityHint=""
|
||||
style={[
|
||||
{
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useImperativeHandle, useRef, useState} from 'react'
|
||||
import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native'
|
||||
import {type AppBskyEmbedVideo} from '@atproto/api'
|
||||
import {BlueskyVideoView} from '@bsky.app/video'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {HITSLOP_30} from '#/lib/constants'
|
||||
import {useAutoplayDisabled} from '#/state/preferences'
|
||||
@@ -39,7 +38,7 @@ export function VideoEmbedInnerNative({
|
||||
*/
|
||||
onError?: (error: string) => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const videoRef = useRef<BlueskyVideoView>(null)
|
||||
const autoplayDisabled = useAutoplayDisabled()
|
||||
const isWithinMessage = useIsWithinMessage()
|
||||
@@ -91,9 +90,7 @@ export function VideoEmbedInnerNative({
|
||||
setError(e.nativeEvent.error)
|
||||
}}
|
||||
ref={videoRef}
|
||||
accessibilityLabel={
|
||||
embed.alt ? _(msg`Video: ${embed.alt}`) : _(msg`Video`)
|
||||
}
|
||||
accessibilityLabel={embed.alt ? l`Video: ${embed.alt}` : l`Video`}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
{isGif ? (
|
||||
@@ -144,7 +141,7 @@ function VideoPresentationControls({
|
||||
timeRemaining: number
|
||||
isPlaying: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const [muted] = useVideoMuteState()
|
||||
|
||||
@@ -159,14 +156,14 @@ function VideoPresentationControls({
|
||||
<Pressable
|
||||
onPress={enterFullscreen}
|
||||
style={a.flex_1}
|
||||
accessibilityLabel={_(msg`Video`)}
|
||||
accessibilityHint={_(msg`Enters full screen`)}
|
||||
accessibilityLabel={l`Video`}
|
||||
accessibilityHint={l`Enters full screen`}
|
||||
accessibilityRole="button"
|
||||
/>
|
||||
<ControlButton
|
||||
onPress={togglePlayback}
|
||||
label={isPlaying ? _(msg`Pause`) : _(msg`Play`)}
|
||||
accessibilityHint={_(msg`Plays or pauses the video`)}
|
||||
label={isPlaying ? l`Pause` : l`Play`}
|
||||
accessibilityHint={l`Plays or pauses the video`}
|
||||
style={{left: 6}}>
|
||||
{isPlaying ? (
|
||||
<PauseIcon width={13} fill={t.palette.white} />
|
||||
@@ -175,15 +172,14 @@ function VideoPresentationControls({
|
||||
)}
|
||||
</ControlButton>
|
||||
{showTime && <TimeIndicator time={timeRemaining} style={{left: 33}} />}
|
||||
|
||||
<ControlButton
|
||||
onPress={toggleMuted}
|
||||
label={
|
||||
muted
|
||||
? _(msg({message: `Unmute`, context: 'video'}))
|
||||
: _(msg({message: `Mute`, context: 'video'}))
|
||||
? l({message: `Unmute`, context: 'video'})
|
||||
: l({message: `Mute`, context: 'video'})
|
||||
}
|
||||
accessibilityHint={_(msg`Toggles the sound`)}
|
||||
accessibilityHint={l`Toggles the sound`}
|
||||
style={{right: 6}}>
|
||||
{muted ? (
|
||||
<MuteIcon width={13} fill={t.palette.white} />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useEffect, useId, useRef, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import type * as HlsTypes from 'hls.js'
|
||||
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
@@ -36,7 +35,7 @@ export function VideoEmbedInnerWeb({
|
||||
const [hasSubtitleTrack, setHasSubtitleTrack] = useState(false)
|
||||
const [hlsLoading, setHlsLoading] = useState(false)
|
||||
const figId = useId()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const [isFullscreen] = useFullscreen(containerRef)
|
||||
const isGif = embed.presentation === 'gif'
|
||||
|
||||
@@ -63,7 +62,7 @@ export function VideoEmbedInnerWeb({
|
||||
return (
|
||||
<View
|
||||
style={[a.flex_1, a.rounded_md, a.overflow_hidden]}
|
||||
accessibilityLabel={_(msg`Embedded video player`)}
|
||||
accessibilityLabel={l`Embedded video player`}
|
||||
accessibilityHint="">
|
||||
<div ref={containerRef} style={{height: '100%', width: '100%'}}>
|
||||
<figure style={{margin: 0, position: 'absolute', inset: 0}}>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -46,14 +45,14 @@ export function Text({children}: {children: React.ReactNode}) {
|
||||
}
|
||||
|
||||
export function RetryButton({onPress}: {onPress: () => void}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<Button
|
||||
onPress={onPress}
|
||||
size="small"
|
||||
color="secondary_inverted"
|
||||
label={_(msg`Retry`)}>
|
||||
label={l`Retry`}>
|
||||
<ButtonIcon icon={ArrowRotateIcon} />
|
||||
<ButtonText>
|
||||
<Trans>Retry</Trans>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useEffect, useRef, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {clamp} from '#/lib/numbers'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -30,7 +29,7 @@ export function Scrubber({
|
||||
togglePlayPause: () => void
|
||||
drawFocus: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const [scrubberActive, setScrubberActive] = useState(false)
|
||||
const {
|
||||
@@ -192,16 +191,12 @@ export function Scrubber({
|
||||
</View>
|
||||
<div
|
||||
ref={circleRef}
|
||||
aria-label={_(
|
||||
msg`Seek slider. Use the arrow keys to seek forwards and backwards, and space to play/pause`,
|
||||
)}
|
||||
aria-label={l`Seek slider. Use the arrow keys to seek forwards and backwards, and space to play/pause`}
|
||||
role="slider"
|
||||
aria-valuemax={duration}
|
||||
aria-valuemin={0}
|
||||
aria-valuenow={currentTime}
|
||||
aria-valuetext={_(
|
||||
msg`${formatTime(currentTime)} of ${formatTime(duration)}`,
|
||||
)}
|
||||
aria-valuetext={l`${formatTime(currentTime)} of ${formatTime(duration)}`}
|
||||
tabIndex={0}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
|
||||
+9
-14
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useEffect, useRef, useState} from 'react'
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {clamp} from '#/lib/numbers'
|
||||
@@ -64,7 +63,7 @@ export function Controls({
|
||||
canPlay,
|
||||
} = useVideoElement(videoRef)
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const subtitlesEnabled = useSubtitlesEnabled()
|
||||
const setSubtitlesEnabled = useSetSubtitlesEnabled()
|
||||
const {
|
||||
@@ -326,11 +325,7 @@ export function Controls({
|
||||
onPointerMove={onPointerMoveEmptySpace}
|
||||
onPointerLeave={onPointerLeaveEmptySpace}
|
||||
accessibilityLabel={
|
||||
!focused
|
||||
? _(msg`Unmute video`)
|
||||
: playing
|
||||
? _(msg`Pause video`)
|
||||
: _(msg`Play video`)
|
||||
!focused ? l`Unmute video` : playing ? l`Pause video` : l`Play video`
|
||||
}
|
||||
accessibilityHint=""
|
||||
style={[
|
||||
@@ -378,8 +373,8 @@ export function Controls({
|
||||
]}>
|
||||
<ControlButton
|
||||
active={playing}
|
||||
activeLabel={_(msg`Pause`)}
|
||||
inactiveLabel={_(msg`Play`)}
|
||||
activeLabel={l`Pause`}
|
||||
inactiveLabel={l`Play`}
|
||||
activeIcon={PauseIcon}
|
||||
inactiveIcon={PlayIcon}
|
||||
onPress={onPressPlayPause}
|
||||
@@ -397,8 +392,8 @@ export function Controls({
|
||||
{hasSubtitleTrack && (
|
||||
<ControlButton
|
||||
active={subtitlesEnabled}
|
||||
activeLabel={_(msg`Disable captions`)}
|
||||
inactiveLabel={_(msg`Enable captions`)}
|
||||
activeLabel={l`Disable captions`}
|
||||
inactiveLabel={l`Enable captions`}
|
||||
activeIcon={CCActiveIcon}
|
||||
inactiveIcon={CCInactiveIcon}
|
||||
onPress={onPressSubtitles}
|
||||
@@ -415,8 +410,8 @@ export function Controls({
|
||||
{!IS_WEB_MOBILE_IOS && (
|
||||
<ControlButton
|
||||
active={isFullscreen}
|
||||
activeLabel={_(msg`Exit fullscreen`)}
|
||||
inactiveLabel={_(msg`Enter fullscreen`)}
|
||||
activeLabel={l`Exit fullscreen`}
|
||||
inactiveLabel={l`Enter fullscreen`}
|
||||
activeIcon={ArrowsInIcon}
|
||||
inactiveIcon={ArrowsOutIcon}
|
||||
onPress={onPressFullscreen}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
|
||||
@@ -26,7 +25,7 @@ export function VolumeControl({
|
||||
onEndHover: () => void
|
||||
drawFocus: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const [volume, setVolume] = useVideoVolumeState()
|
||||
|
||||
const onVolumeChange = useCallback(
|
||||
@@ -77,7 +76,7 @@ export function VolumeControl({
|
||||
min={0}
|
||||
max={100}
|
||||
value={sliderVolume}
|
||||
aria-label={_(msg`Volume`)}
|
||||
aria-label={l`Volume`}
|
||||
style={
|
||||
// Ridiculous safari hack for old version of safari. Fixed in sonoma beta -h
|
||||
IS_WEB_SAFARI
|
||||
@@ -93,8 +92,8 @@ export function VolumeControl({
|
||||
)}
|
||||
<ControlButton
|
||||
active={muted || volume === 0}
|
||||
activeLabel={_(msg({message: `Unmute`, context: 'video'}))}
|
||||
inactiveLabel={_(msg({message: `Mute`, context: 'video'}))}
|
||||
activeLabel={l({message: `Unmute`, context: 'video'})}
|
||||
inactiveLabel={l({message: `Mute`, context: 'video'})}
|
||||
activeIcon={MuteIcon}
|
||||
inactiveIcon={UnmuteIcon}
|
||||
onPress={onPressMute}
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useCallback, useEffect, useRef, useState} from 'react'
|
||||
import {ActivityIndicator, View} from 'react-native'
|
||||
import {ImageBackground} from 'expo-image'
|
||||
import {type AppBskyEmbedVideo} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {
|
||||
@@ -70,7 +69,7 @@ export function VideoEmbed({embed}: Props) {
|
||||
}
|
||||
|
||||
function InnerWrapper({embed}: Props) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const ref = useRef<{togglePlayback: () => void}>(null)
|
||||
|
||||
@@ -175,7 +174,7 @@ function InnerWrapper({embed}: Props) {
|
||||
onPress={() => {
|
||||
ref.current?.togglePlayback()
|
||||
}}
|
||||
label={_(msg`Play video`)}>
|
||||
label={l`Play video`}>
|
||||
{showSpinner ? (
|
||||
<View style={[a.align_center, a.justify_center]}>
|
||||
<ActivityIndicator size="large" color="white" />
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyEmbedVideo} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -288,7 +287,7 @@ function VideoError({
|
||||
error: unknown
|
||||
retry: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
|
||||
let showRetryButton = true
|
||||
@@ -296,16 +295,14 @@ function VideoError({
|
||||
let errorClass: string
|
||||
|
||||
if (error instanceof VideoNotFoundError) {
|
||||
text = _(msg`Video not found.`)
|
||||
text = l`Video not found.`
|
||||
errorClass = 'VideoNotFoundError'
|
||||
} else if (error instanceof HLSUnsupportedError) {
|
||||
showRetryButton = false
|
||||
text = _(
|
||||
msg`This video can’t be played on your device. Your browser or system may be missing the required video codecs (H.264/AAC).`,
|
||||
)
|
||||
text = l`This video can’t be played on your device. Your browser or system may be missing the required video codecs (H.264/AAC).`
|
||||
errorClass = 'HLSUnsupportedError'
|
||||
} else {
|
||||
text = _(msg`An error occurred while loading the video. Please try again.`)
|
||||
text = l`An error occurred while loading the video. Please try again.`
|
||||
if (error instanceof HLSFatalError) {
|
||||
errorClass = error.detail
|
||||
} else if (error instanceof Error) {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {memo} from 'react'
|
||||
import {type Insets} from 'react-native'
|
||||
import {type AppBskyFeedDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useCleanError} from '#/lib/hooks/useCleanError'
|
||||
@@ -30,7 +29,7 @@ export const BookmarkButton = memo(function BookmarkButton({
|
||||
}): React.ReactNode {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {mutateAsync: bookmark} = useBookmarkMutation()
|
||||
const cleanError = useCleanError()
|
||||
const requireAuth = useRequireAuth()
|
||||
@@ -39,12 +38,10 @@ export const BookmarkButton = memo(function BookmarkButton({
|
||||
const {viewer} = post
|
||||
const isBookmarked = !!viewer?.bookmarked
|
||||
|
||||
const undoLabel = _(
|
||||
msg({
|
||||
message: `Undo`,
|
||||
context: `Button label to undo saving/removing a post from saved posts.`,
|
||||
}),
|
||||
)
|
||||
const undoLabel = l({
|
||||
message: `Undo`,
|
||||
context: `Button label to undo saving/removing a post from saved posts.`,
|
||||
})
|
||||
|
||||
const save = async () => {
|
||||
try {
|
||||
@@ -115,11 +112,7 @@ export const BookmarkButton = memo(function BookmarkButton({
|
||||
big={big}
|
||||
active={isBookmarked}
|
||||
activeColor={t.palette.primary_500}
|
||||
label={
|
||||
isBookmarked
|
||||
? _(msg`Remove from saved posts`)
|
||||
: _(msg`Add to saved posts`)
|
||||
}
|
||||
label={isBookmarked ? l`Remove from saved posts` : l`Add to saved posts`}
|
||||
onPress={onHandlePress}
|
||||
hitSlop={hitSlop}>
|
||||
<PostControlButtonIcon icon={isBookmarked ? BookmarkFilled : Bookmark} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {memo, useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useHaptics} from '#/lib/haptics'
|
||||
@@ -37,7 +37,7 @@ let RepostButton = ({
|
||||
embeddingDisabled,
|
||||
}: Props): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const requireAuth = useRequireAuth()
|
||||
const dialogControl = Dialog.useDialogControl()
|
||||
const formatPostStatCount = useFormatPostStatCount()
|
||||
@@ -64,26 +64,22 @@ let RepostButton = ({
|
||||
onLongPress={onLongPress}
|
||||
label={
|
||||
isReposted
|
||||
? _(
|
||||
msg({
|
||||
message: `Undo repost (${plural(repostCount || 0, {
|
||||
one: '# repost',
|
||||
other: '# reposts',
|
||||
})})`,
|
||||
comment:
|
||||
'Accessibility label for the repost button when the post has been reposted, verb followed by number of reposts and noun',
|
||||
}),
|
||||
)
|
||||
: _(
|
||||
msg({
|
||||
message: `Repost (${plural(repostCount || 0, {
|
||||
one: '# repost',
|
||||
other: '# reposts',
|
||||
})})`,
|
||||
comment:
|
||||
'Accessibility label for the repost button when the post has not been reposted, verb form followed by number of reposts and noun form',
|
||||
}),
|
||||
)
|
||||
? l({
|
||||
message: `Undo repost (${plural(repostCount || 0, {
|
||||
one: '# repost',
|
||||
other: '# reposts',
|
||||
})})`,
|
||||
comment:
|
||||
'Accessibility label for the repost button when the post has been reposted, verb followed by number of reposts and noun',
|
||||
})
|
||||
: l({
|
||||
message: `Repost (${plural(repostCount || 0, {
|
||||
one: '# repost',
|
||||
other: '# reposts',
|
||||
})})`,
|
||||
comment:
|
||||
'Accessibility label for the repost button when the post has not been reposted, verb form followed by number of reposts and noun form',
|
||||
})
|
||||
}>
|
||||
<PostControlButtonIcon icon={RepostIcon} />
|
||||
{typeof repostCount !== 'undefined' && repostCount > 0 && (
|
||||
@@ -121,7 +117,7 @@ let RepostButtonDialogInner = ({
|
||||
embeddingDisabled: boolean
|
||||
}): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const playHaptic = useHaptics()
|
||||
const control = Dialog.useDialogContext()
|
||||
|
||||
@@ -143,15 +139,15 @@ let RepostButtonDialogInner = ({
|
||||
const onPressClose = useCallback(() => control.close(), [control])
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner label={_(msg`Repost or quote post`)}>
|
||||
<Dialog.ScrollableInner label={l`Repost or quote post`}>
|
||||
<View style={a.gap_xl}>
|
||||
<View style={a.gap_xs}>
|
||||
<Button
|
||||
style={[a.justify_start, a.px_md, a.gap_sm]}
|
||||
label={
|
||||
isReposted
|
||||
? _(msg`Remove repost`)
|
||||
: _(msg({message: `Repost`, context: 'action'}))
|
||||
? l`Remove repost`
|
||||
: l({message: `Repost`, context: 'action'})
|
||||
}
|
||||
onPress={onPressRepost}
|
||||
size="large"
|
||||
@@ -170,11 +166,7 @@ let RepostButtonDialogInner = ({
|
||||
disabled={embeddingDisabled}
|
||||
testID="quoteBtn"
|
||||
style={[a.justify_start, a.px_md, a.gap_sm]}
|
||||
label={
|
||||
embeddingDisabled
|
||||
? _(msg`Quote posts disabled`)
|
||||
: _(msg`Quote post`)
|
||||
}
|
||||
label={embeddingDisabled ? l`Quote posts disabled` : l`Quote post`}
|
||||
onPress={onPressQuote}
|
||||
size="large"
|
||||
variant="ghost"
|
||||
@@ -202,7 +194,7 @@ let RepostButtonDialogInner = ({
|
||||
</Button>
|
||||
</View>
|
||||
<Button
|
||||
label={_(msg`Cancel quote post`)}
|
||||
label={l`Cancel quote post`}
|
||||
onPress={onPressClose}
|
||||
size="large"
|
||||
color="secondary">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useRequireAuth, useSession} from '#/state/session'
|
||||
import {EventStopper} from '#/view/com/util/EventStopper'
|
||||
@@ -32,7 +31,7 @@ export const RepostButton = ({
|
||||
embeddingDisabled,
|
||||
}: Props) => {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {hasSession} = useSession()
|
||||
const requireAuth = useRequireAuth()
|
||||
const formatPostStatCount = useFormatPostStatCount()
|
||||
@@ -40,7 +39,7 @@ export const RepostButton = ({
|
||||
return hasSession ? (
|
||||
<EventStopper onKeyDown={false}>
|
||||
<Menu.Root>
|
||||
<Menu.Trigger label={_(msg`Repost or quote post`)}>
|
||||
<Menu.Trigger label={l`Repost or quote post`}>
|
||||
{({props}) => {
|
||||
return (
|
||||
<PostControlButton
|
||||
@@ -64,31 +63,25 @@ export const RepostButton = ({
|
||||
<Menu.Item
|
||||
label={
|
||||
isReposted
|
||||
? _(msg`Undo repost`)
|
||||
: _(msg({message: `Repost`, context: `action`}))
|
||||
? l`Undo repost`
|
||||
: l({message: `Repost`, context: `action`})
|
||||
}
|
||||
testID="repostDropdownRepostBtn"
|
||||
onPress={onRepost}>
|
||||
<Menu.ItemText>
|
||||
{isReposted
|
||||
? _(msg`Undo repost`)
|
||||
: _(msg({message: `Repost`, context: `action`}))}
|
||||
? l`Undo repost`
|
||||
: l({message: `Repost`, context: `action`})}
|
||||
</Menu.ItemText>
|
||||
<Menu.ItemIcon icon={Repost} position="right" />
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
disabled={embeddingDisabled}
|
||||
label={
|
||||
embeddingDisabled
|
||||
? _(msg`Quote posts disabled`)
|
||||
: _(msg`Quote post`)
|
||||
}
|
||||
label={embeddingDisabled ? l`Quote posts disabled` : l`Quote post`}
|
||||
testID="repostDropdownQuoteBtn"
|
||||
onPress={onQuote}>
|
||||
<Menu.ItemText>
|
||||
{embeddingDisabled
|
||||
? _(msg`Quote posts disabled`)
|
||||
: _(msg`Quote post`)}
|
||||
{embeddingDisabled ? l`Quote posts disabled` : l`Quote post`}
|
||||
</Menu.ItemText>
|
||||
<Menu.ItemIcon icon={Quote} position="right" />
|
||||
</Menu.Item>
|
||||
@@ -100,7 +93,7 @@ export const RepostButton = ({
|
||||
onPress={() => requireAuth(() => {})}
|
||||
active={isReposted}
|
||||
activeColor={t.palette.positive_500}
|
||||
label={_(msg`Repost or quote post`)}
|
||||
label={l`Repost or quote post`}
|
||||
big={big}>
|
||||
<PostControlButtonIcon icon={Repost} />
|
||||
{typeof repostCount !== 'undefined' && repostCount > 0 && (
|
||||
|
||||
@@ -4,8 +4,7 @@ import {
|
||||
moderateProfile,
|
||||
type ModerationOpts,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
@@ -118,7 +117,7 @@ function RecentChatItem({
|
||||
convo: ConvoWithDetails
|
||||
primaryMember: ChatBskyActorDefs.ProfileViewBasic
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
const primaryProfile = useProfileShadow(primaryMember)
|
||||
@@ -143,7 +142,7 @@ function RecentChatItem({
|
||||
return (
|
||||
<Button
|
||||
onPress={onPress}
|
||||
label={_(msg`Send post to ${name}`)}
|
||||
label={l`Send post to ${name}`}
|
||||
style={[
|
||||
a.flex_col,
|
||||
{width: WIDTH},
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
AtUri,
|
||||
type RichText as RichTextAPI,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {shareUrl} from '#/lib/sharing'
|
||||
@@ -48,7 +47,7 @@ let ShareMenuButton = ({
|
||||
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
|
||||
}): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {feedDescriptor} = useFeedFeedbackContext()
|
||||
|
||||
const menuControl = useMenuControl()
|
||||
@@ -95,7 +94,7 @@ let ShareMenuButton = ({
|
||||
return (
|
||||
<EventStopper onKeyDown={false}>
|
||||
<Menu.Root control={lazyMenuControl}>
|
||||
<Menu.Trigger label={_(msg`Open share menu`)}>
|
||||
<Menu.Trigger label={l`Open share menu`}>
|
||||
{({props}) => {
|
||||
return (
|
||||
<PostControlButton
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useCallback} from 'react'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
/**
|
||||
* This matches `formatCount` from `view/com/util/numeric/format.ts`, but has
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
type ModerationOpts,
|
||||
} from '@atproto/api'
|
||||
import {flip, offset, shift, size, useFloating} from '@floating-ui/react-dom'
|
||||
import {msg, plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {plural} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {getModerationCauseKey} from '#/lib/moderation'
|
||||
@@ -423,7 +423,7 @@ function Inner({
|
||||
hide: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_, i18n} = useLingui()
|
||||
const {t: l, i18n} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const moderation = useMemo(
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
@@ -462,7 +462,7 @@ function Inner({
|
||||
return (
|
||||
<View>
|
||||
<View style={[a.flex_row, a.justify_between, a.align_start]}>
|
||||
<Link to={profileURL} label={_(msg`View profile`)} onPress={hide}>
|
||||
<Link to={profileURL} label={l`View profile`} onPress={hide}>
|
||||
<UserAvatar
|
||||
size={64}
|
||||
avatar={profile.avatar}
|
||||
@@ -476,24 +476,20 @@ function Inner({
|
||||
(isBlockedUser ? (
|
||||
<Link
|
||||
to={profileURL}
|
||||
label={_(msg`View blocked user's profile`)}
|
||||
label={l`View blocked user's profile`}
|
||||
onPress={hide}
|
||||
size="small"
|
||||
color="secondary"
|
||||
variant="solid"
|
||||
style={[a.rounded_full]}>
|
||||
<ButtonText>{_(msg`View profile`)}</ButtonText>
|
||||
<ButtonText>{l`View profile`}</ButtonText>
|
||||
</Link>
|
||||
) : (
|
||||
<Button
|
||||
size="small"
|
||||
color={profileShadow.viewer?.following ? 'secondary' : 'primary'}
|
||||
variant="solid"
|
||||
label={
|
||||
profileShadow.viewer?.following
|
||||
? _(msg`Following`)
|
||||
: _(msg`Follow`)
|
||||
}
|
||||
label={profileShadow.viewer?.following ? l`Following` : l`Follow`}
|
||||
style={[a.rounded_full]}
|
||||
onPress={profileShadow.viewer?.following ? unfollow : follow}>
|
||||
<ButtonIcon
|
||||
@@ -501,15 +497,12 @@ function Inner({
|
||||
icon={profileShadow.viewer?.following ? Check : Plus}
|
||||
/>
|
||||
<ButtonText>
|
||||
{profileShadow.viewer?.following
|
||||
? _(msg`Following`)
|
||||
: _(msg`Follow`)}
|
||||
{profileShadow.viewer?.following ? l`Following` : l`Follow`}
|
||||
</ButtonText>
|
||||
</Button>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<Link to={profileURL} label={_(msg`View profile`)} onPress={hide}>
|
||||
<Link to={profileURL} label={l`View profile`} onPress={hide}>
|
||||
<View style={[a.pb_sm, a.flex_1]}>
|
||||
<View style={[a.flex_row, a.align_center, a.pt_md, a.pb_xs]}>
|
||||
<Text
|
||||
@@ -540,7 +533,6 @@ function Inner({
|
||||
<ProfileHeaderHandle profile={profileShadow} disableTaps />
|
||||
</View>
|
||||
</Link>
|
||||
|
||||
{isBlockedUser && (
|
||||
<View style={[a.flex_row, a.flex_wrap, a.gap_xs]}>
|
||||
{moderation.ui('profileView').alerts.map(cause => (
|
||||
@@ -553,7 +545,6 @@ function Inner({
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{!isBlockedUser && (
|
||||
<>
|
||||
<View style={[a.flex_row, a.flex_wrap, a.gap_md, a.pt_xs]}>
|
||||
@@ -569,7 +560,7 @@ function Inner({
|
||||
</InlineLinkText>
|
||||
<InlineLinkText
|
||||
to={makeProfileLink(profile, 'follows')}
|
||||
label={_(msg`${following} following`)}
|
||||
label={l`${following} following`}
|
||||
style={[t.atoms.text]}
|
||||
onPress={hide}>
|
||||
<Text style={[a.text_md, a.font_semi_bold]}>{following} </Text>
|
||||
|
||||
@@ -15,8 +15,7 @@ import Animated, {
|
||||
} from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {scheduleOnRN} from 'react-native-worklets'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Portal} from '#/components/Portal'
|
||||
@@ -40,7 +39,7 @@ export const ProgressGuideToast = forwardRef<
|
||||
ProgressGuideToastProps
|
||||
>(function ProgressGuideToast({title, subtitle, visibleDuration}, ref) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const insets = useSafeAreaInsets()
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const translateY = useSharedValue(0)
|
||||
@@ -156,7 +155,7 @@ export const ProgressGuideToast = forwardRef<
|
||||
},
|
||||
]}
|
||||
onPress={close}
|
||||
accessibilityLabel={_(msg`Tap to dismiss`)}
|
||||
accessibilityLabel={l`Tap to dismiss`}
|
||||
accessibilityHint="">
|
||||
<AnimatedCheck
|
||||
fill={t.palette.primary_500}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useMemo} from 'react'
|
||||
import {type StyleProp, Text as RNText, type TextStyle} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
@@ -35,7 +34,7 @@ export function RichTextTag({
|
||||
authorHandle?: string
|
||||
textStyle: StyleProp<TextStyle>
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {isLoading: isPreferencesLoading, data: preferences} =
|
||||
usePreferencesQuery()
|
||||
const {
|
||||
@@ -50,10 +49,10 @@ export function RichTextTag({
|
||||
} = useRemoveMutedWordsMutation()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const isCashtag = tag.startsWith('$')
|
||||
const label = isCashtag ? _(msg`Cashtag ${tag}`) : _(msg`Hashtag ${tag}`)
|
||||
const label = isCashtag ? l`Cashtag ${tag}` : l`Hashtag ${tag}`
|
||||
const hint = IS_NATIVE
|
||||
? _(msg`Long press to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
||||
: _(msg`Click to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
||||
? l`Long press to open tag menu for ${isCashtag ? tag : `#${tag}`}`
|
||||
: l`Click to open tag menu for ${isCashtag ? tag : `#${tag}`}`
|
||||
|
||||
const isMuted = Boolean(
|
||||
(preferences?.moderationPrefs.mutedWords?.find(
|
||||
@@ -111,7 +110,7 @@ export function RichTextTag({
|
||||
<Menu.Outer>
|
||||
<Menu.Group>
|
||||
<Menu.Item
|
||||
label={_(msg`See ${isCashtag ? tag : `#${tag}`} posts`)}
|
||||
label={l`See ${isCashtag ? tag : `#${tag}`} posts`}
|
||||
onPress={() => {
|
||||
navigation.push('Hashtag', {
|
||||
tag: encodeURIComponent(tag),
|
||||
@@ -128,7 +127,7 @@ export function RichTextTag({
|
||||
</Menu.Item>
|
||||
{authorHandle && !isInvalidHandle(authorHandle) && (
|
||||
<Menu.Item
|
||||
label={_(msg`See ${isCashtag ? tag : `#${tag}`} posts by user`)}
|
||||
label={l`See ${isCashtag ? tag : `#${tag}`} posts by user`}
|
||||
onPress={() => {
|
||||
navigation.push('Hashtag', {
|
||||
tag: encodeURIComponent(tag),
|
||||
@@ -150,8 +149,8 @@ export function RichTextTag({
|
||||
<Menu.Item
|
||||
label={
|
||||
isMuted
|
||||
? _(msg`Unmute ${isCashtag ? tag : `#${tag}`}`)
|
||||
: _(msg`Mute ${isCashtag ? tag : `#${tag}`}`)
|
||||
? l`Unmute ${isCashtag ? tag : `#${tag}`}`
|
||||
: l`Mute ${isCashtag ? tag : `#${tag}`}`
|
||||
}
|
||||
onPress={() => {
|
||||
if (isMuted) {
|
||||
@@ -166,8 +165,8 @@ export function RichTextTag({
|
||||
}}>
|
||||
<Menu.ItemText>
|
||||
{isMuted
|
||||
? _(msg`Unmute ${isCashtag ? tag : `#${tag}`}`)
|
||||
: _(msg`Mute ${isCashtag ? tag : `#${tag}`}`)}
|
||||
? l`Unmute ${isCashtag ? tag : `#${tag}`}`
|
||||
: l`Mute ${isCashtag ? tag : `#${tag}`}`}
|
||||
</Menu.ItemText>
|
||||
<Menu.ItemIcon icon={isPreferencesLoading ? Loader : Mute} />
|
||||
</Menu.Item>
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
@@ -170,7 +169,7 @@ function ContentInner<T>({
|
||||
valueExtractor,
|
||||
...context
|
||||
}: ContentProps<T> & ContextType) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const [headerHeight, setHeaderHeight] = useState(61)
|
||||
|
||||
const render = useCallback(
|
||||
@@ -196,7 +195,7 @@ function ContentInner<T>({
|
||||
]}>
|
||||
<Dialog.HeaderText
|
||||
style={[a.flex_1, a.px_xl, a.text_left, a.font_bold, a.text_2xl]}>
|
||||
{label ?? _(msg`Select an option`)}
|
||||
{label ?? l`Select an option`}
|
||||
</Dialog.HeaderText>
|
||||
</Dialog.Header>
|
||||
<Dialog.Handle />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {forwardRef, useCallback, useImperativeHandle} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
||||
import {PostFeed} from '#/view/com/posts/PostFeed'
|
||||
@@ -20,7 +19,7 @@ interface ProfilesListProps {
|
||||
export const PostsList = forwardRef<SectionRef, ProfilesListProps>(
|
||||
function PostsListImpl({listUri, headerHeight, scrollElRef}, ref) {
|
||||
const feed: FeedDescriptor = `list|${listUri}`
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const onScrollToTop = useCallback(() => {
|
||||
scrollElRef.current?.scrollToOffset({
|
||||
@@ -38,10 +37,10 @@ export const PostsList = forwardRef<SectionRef, ProfilesListProps>(
|
||||
<EmptyState
|
||||
icon={HashtagWideIcon}
|
||||
iconSize="2xl"
|
||||
message={_(msg`This feed is empty.`)}
|
||||
message={l`This feed is empty.`}
|
||||
/>
|
||||
)
|
||||
}, [_])
|
||||
}, [l])
|
||||
|
||||
return (
|
||||
<View>
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {type AppBskyGraphDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
@@ -90,7 +89,7 @@ export function ProfileStarterPacks({
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
const items = data?.pages.flatMap(page => page.starterPacks)
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const EmptyComponent = useCallback(() => {
|
||||
if (emptyStateMessage || emptyStateButton || emptyStateIcon) {
|
||||
@@ -101,9 +100,7 @@ export function ProfileStarterPacks({
|
||||
iconSize="3xl"
|
||||
message={
|
||||
emptyStateMessage ??
|
||||
_(
|
||||
msg`Starter packs let you share your favorite feeds and people with your friends.`,
|
||||
)
|
||||
l`Starter packs let you share your favorite feeds and people with your friends.`
|
||||
}
|
||||
button={emptyStateButton}
|
||||
/>
|
||||
@@ -111,7 +108,7 @@ export function ProfileStarterPacks({
|
||||
)
|
||||
}
|
||||
return <Empty />
|
||||
}, [_, emptyStateMessage, emptyStateButton, emptyStateIcon])
|
||||
}, [l, emptyStateMessage, emptyStateButton, emptyStateIcon])
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
scrollToTop: () => {},
|
||||
@@ -193,7 +190,7 @@ export function ProfileStarterPacks({
|
||||
}
|
||||
|
||||
function CreateAnother() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
@@ -207,7 +204,7 @@ function CreateAnother() {
|
||||
t.atoms.border_contrast_low,
|
||||
]}>
|
||||
<Button
|
||||
label={_(msg`Create a starter pack`)}
|
||||
label={l`Create a starter pack`}
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
@@ -223,7 +220,7 @@ function CreateAnother() {
|
||||
}
|
||||
|
||||
function Empty() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const confirmDialogControl = useDialogControl()
|
||||
const followersDialogControl = useDialogControl()
|
||||
@@ -303,7 +300,7 @@ function Empty() {
|
||||
</View>
|
||||
<View style={[a.flex_row, a.gap_md, {marginLeft: 'auto'}]}>
|
||||
<Button
|
||||
label={_(msg`Create a starter pack for me`)}
|
||||
label={l`Create a starter pack for me`}
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="small"
|
||||
@@ -316,7 +313,7 @@ function Empty() {
|
||||
{isGenerating && <Loader size="md" />}
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Create a starter pack`)}
|
||||
label={l`Create a starter pack`}
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="small"
|
||||
@@ -333,7 +330,6 @@ function Empty() {
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<Prompt.Outer control={confirmDialogControl}>
|
||||
<Prompt.Content>
|
||||
<Prompt.TitleText>
|
||||
@@ -349,12 +345,12 @@ function Empty() {
|
||||
<Prompt.Actions>
|
||||
<Prompt.Action
|
||||
color="primary"
|
||||
cta={_(msg`Choose for me`)}
|
||||
cta={l`Choose for me`}
|
||||
onPress={generate}
|
||||
/>
|
||||
<Prompt.Action
|
||||
color="secondary"
|
||||
cta={_(msg`Let me choose`)}
|
||||
cta={l`Let me choose`}
|
||||
onPress={() => {
|
||||
navigation.navigate('StarterPackWizard', {})
|
||||
}}
|
||||
@@ -363,21 +359,17 @@ function Empty() {
|
||||
</Prompt.Outer>
|
||||
<Prompt.Basic
|
||||
control={followersDialogControl}
|
||||
title={_(msg`Oops!`)}
|
||||
description={_(
|
||||
msg`You must be following at least seven other people to generate a starter pack.`,
|
||||
)}
|
||||
title={l`Oops!`}
|
||||
description={l`You must be following at least seven other people to generate a starter pack.`}
|
||||
onConfirm={() => {}}
|
||||
showCancel={false}
|
||||
/>
|
||||
<Prompt.Basic
|
||||
control={errorDialogControl}
|
||||
title={_(msg`Oops!`)}
|
||||
description={_(
|
||||
msg`An error occurred while generating your starter pack. Want to try again?`,
|
||||
)}
|
||||
title={l`Oops!`}
|
||||
description={l`An error occurred while generating your starter pack. Want to try again?`}
|
||||
onConfirm={generate}
|
||||
confirmButtonCta={_(msg`Retry`)}
|
||||
confirmButtonCta={l`Retry`}
|
||||
/>
|
||||
</LinearGradientBackground>
|
||||
)
|
||||
|
||||
@@ -4,8 +4,7 @@ import type ViewShot from 'react-native-view-shot'
|
||||
import {requestPermissionsAsync, saveToLibraryAsync} from 'expo-media-library'
|
||||
import * as Sharing from 'expo-sharing'
|
||||
import {type AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
@@ -32,7 +31,7 @@ export function QrCodeDialog({
|
||||
link?: string
|
||||
control: DialogControlProps
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const [isSaveProcessing, setIsSaveProcessing] = useState(false)
|
||||
@@ -65,9 +64,7 @@ export function QrCodeDialog({
|
||||
|
||||
if (!res.granted) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`You must grant access to your photo library to save a QR code`,
|
||||
),
|
||||
l`You must grant access to your photo library to save a QR code`,
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -78,7 +75,7 @@ export function QrCodeDialog({
|
||||
// works with the add-only permission on iOS (APP-2374)
|
||||
await saveToLibraryAsync(`file://${uri}`)
|
||||
} catch (e: unknown) {
|
||||
Toast.show(_(msg`An error occurred while saving the QR code!`), {
|
||||
Toast.show(l`An error occurred while saving the QR code!`, {
|
||||
type: 'error',
|
||||
})
|
||||
logger.error('Failed to save QR code', {error: e})
|
||||
@@ -118,8 +115,8 @@ export function QrCodeDialog({
|
||||
setIsSaveProcessing(false)
|
||||
Toast.show(
|
||||
IS_WEB
|
||||
? _(msg`QR code has been downloaded!`)
|
||||
: _(msg`QR code saved to your camera roll!`),
|
||||
? l`QR code has been downloaded!`
|
||||
: l`QR code saved to your camera roll!`,
|
||||
)
|
||||
control.close()
|
||||
})
|
||||
@@ -140,7 +137,7 @@ export function QrCodeDialog({
|
||||
shareType: 'qrcode',
|
||||
qrShareType: 'copy',
|
||||
})
|
||||
Toast.show(_(msg`QR code copied to your clipboard!`))
|
||||
Toast.show(l`QR code copied to your clipboard!`)
|
||||
setIsCopyProcessing(false)
|
||||
control.close()
|
||||
})
|
||||
@@ -165,8 +162,7 @@ export function QrCodeDialog({
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Create a QR code for a starter pack`)}>
|
||||
<Dialog.ScrollableInner label={l`Create a QR code for a starter pack`}>
|
||||
<View style={[a.flex_1, a.align_center, a.gap_5xl]}>
|
||||
<Suspense fallback={<Loading />}>
|
||||
{!link ? (
|
||||
@@ -181,7 +177,7 @@ export function QrCodeDialog({
|
||||
gtMobile && [a.flex_row, a.justify_center, a.flex_wrap],
|
||||
]}>
|
||||
<Button
|
||||
label={_(msg`Copy QR code`)}
|
||||
label={l`Copy QR code`}
|
||||
color="primary_subtle"
|
||||
size="large"
|
||||
onPress={IS_WEB ? onCopyPress : onSharePress}>
|
||||
@@ -199,7 +195,7 @@ export function QrCodeDialog({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Save QR code`)}
|
||||
label={l`Save QR code`}
|
||||
color="secondary"
|
||||
size="large"
|
||||
onPress={onSavePress}>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {type AppBskyGraphDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useSaveImageToMediaLibrary} from '#/lib/media/save-image'
|
||||
@@ -46,7 +45,7 @@ function ShareDialogInner({
|
||||
qrDialogControl,
|
||||
control,
|
||||
}: Props) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const t = useTheme()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -71,7 +70,7 @@ function ShareDialogInner({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog.ScrollableInner label={_(msg`Share link dialog`)}>
|
||||
<Dialog.ScrollableInner label={l`Share link dialog`}>
|
||||
{!imageLoaded || !link ? (
|
||||
<View style={[a.align_center, a.justify_center, {minHeight: 350}]}>
|
||||
<Loader size="xl" />
|
||||
@@ -112,7 +111,7 @@ function ShareDialogInner({
|
||||
],
|
||||
]}>
|
||||
<Button
|
||||
label={IS_WEB ? _(msg`Copy link`) : _(msg`Share link`)}
|
||||
label={IS_WEB ? l`Copy link` : l`Share link`}
|
||||
color="primary_subtle"
|
||||
size="large"
|
||||
onPress={onShareLink}>
|
||||
@@ -126,7 +125,7 @@ function ShareDialogInner({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Share QR code`)}
|
||||
label={l`Share QR code`}
|
||||
color="primary_subtle"
|
||||
size="large"
|
||||
onPress={() => {
|
||||
@@ -141,7 +140,7 @@ function ShareDialogInner({
|
||||
</Button>
|
||||
{IS_NATIVE && (
|
||||
<Button
|
||||
label={_(msg`Save image`)}
|
||||
label={l`Save image`}
|
||||
color="secondary"
|
||||
size="large"
|
||||
onPress={onSave}>
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {AppBskyGraphStarterpack, AtUri} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
@@ -58,7 +57,7 @@ export function Card({
|
||||
}) {
|
||||
const {record, creator, joinedAllTimeCount} = starterPack
|
||||
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
@@ -87,8 +86,8 @@ export function Card({
|
||||
style={[a.leading_snug, t.atoms.text_contrast_medium]}
|
||||
numberOfLines={1}>
|
||||
{creator?.did === currentAccount?.did
|
||||
? _(msg`Starter pack by you`)
|
||||
: _(msg`Starter pack by ${sanitizeHandle(creator.handle, '@')}`)}
|
||||
? l`Starter pack by you`
|
||||
: l`Starter pack by ${sanitizeHandle(creator.handle, '@')}`}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -113,7 +112,7 @@ export function useStarterPackLink({
|
||||
}: {
|
||||
view: bsky.starterPack.AnyStarterPackView
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const qc = useQueryClient()
|
||||
const {rkey, handleOrDid} = useMemo(() => {
|
||||
const rkey = new AtUri(view.uri).rkey
|
||||
@@ -131,8 +130,8 @@ export function useStarterPackLink({
|
||||
view.record,
|
||||
AppBskyGraphStarterpack.isRecord,
|
||||
)
|
||||
? _(msg`Navigate to ${view.record.name}`)
|
||||
: _(msg`Navigate to starter pack`),
|
||||
? l`Navigate to ${view.record.name}`
|
||||
: l`Navigate to starter pack`,
|
||||
precache,
|
||||
}
|
||||
}
|
||||
@@ -145,7 +144,7 @@ export function Link({
|
||||
onPress?: () => void
|
||||
children: BaseLinkProps['children']
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const queryClient = useQueryClient()
|
||||
const {record} = starterPack
|
||||
const {rkey, handleOrDid} = useMemo(() => {
|
||||
@@ -166,7 +165,7 @@ export function Link({
|
||||
return (
|
||||
<BaseLink
|
||||
to={`/starter-pack/${handleOrDid}/${rkey}`}
|
||||
label={_(msg`Navigate to ${record.name}`)}
|
||||
label={l`Navigate to ${record.name}`}
|
||||
onPress={() => {
|
||||
precacheResolvedUri(
|
||||
queryClient,
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
type AppBskyFeedDefs,
|
||||
type ModerationOpts,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||
@@ -46,7 +45,7 @@ export function WizardEditListDialog({
|
||||
moderationOpts: ModerationOpts
|
||||
profile: AppBskyActorDefs.ProfileViewDetailed
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
|
||||
@@ -119,7 +118,7 @@ export function WizardEditListDialog({
|
||||
<View style={{width: 60}}>
|
||||
{IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="small"
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
type ModerationOpts,
|
||||
type ModerationUI,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {DISCOVER_FEED_URI, STARTER_PACK_MAX_SIZE} from '#/lib/constants'
|
||||
@@ -52,15 +51,15 @@ function WizardListCard({
|
||||
moderationUi: ModerationUI
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<Toggle.Item
|
||||
name={type === 'user' ? _(msg`Person toggle`) : _(msg`Feed toggle`)}
|
||||
name={type === 'user' ? l`Person toggle` : l`Feed toggle`}
|
||||
label={
|
||||
included
|
||||
? _(msg`Remove ${displayName} from starter pack`)
|
||||
: _(msg`Add ${displayName} to starter pack`)
|
||||
? l`Remove ${displayName} from starter pack`
|
||||
: l`Add ${displayName} to starter pack`
|
||||
}
|
||||
value={included}
|
||||
disabled={btnType === 'remove' || disabled}
|
||||
@@ -103,7 +102,7 @@ function WizardListCard({
|
||||
<Checkbox />
|
||||
) : !disabled ? (
|
||||
<Button
|
||||
label={_(msg`Remove`)}
|
||||
label={l`Remove`}
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
type AppBskyGraphDefs,
|
||||
AtUri,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {HITSLOP_10} from '#/lib/constants'
|
||||
@@ -49,7 +48,7 @@ interface WhoCanReplyProps {
|
||||
export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const infoDialogControl = useDialogControl()
|
||||
const editDialogControl = useDialogControl()
|
||||
|
||||
@@ -82,10 +81,10 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
|
||||
settings.length === 1 && settings[0].type === 'everybody'
|
||||
const noOneCanReply = settings.length === 1 && settings[0].type === 'nobody'
|
||||
const description = anyoneCanReply
|
||||
? _(msg`Everybody can reply`)
|
||||
? l`Everybody can reply`
|
||||
: noOneCanReply
|
||||
? _(msg`Replies disabled`)
|
||||
: _(msg`Some people can reply`)
|
||||
? l`Replies disabled`
|
||||
: l`Some people can reply`
|
||||
|
||||
const onPressOpen = () => {
|
||||
if (IS_NATIVE && Keyboard.isVisible()) {
|
||||
@@ -112,9 +111,7 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
label={
|
||||
isThreadAuthor ? _(msg`Edit who can reply`) : _(msg`Who can reply`)
|
||||
}
|
||||
label={isThreadAuthor ? l`Edit who can reply` : l`Who can reply`}
|
||||
onPress={onPressOpen}
|
||||
{...(isThreadAuthor
|
||||
? Platform.select({
|
||||
@@ -161,7 +158,6 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
|
||||
</View>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
{isThreadAuthor ? (
|
||||
<PostInteractionSettingsDialog
|
||||
postUri={post.uri}
|
||||
@@ -213,13 +209,13 @@ function WhoCanReplyDialog({
|
||||
settings: ThreadgateAllowUISetting[]
|
||||
embeddingDisabled: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Dialog: adjust who can interact with this post`)}
|
||||
label={l`Dialog: adjust who can interact with this post`}
|
||||
style={web({maxWidth: 400})}>
|
||||
<View style={[a.gap_sm]}>
|
||||
<Text style={[a.font_semi_bold, a.text_xl, a.pb_sm]}>
|
||||
@@ -233,7 +229,7 @@ function WhoCanReplyDialog({
|
||||
</View>
|
||||
{IS_NATIVE && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
onPress={() => control.close()}
|
||||
size="small"
|
||||
variant="solid"
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
type ModerationOpts,
|
||||
type Un$Typed,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {
|
||||
type InfiniteData,
|
||||
@@ -72,7 +71,7 @@ function DialogInner({
|
||||
includeProfile?: boolean
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const agent = useAgent()
|
||||
const control = Dialog.useDialogContext()
|
||||
@@ -136,9 +135,7 @@ function DialogInner({
|
||||
if (!activitySubscription.post && !activitySubscription.reply) {
|
||||
ax.metric('activitySubscription:disable', {})
|
||||
Toast.show(
|
||||
_(
|
||||
msg`You will no longer receive notifications for ${sanitizeHandle(profile.handle, '@')}`,
|
||||
),
|
||||
l`You will no longer receive notifications for ${sanitizeHandle(profile.handle, '@')}`,
|
||||
{
|
||||
type: 'success',
|
||||
},
|
||||
@@ -168,15 +165,13 @@ function DialogInner({
|
||||
})
|
||||
if (!initialState.post && !initialState.reply) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`You'll start receiving notifications for ${sanitizeHandle(profile.handle, '@')}!`,
|
||||
),
|
||||
l`You'll start receiving notifications for ${sanitizeHandle(profile.handle, '@')}!`,
|
||||
{
|
||||
type: 'success',
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Toast.show(_(msg`Changes saved`), {
|
||||
Toast.show(l`Changes saved`, {
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
@@ -195,7 +190,7 @@ function DialogInner({
|
||||
|
||||
if (isDirty) {
|
||||
return {
|
||||
label: _(msg`Save changes`),
|
||||
label: l`Save changes`,
|
||||
color: hasAny ? 'primary' : 'negative',
|
||||
onPress: () => saveChanges(state),
|
||||
disabled: isSaving,
|
||||
@@ -204,26 +199,26 @@ function DialogInner({
|
||||
// on web, a disabled save button feels more natural than a massive close button
|
||||
if (IS_WEB) {
|
||||
return {
|
||||
label: _(msg`Save changes`),
|
||||
label: l`Save changes`,
|
||||
color: 'secondary',
|
||||
disabled: true,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
label: _(msg`Cancel`),
|
||||
label: l`Cancel`,
|
||||
color: 'secondary',
|
||||
onPress: () => control.close(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [state, initialState, control, _, isSaving, saveChanges])
|
||||
}, [state, initialState, control, l, isSaving, saveChanges])
|
||||
|
||||
const name = createSanitizedDisplayName(profile, false)
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
style={web({maxWidth: 400})}
|
||||
label={_(msg`Get notified of new posts from ${name}`)}>
|
||||
label={l`Get notified of new posts from ${name}`}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<View style={[a.gap_xs]}>
|
||||
<Text style={[a.font_bold, a.text_2xl]}>
|
||||
@@ -249,12 +244,12 @@ function DialogInner({
|
||||
)}
|
||||
|
||||
<Toggle.Group
|
||||
label={_(msg`Subscribe to account activity`)}
|
||||
label={l`Subscribe to account activity`}
|
||||
values={values}
|
||||
onChange={onChange}>
|
||||
<View style={[a.gap_sm]}>
|
||||
<Toggle.Item
|
||||
label={_(msg`Posts`)}
|
||||
label={l`Posts`}
|
||||
name="post"
|
||||
style={[
|
||||
a.flex_1,
|
||||
@@ -271,7 +266,7 @@ function DialogInner({
|
||||
<Toggle.Switch />
|
||||
</Toggle.Item>
|
||||
<Toggle.Item
|
||||
label={_(msg`Replies`)}
|
||||
label={l`Replies`}
|
||||
name="reply"
|
||||
style={[
|
||||
a.flex_1,
|
||||
@@ -301,7 +296,6 @@ function DialogInner({
|
||||
{isSaving && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf'
|
||||
@@ -40,7 +39,7 @@ function Inner({
|
||||
control: Dialog.DialogControlProps
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
|
||||
return (
|
||||
@@ -90,7 +89,7 @@ function Inner({
|
||||
<Trans>
|
||||
Learn more in your{' '}
|
||||
<InlineLinkText
|
||||
label={_(msg`Go to account settings`)}
|
||||
label={l`Go to account settings`}
|
||||
to={'/settings/account'}
|
||||
style={[a.text_sm, a.leading_snug, a.font_semi_bold]}
|
||||
onPress={() => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {ToolsOzoneReportDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
@@ -23,12 +22,12 @@ export function AgeAssuranceAppealDialog({
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
return (
|
||||
<Dialog.Outer control={control}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Contact our moderation team`)}
|
||||
label={l`Contact our moderation team`}
|
||||
style={[web({maxWidth: 400})]}>
|
||||
<Inner control={control} />
|
||||
<Dialog.Close />
|
||||
@@ -38,7 +37,7 @@ export function AgeAssuranceAppealDialog({
|
||||
}
|
||||
|
||||
function Inner({control}: {control: Dialog.DialogControlProps}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {currentAccount} = useSession()
|
||||
const {gtPhone} = useBreakpoints()
|
||||
@@ -68,22 +67,17 @@ function Inner({control}: {control: Dialog.DialogControlProps}) {
|
||||
},
|
||||
onError: err => {
|
||||
logger.error('AgeAssuranceAppealDialog failed', {safeMessage: err})
|
||||
Toast.show(
|
||||
_(msg`Age assurance inquiry failed to send, please try again.`),
|
||||
{
|
||||
type: 'error',
|
||||
},
|
||||
)
|
||||
Toast.show(l`Age assurance inquiry failed to send, please try again.`, {
|
||||
type: 'error',
|
||||
})
|
||||
},
|
||||
onSuccess: () => {
|
||||
control.close()
|
||||
Toast.show(
|
||||
_(
|
||||
msg({
|
||||
message: 'Age assurance inquiry was submitted',
|
||||
context: 'toast',
|
||||
}),
|
||||
),
|
||||
l({
|
||||
message: 'Age assurance inquiry was submitted',
|
||||
context: 'toast',
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -93,18 +87,15 @@ function Inner({control}: {control: Dialog.DialogControlProps}) {
|
||||
<View style={[a.align_start]}>
|
||||
<AgeAssuranceBadge />
|
||||
</View>
|
||||
|
||||
<Text style={[a.text_2xl, a.font_bold, a.pt_md, a.leading_tight]}>
|
||||
<Trans>Contact us</Trans>
|
||||
</Text>
|
||||
|
||||
<Text style={[a.text_sm, a.pt_sm, a.leading_snug]}>
|
||||
<Trans>
|
||||
Please provide any additional details you feel moderators may need in
|
||||
order to properly assess your Age Assurance status.
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<View style={[a.pt_md]}>
|
||||
<Dialog.Input
|
||||
multiline
|
||||
@@ -113,13 +104,13 @@ function Inner({control}: {control: Dialog.DialogControlProps}) {
|
||||
onChangeText={details => {
|
||||
setDetails(details)
|
||||
}}
|
||||
label={_(msg`Additional details (limit 1000 characters)`)}
|
||||
label={l`Additional details (limit 1000 characters)`}
|
||||
numberOfLines={4}
|
||||
onSubmitEditing={() => mutate()}
|
||||
/>
|
||||
<View style={[a.pt_md, a.gap_sm, gtPhone && [a.flex_row_reverse]]}>
|
||||
<Button
|
||||
label={_(msg`Submit`)}
|
||||
label={l`Submit`}
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
@@ -130,7 +121,7 @@ function Inner({control}: {control: Dialog.DialogControlProps}) {
|
||||
{isPending && <ButtonIcon icon={Loader} position="right" />}
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
import {atoms as a, select, useTheme} from '#/alf'
|
||||
@@ -43,7 +42,7 @@ export function useInternalState() {
|
||||
export function AgeAssuranceDismissibleFeedBanner() {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {visible, close} = useInternalState()
|
||||
const copy = useAgeAssuranceCopy()
|
||||
|
||||
@@ -63,7 +62,7 @@ export function AgeAssuranceDismissibleFeedBanner() {
|
||||
},
|
||||
]}>
|
||||
<Link
|
||||
label={_(msg`Learn more about age assurance`)}
|
||||
label={l`Learn more about age assurance`}
|
||||
to="/settings/account"
|
||||
onPress={() => {
|
||||
close()
|
||||
@@ -100,9 +99,8 @@ export function AgeAssuranceDismissibleFeedBanner() {
|
||||
</View>
|
||||
</View>
|
||||
</Link>
|
||||
|
||||
<Button
|
||||
label={_(msg`Don't show again`)}
|
||||
label={l`Don't show again`}
|
||||
size="small"
|
||||
onPress={() => {
|
||||
close()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
import {atoms as a, type ViewStyleProp} from '#/alf'
|
||||
@@ -13,7 +12,7 @@ import {useAgeAssurance} from '#/ageAssurance'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
|
||||
export function AgeAssuranceDismissibleNotice({style}: ViewStyleProp & {}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const aa = useAgeAssurance()
|
||||
const {nux} = useNux(Nux.AgeAssuranceDismissibleNotice)
|
||||
@@ -35,7 +34,7 @@ export function AgeAssuranceDismissibleNotice({style}: ViewStyleProp & {}) {
|
||||
<AgeAssuranceAdmonition>{copy.notice}</AgeAssuranceAdmonition>
|
||||
|
||||
<Button
|
||||
label={_(msg`Don't show again`)}
|
||||
label={l`Don't show again`}
|
||||
size="tiny"
|
||||
variant="solid"
|
||||
color="secondary_inverted"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {type ViewStyleProp} from '#/alf'
|
||||
@@ -9,7 +8,7 @@ import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as RetryIcon} from '
|
||||
import {refetchConfig} from '#/ageAssurance/data'
|
||||
|
||||
export function AgeAssuranceConfigUnavailableError(props: ViewStyleProp) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
return (
|
||||
<Admonition.Outer type="error" style={props.style}>
|
||||
<Admonition.Row>
|
||||
@@ -25,7 +24,7 @@ export function AgeAssuranceConfigUnavailableError(props: ViewStyleProp) {
|
||||
</Admonition.Content>
|
||||
<Admonition.Button
|
||||
color="negative_subtle"
|
||||
label={_(msg`Retry`)}
|
||||
label={l`Retry`}
|
||||
onPress={() => refetchConfig().catch(() => {})}>
|
||||
<ButtonText>
|
||||
<Trans>Retry</Trans>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {XRPCError} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {validate as validateEmail} from 'email-validator'
|
||||
|
||||
@@ -41,15 +40,12 @@ export function AgeAssuranceInitDialog({
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
return (
|
||||
<Dialog.Outer control={control}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(
|
||||
msg`Begin the age assurance process by completing the fields below.`,
|
||||
)}
|
||||
label={l`Begin the age assurance process by completing the fields below.`}
|
||||
style={[
|
||||
web({
|
||||
maxWidth: 400,
|
||||
@@ -63,7 +59,7 @@ export function AgeAssuranceInitDialog({
|
||||
}
|
||||
|
||||
function Inner() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {currentAccount} = useSession()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
@@ -98,9 +94,7 @@ function Inner() {
|
||||
|
||||
if (tlds && isEmailMaybeInvalid(email, tlds)) {
|
||||
setEmailError(
|
||||
_(
|
||||
msg`Please double-check that you have entered your email address correctly.`,
|
||||
),
|
||||
l`Please double-check that you have entered your email address correctly.`,
|
||||
)
|
||||
return {status: 'maybe'}
|
||||
}
|
||||
@@ -108,7 +102,7 @@ function Inner() {
|
||||
return {status: 'valid'}
|
||||
}
|
||||
|
||||
setEmailError(_(msg`Please enter a valid email address.`))
|
||||
setEmailError(l`Please enter a valid email address.`)
|
||||
setDisabled(true)
|
||||
|
||||
return {status: 'invalid'}
|
||||
@@ -135,15 +129,11 @@ function Inner() {
|
||||
|
||||
setSuccess(true)
|
||||
} catch (e) {
|
||||
let error: React.ReactNode = _(
|
||||
msg`Something went wrong, please try again`,
|
||||
)
|
||||
let error: React.ReactNode = l`Something went wrong, please try again`
|
||||
|
||||
if (e instanceof XRPCError) {
|
||||
if (e.error === 'InvalidEmail') {
|
||||
error = _(
|
||||
msg`Please enter a valid, non-temporary email address. You may need to access this email in the future.`,
|
||||
)
|
||||
error = l`Please enter a valid, non-temporary email address. You may need to access this email in the future.`
|
||||
ax.metric('ageAssurance:initDialogError', {code: 'InvalidEmail'})
|
||||
} else if (e.error === 'DidTooLong') {
|
||||
error = (
|
||||
@@ -153,7 +143,7 @@ function Inner() {
|
||||
your account. Please{' '}
|
||||
<SimpleInlineLinkText
|
||||
to={createSupportLink({code: SupportCode.AA_DID, email})}
|
||||
label={_(msg`Contact support`)}>
|
||||
label={l`Contact support`}>
|
||||
contact support
|
||||
</SimpleInlineLinkText>{' '}
|
||||
for assistance.
|
||||
@@ -197,7 +187,7 @@ function Inner() {
|
||||
<Trans>
|
||||
We have partnered with{' '}
|
||||
<SimpleInlineLinkText
|
||||
label={_(msg`KWS website`)}
|
||||
label={l`KWS website`}
|
||||
to={urls.kwsHome}
|
||||
style={[a.text_sm, a.leading_snug]}>
|
||||
KWS
|
||||
@@ -220,7 +210,7 @@ function Inner() {
|
||||
{success ? (
|
||||
<View style={[a.w_full]}>
|
||||
<Button
|
||||
label={_(msg`Close dialog`)}
|
||||
label={l`Close dialog`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
@@ -253,8 +243,8 @@ function Inner() {
|
||||
</TextField.LabelText>
|
||||
<TextField.Root isInvalid={!!emailError}>
|
||||
<TextField.Input
|
||||
label={_(msg`Your email`)}
|
||||
placeholder={_(msg`Your email`)}
|
||||
label={l`Your email`}
|
||||
placeholder={l`Your email`}
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
onFocus={() => setEmailError('')}
|
||||
@@ -289,7 +279,7 @@ function Inner() {
|
||||
<Trans>Your preferred language</Trans>
|
||||
</TextField.LabelText>
|
||||
<LanguageSelect
|
||||
label={_(msg`Preferred language`)}
|
||||
label={l`Preferred language`}
|
||||
value={language}
|
||||
onChange={value => {
|
||||
setLanguage(value)
|
||||
@@ -310,7 +300,7 @@ function Inner() {
|
||||
|
||||
<Button
|
||||
disabled={disabled}
|
||||
label={_(msg`Begin age assurance process`)}
|
||||
label={l`Begin age assurance process`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useEffect, useRef, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {retry} from '#/lib/async/retry'
|
||||
@@ -61,7 +60,7 @@ export function useAgeAssuranceRedirectDialogControl() {
|
||||
}
|
||||
|
||||
export function AgeAssuranceRedirectDialog() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const control = useAgeAssuranceRedirectDialogControl()
|
||||
|
||||
// for testing
|
||||
@@ -70,9 +69,8 @@ export function AgeAssuranceRedirectDialog() {
|
||||
return (
|
||||
<Dialog.Outer control={control.control} onClose={() => control.clear()}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Verifying your age assurance status`)}
|
||||
label={l`Verifying your age assurance status`}
|
||||
style={[web({maxWidth: 400})]}>
|
||||
<Inner optimisticState={control.value} />
|
||||
</Dialog.ScrollableInner>
|
||||
@@ -83,7 +81,7 @@ export function AgeAssuranceRedirectDialog() {
|
||||
export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const agent = useAgent()
|
||||
const polling = useRef(false)
|
||||
const unmounted = useRef(false)
|
||||
@@ -171,7 +169,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
||||
{IS_NATIVE && (
|
||||
<View style={[a.w_full, a.pt_lg]}>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
@@ -183,7 +181,6 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</>
|
||||
)
|
||||
@@ -230,7 +227,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
||||
{error && IS_NATIVE && (
|
||||
<View style={[a.w_full, a.pt_lg]}>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
@@ -242,7 +239,6 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{error && <Dialog.Close />}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
@@ -27,7 +26,7 @@ export function AgeRestrictedScreen({
|
||||
infoText?: string
|
||||
rightHeaderSlot?: React.ReactNode
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const copy = useAgeAssuranceCopy()
|
||||
const aa = useAgeAssurance()
|
||||
@@ -70,7 +69,7 @@ export function AgeRestrictedScreen({
|
||||
<View
|
||||
style={[a.flex_row, a.justify_between, a.align_center, a.pb_xl]}>
|
||||
<Link
|
||||
label={_(msg`Go to account settings`)}
|
||||
label={l`Go to account settings`}
|
||||
to="/settings/account"
|
||||
size="small"
|
||||
variant="solid"
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import {useMemo} from 'react'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useAgeAssurance} from '#/ageAssurance'
|
||||
|
||||
export function useAgeAssuranceCopy() {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const aa = useAgeAssurance()
|
||||
|
||||
const hasCompletedFlow = aa.state.status === aa.Status.Assured
|
||||
@@ -13,18 +12,10 @@ export function useAgeAssuranceCopy() {
|
||||
return useMemo(() => {
|
||||
return {
|
||||
notice: hasCompletedFlow
|
||||
? _(
|
||||
msg`You have completed the Age Assurance process, but based on the results, we cannot be sure that you are 18 years of age or older. Due to laws in your region, certain features on Bluesky must remain restricted until you're able to verify you're an adult.`,
|
||||
)
|
||||
: _(
|
||||
msg`Due to laws in your region, certain features on Bluesky are currently restricted until you're able to verify you're an adult.`,
|
||||
),
|
||||
banner: _(
|
||||
msg`The laws in your region require you to verify you're an adult to access certain features. Tap to learn more.`,
|
||||
),
|
||||
chatsInfoText: _(
|
||||
msg`Don't worry! All existing messages and settings are saved and will be available after you verify you're an adult.`,
|
||||
),
|
||||
? l`You have completed the Age Assurance process, but based on the results, we cannot be sure that you are 18 years of age or older. Due to laws in your region, certain features on Bluesky must remain restricted until you're able to verify you're an adult.`
|
||||
: l`Due to laws in your region, certain features on Bluesky are currently restricted until you're able to verify you're an adult.`,
|
||||
banner: l`The laws in your region require you to verify you're an adult to access certain features. Tap to learn more.`,
|
||||
chatsInfoText: l`Don't worry! All existing messages and settings are saved and will be available after you verify you're an adult.`,
|
||||
}
|
||||
}, [_, hasCompletedFlow])
|
||||
}, [l, hasCompletedFlow])
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {HITSLOP_10} from '#/lib/constants'
|
||||
@@ -19,7 +18,7 @@ import {useIsFindContactsFeatureEnabledBasedOnGeolocation} from './country-allow
|
||||
|
||||
export function FindContactsBannerNUX() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {visible, close} = useInternalState()
|
||||
|
||||
@@ -30,7 +29,7 @@ export function FindContactsBannerNUX() {
|
||||
<View style={a.w_full}>
|
||||
<Link
|
||||
to={{screen: 'FindContactsFlow'}}
|
||||
label={_(msg`Import contacts to find your friends`)}
|
||||
label={l`Import contacts to find your friends`}
|
||||
onPress={() => {
|
||||
ax.metric('contacts:nux:bannerPressed', {})
|
||||
}}
|
||||
@@ -75,7 +74,7 @@ export function FindContactsBannerNUX() {
|
||||
</LinearGradient>
|
||||
</Link>
|
||||
<Button
|
||||
label={_(msg`Dismiss banner`)}
|
||||
label={l`Dismiss banner`}
|
||||
hitSlop={HITSLOP_10}
|
||||
onPress={close}
|
||||
style={[a.absolute, {top: 14, right: 14}]}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
|
||||
export function ContactsHeroImage() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -24,9 +23,7 @@ export function ContactsHeroImage() {
|
||||
source={require('../../../../assets/images/find_friends_illustration.webp')}
|
||||
accessibilityIgnoresInvertColors
|
||||
style={[a.w_full, {aspectRatio: 1278 / 661}]}
|
||||
alt={_(
|
||||
msg`An illustration depicting user avatars flowing from a contact book into the Bluesky app`,
|
||||
)}
|
||||
alt={l`An illustration depicting user avatars flowing from a contact book into the Bluesky app`}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {type StyleProp, type TextStyle} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {HITSLOP_20} from '#/lib/constants'
|
||||
@@ -22,7 +21,7 @@ export function InviteInfo({
|
||||
*/
|
||||
iconOffset?: number
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
const style = [a.text_md, a.leading_snug, a.mt_xs]
|
||||
@@ -30,16 +29,15 @@ export function InviteInfo({
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
label={_(msg`Learn more about how inviting friends works`)}
|
||||
label={l`Learn more about how inviting friends works`}
|
||||
onPress={control.open}
|
||||
hitSlop={HITSLOP_20}
|
||||
style={android({transform: [{translateY: iconOffset}]})}>
|
||||
<InfoIcon style={iconStyle} size="sm" />
|
||||
</Button>
|
||||
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner label={_(msg`Invite Friends`)}>
|
||||
<Dialog.ScrollableInner label={l`Invite Friends`}>
|
||||
<Text style={[a.text_2xl, a.font_bold]}>
|
||||
<Trans>Invite Friends</Trans>
|
||||
</Text>
|
||||
@@ -70,7 +68,7 @@ export function InviteInfo({
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
label={_(msg`Done`)}
|
||||
label={l`Done`}
|
||||
onPress={() => control.close()}
|
||||
size="large"
|
||||
color="primary"
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
type TextInputSelectionChangeEvent,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {mergeRefs} from '#/lib/merge-refs'
|
||||
import {atoms as a, ios, platform, useTheme} from '#/alf'
|
||||
@@ -30,7 +29,7 @@ export function OTPInput({
|
||||
onComplete?: (code: string) => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const innerRef = useRef<TextInput>(null)
|
||||
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
||||
const [selection, setSelection] = useState({start: 0, end: 0})
|
||||
@@ -52,7 +51,7 @@ export function OTPInput({
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
accessibilityLabel={_(msg`Focus code input`)}
|
||||
accessibilityLabel={l`Focus code input`}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint=""
|
||||
style={[a.w_full, a.relative]}
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
AppBskyContactImportContacts,
|
||||
type Un$Typed,
|
||||
} from '@atproto/api'
|
||||
import {msg, t} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {t} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
@@ -52,7 +52,7 @@ export function GetContacts({
|
||||
onCancel: () => void
|
||||
context: 'Onboarding' | 'Standalone'
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const insets = useSafeAreaInsets()
|
||||
@@ -143,32 +143,26 @@ export function GetContacts({
|
||||
})
|
||||
if (isNetworkError(err)) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`There was a problem with your internet connection, please try again`,
|
||||
),
|
||||
l`There was a problem with your internet connection, please try again`,
|
||||
{type: 'error'},
|
||||
)
|
||||
} else if (
|
||||
err instanceof AppBskyContactImportContacts.TooManyContactsError
|
||||
) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`Too many contacts - you've exceeded the number of contacts you can import to find your friends`,
|
||||
),
|
||||
l`Too many contacts - you've exceeded the number of contacts you can import to find your friends`,
|
||||
{type: 'error'},
|
||||
)
|
||||
} else if (
|
||||
err instanceof AppBskyContactImportContacts.InvalidTokenError
|
||||
) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`Could not upload contacts. You need to re-verify your phone number to proceed`,
|
||||
),
|
||||
l`Could not upload contacts. You need to re-verify your phone number to proceed`,
|
||||
{type: 'error'},
|
||||
)
|
||||
} else {
|
||||
logger.error('Error uploading contacts', {safeMessage: err})
|
||||
Toast.show(_(msg`Could not upload contacts. ${cleanError(err)}`), {
|
||||
Toast.show(l`Could not upload contacts. ${cleanError(err)}`, {
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
@@ -270,7 +264,7 @@ export function GetContacts({
|
||||
</Trans>
|
||||
</Text>
|
||||
<Button
|
||||
label={_(msg`Find my friends`)}
|
||||
label={l`Find my friends`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={() => getContacts()}
|
||||
@@ -289,7 +283,7 @@ export function GetContacts({
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
size="large"
|
||||
color="secondary"
|
||||
onPress={onCancel}>
|
||||
|
||||
@@ -3,8 +3,7 @@ import {Keyboard, View} from 'react-native'
|
||||
import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {AppBskyContactStartPhoneVerification} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
@@ -53,7 +52,7 @@ export function PhoneInput({
|
||||
context: 'Onboarding' | 'Standalone'
|
||||
onSkip: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const t = useTheme()
|
||||
const agent = useAgent()
|
||||
@@ -98,26 +97,22 @@ export function PhoneInput({
|
||||
onError: err => {
|
||||
if (isNetworkError(err)) {
|
||||
setError(
|
||||
_(
|
||||
msg`A network error occurred. Please check your internet connection`,
|
||||
),
|
||||
l`A network error occurred. Please check your internet connection`,
|
||||
)
|
||||
} else if (
|
||||
err instanceof
|
||||
AppBskyContactStartPhoneVerification.RateLimitExceededError
|
||||
) {
|
||||
setError(_(msg`Rate limit exceeded. Please try again later.`))
|
||||
setError(l`Rate limit exceeded. Please try again later.`)
|
||||
} else if (
|
||||
err instanceof AppBskyContactStartPhoneVerification.InvalidPhoneError
|
||||
) {
|
||||
setError(
|
||||
_(
|
||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
),
|
||||
l`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
)
|
||||
} else {
|
||||
logger.error('Verify phone number failed', {safeMessage: err})
|
||||
setError(_(msg`An error occurred. ${cleanError(err)}`))
|
||||
setError(l`An error occurred. ${cleanError(err)}`)
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -139,7 +134,7 @@ export function PhoneInput({
|
||||
phoneNumber: result.formatted,
|
||||
})
|
||||
} else {
|
||||
setFormatError(result.reason ?? _(msg`Invalid phone number`))
|
||||
setFormatError(result.reason ?? l`Invalid phone number`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +152,7 @@ export function PhoneInput({
|
||||
size="small"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
label={_(msg`Skip contact sharing and continue to the app`)}
|
||||
label={l`Skip contact sharing and continue to the app`}
|
||||
onPress={onSkip}>
|
||||
<ButtonText>
|
||||
<Trans>Skip</Trans>
|
||||
@@ -201,7 +196,7 @@ export function PhoneInput({
|
||||
<View style={[a.flex_1]}>
|
||||
<TextField.Root isInvalid={!!formatError || !isFeatureEnabled}>
|
||||
<TextField.Input
|
||||
label={_(msg`Phone number`)}
|
||||
label={l`Phone number`}
|
||||
value={phoneNumber}
|
||||
onChangeText={text => {
|
||||
if (formatError) setFormatError('')
|
||||
@@ -252,7 +247,7 @@ export function PhoneInput({
|
||||
<View style={[gutters, {paddingBottom}]}>
|
||||
<Button
|
||||
disabled={!phoneNumber || isPending}
|
||||
label={_(msg`Send code`)}
|
||||
label={l`Send code`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={onSubmitNumber}>
|
||||
@@ -269,7 +264,7 @@ export function PhoneInput({
|
||||
|
||||
function LegalDisclaimer() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const style = [a.text_xs, t.atoms.text_contrast_medium, a.leading_snug]
|
||||
|
||||
@@ -299,12 +294,10 @@ function LegalDisclaimer() {
|
||||
time by visiting settings.{' '}
|
||||
<InlineLinkText
|
||||
to={urls.website.support.findFriendsPrivacyPolicy}
|
||||
label={_(
|
||||
msg({
|
||||
message: `Learn more about importing contacts`,
|
||||
context: `english-only-resource`,
|
||||
}),
|
||||
)}
|
||||
label={l({
|
||||
message: `Learn more about importing contacts`,
|
||||
context: `english-only-resource`,
|
||||
})}
|
||||
style={[a.text_xs, a.leading_snug]}>
|
||||
<Trans context="english-only-resource">Learn more</Trans>
|
||||
</InlineLinkText>
|
||||
|
||||
@@ -4,8 +4,7 @@ import {
|
||||
AppBskyContactStartPhoneVerification,
|
||||
AppBskyContactVerifyPhone,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
@@ -41,7 +40,7 @@ export function VerifyNumber({
|
||||
onSkip: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const gutters = useGutters([0, 'wide'])
|
||||
@@ -95,23 +94,19 @@ export function VerifyNumber({
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: false,
|
||||
message: _(
|
||||
msg`A network error occurred. Please check your internet connection.`,
|
||||
),
|
||||
message: l`A network error occurred. Please check your internet connection.`,
|
||||
})
|
||||
} else if (err instanceof AppBskyContactVerifyPhone.InvalidCodeError) {
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: true,
|
||||
message: _(msg`This code is invalid. Resend to get a new code.`),
|
||||
message: l`This code is invalid. Resend to get a new code.`,
|
||||
})
|
||||
} else if (err instanceof AppBskyContactVerifyPhone.InvalidPhoneError) {
|
||||
setError({
|
||||
retryable: false,
|
||||
isResendError: false,
|
||||
message: _(
|
||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
),
|
||||
message: l`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
})
|
||||
} else if (
|
||||
err instanceof AppBskyContactVerifyPhone.RateLimitExceededError
|
||||
@@ -119,16 +114,14 @@ export function VerifyNumber({
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: false,
|
||||
message: _(
|
||||
msg`Too many attempts. Please wait a few minutes and try again.`,
|
||||
),
|
||||
message: l`Too many attempts. Please wait a few minutes and try again.`,
|
||||
})
|
||||
} else {
|
||||
logger.error('Verify phone number failed', {safeMessage: err})
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: false,
|
||||
message: _(msg`An error occurred. ${cleanError(err)}`),
|
||||
message: l`An error occurred. ${cleanError(err)}`,
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -140,7 +133,7 @@ export function VerifyNumber({
|
||||
},
|
||||
onSuccess: () => {
|
||||
dispatch({type: 'RESEND_VERIFICATION_CODE'})
|
||||
Toast.show(_(msg`A new code has been sent`))
|
||||
Toast.show(l`A new code has been sent`)
|
||||
},
|
||||
onMutate: () => {
|
||||
setOtpCode('')
|
||||
@@ -151,9 +144,7 @@ export function VerifyNumber({
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: true,
|
||||
message: _(
|
||||
msg`A network error occurred. Please check your internet connection.`,
|
||||
),
|
||||
message: l`A network error occurred. Please check your internet connection.`,
|
||||
})
|
||||
} else if (
|
||||
err instanceof AppBskyContactStartPhoneVerification.InvalidPhoneError
|
||||
@@ -161,9 +152,7 @@ export function VerifyNumber({
|
||||
setError({
|
||||
retryable: false,
|
||||
isResendError: true,
|
||||
message: _(
|
||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
),
|
||||
message: l`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||
})
|
||||
} else if (
|
||||
err instanceof
|
||||
@@ -172,16 +161,14 @@ export function VerifyNumber({
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: true,
|
||||
message: _(
|
||||
msg`Too many codes sent. Please wait a few minutes and try again.`,
|
||||
),
|
||||
message: l`Too many codes sent. Please wait a few minutes and try again.`,
|
||||
})
|
||||
} else {
|
||||
logger.error('Resend failed', {safeMessage: err})
|
||||
setError({
|
||||
retryable: true,
|
||||
isResendError: true,
|
||||
message: _(msg`An error occurred. ${cleanError(err)}`),
|
||||
message: l`An error occurred. ${cleanError(err)}`,
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -199,7 +186,7 @@ export function VerifyNumber({
|
||||
size="small"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
label={_(msg`Skip contact sharing and continue to the app`)}
|
||||
label={l`Skip contact sharing and continue to the app`}
|
||||
onPress={onSkip}>
|
||||
<ButtonText>
|
||||
<Trans>Skip</Trans>
|
||||
@@ -227,9 +214,7 @@ export function VerifyNumber({
|
||||
</Text>
|
||||
<View style={[a.mt_2xl]}>
|
||||
<OTPInput
|
||||
label={_(
|
||||
msg`Enter 6-digit code that was sent to your phone number`,
|
||||
)}
|
||||
label={l`Enter 6-digit code that was sent to your phone number`}
|
||||
value={otpCode}
|
||||
onChange={setOtpCode}
|
||||
onComplete={code => verifyNumber(code)}
|
||||
@@ -276,7 +261,7 @@ function OTPStatus({
|
||||
onRetry: () => void
|
||||
lastCodeSentAt: Date | null
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
const [time, setTime] = useState(Date.now())
|
||||
@@ -301,10 +286,10 @@ function OTPStatus({
|
||||
|
||||
if (isSuccess) {
|
||||
Icon = CircleCheckIcon
|
||||
text = _(msg`Phone number verified`)
|
||||
text = l`Phone number verified`
|
||||
textColor = t.palette.positive_500
|
||||
} else if (isPending) {
|
||||
text = _(msg`Verifying...`)
|
||||
text = l`Verifying...`
|
||||
} else if (error) {
|
||||
Icon = WarningIcon
|
||||
text = error.message
|
||||
@@ -342,12 +327,11 @@ function OTPStatus({
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showRetryButton && (
|
||||
<Button
|
||||
size="small"
|
||||
color="secondary_inverted"
|
||||
label={_(msg`Retry`)}
|
||||
label={l`Retry`}
|
||||
onPress={onRetry}
|
||||
style={[a.mt_2xl]}>
|
||||
<ButtonIcon icon={RetryIcon} />
|
||||
@@ -356,13 +340,12 @@ function OTPStatus({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{showResendButton && (
|
||||
<Button
|
||||
size="large"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
label={_(msg`Resend code`)}
|
||||
label={l`Resend code`}
|
||||
disabled={isResendingCode || isWaiting}
|
||||
onPress={onResend}
|
||||
style={[a.mt_2xl]}>
|
||||
|
||||
@@ -3,8 +3,7 @@ import {View} from 'react-native'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import * as SMS from 'expo-sms'
|
||||
import {type ModerationOpts} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
@@ -84,7 +83,7 @@ export function ViewMatches({
|
||||
onNext: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const gutter = useGutters([0, 'wide'])
|
||||
const moderationOpts = useModerationOpts()
|
||||
@@ -141,11 +140,11 @@ export function ViewMatches({
|
||||
}),
|
||||
onSuccess: () => {
|
||||
setDidFollowAll(true)
|
||||
Toast.show(_(msg`All friends followed!`), {type: 'success'})
|
||||
Toast.show(l`All friends followed!`, {type: 'success'})
|
||||
cumulativeFollowCount.current += followableDids.length
|
||||
},
|
||||
onError: _err => {
|
||||
Toast.show(_(msg`Failed to follow all your friends, please try again`), {
|
||||
Toast.show(l`Failed to follow all your friends, please try again`, {
|
||||
type: 'error',
|
||||
})
|
||||
for (const did of followableDids) {
|
||||
@@ -232,15 +231,13 @@ export function ViewMatches({
|
||||
dispatch({type: 'DISMISS_MATCH_FAILED', payload: {did}})
|
||||
if (isNetworkError(err)) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`Failed to hide suggestion, please check your internet connection`,
|
||||
),
|
||||
l`Failed to hide suggestion, please check your internet connection`,
|
||||
{type: 'error'},
|
||||
)
|
||||
} else {
|
||||
logger.error('Dismissing match failed', {safeMessage: err})
|
||||
Toast.show(
|
||||
_(msg`An error occurred while hiding suggestion. ${cleanError(err)}`),
|
||||
l`An error occurred while hiding suggestion. ${cleanError(err)}`,
|
||||
{type: 'error'},
|
||||
)
|
||||
}
|
||||
@@ -273,7 +270,7 @@ export function ViewMatches({
|
||||
}>
|
||||
{item.count > 1 && (
|
||||
<Button
|
||||
label={_(msg`Follow all`)}
|
||||
label={l`Follow all`}
|
||||
size="small"
|
||||
color="primary_subtle"
|
||||
onPress={() => followAll()}
|
||||
@@ -309,7 +306,7 @@ export function ViewMatches({
|
||||
case 'no matches header':
|
||||
return (
|
||||
<Header
|
||||
titleText={_(msg`You got here first`)}
|
||||
titleText={l`You got here first`}
|
||||
largeTitle
|
||||
subtitleText={
|
||||
<Trans>
|
||||
@@ -353,7 +350,7 @@ export function ViewMatches({
|
||||
]}>
|
||||
{context === 'Onboarding' && <OnboardingPosition />}
|
||||
<SearchInput
|
||||
placeholder={_(msg`Search contacts`)}
|
||||
placeholder={l`Search contacts`}
|
||||
value={search}
|
||||
onFocus={() => {
|
||||
onFocus()
|
||||
@@ -392,7 +389,7 @@ export function ViewMatches({
|
||||
{paddingBottom: insets.bottom + tokens.space.md},
|
||||
]}>
|
||||
<Button
|
||||
label={context === 'Onboarding' ? _(msg`Next`) : _(msg`Done`)}
|
||||
label={context === 'Onboarding' ? l`Next` : l`Done`}
|
||||
onPress={() => {
|
||||
if (context === 'Onboarding') {
|
||||
ax.metric('onboarding:contacts:nextPressed', {
|
||||
@@ -444,19 +441,19 @@ function MatchItem({
|
||||
}) {
|
||||
const gutter = useGutters([0, 'wide'])
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const shadow = useProfileShadow(profile)
|
||||
|
||||
const contactName = useMemo(() => {
|
||||
if (!contact) return null
|
||||
|
||||
const name = contact.name ?? contact.firstName ?? contact.lastName
|
||||
if (name) return _(msg`Your contact ${name}`)
|
||||
if (name) return l`Your contact ${name}`
|
||||
const phone =
|
||||
contact.phoneNumbers?.find(p => p.isPrimary) ?? contact.phoneNumbers?.[0]
|
||||
if (phone?.number) return phone.number
|
||||
return null
|
||||
}, [contact, _])
|
||||
}, [contact, l])
|
||||
|
||||
if (!moderationOpts) return null
|
||||
|
||||
@@ -497,7 +494,7 @@ function MatchItem({
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
label={_(msg`Remove suggestion`)}
|
||||
label={l`Remove suggestion`}
|
||||
onPress={() => onRemoveSuggestion(profile.did)}
|
||||
hoverStyle={[a.bg_transparent, {opacity: 0.5}]}
|
||||
hitSlop={8}>
|
||||
@@ -518,7 +515,7 @@ function ContactItem({
|
||||
}) {
|
||||
const gutter = useGutters([0, 'wide'])
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
@@ -564,7 +561,7 @@ function ContactItem({
|
||||
</Text>
|
||||
{phoneNumber && currentAccount && (
|
||||
<Button
|
||||
label={_(msg`Invite ${name} to join Bluesky`)}
|
||||
label={l`Invite ${name} to join Bluesky`}
|
||||
color="secondary"
|
||||
size="small"
|
||||
onPress={async () => {
|
||||
@@ -574,12 +571,10 @@ function ContactItem({
|
||||
try {
|
||||
await SMS.sendSMSAsync(
|
||||
[phoneNumber],
|
||||
_(
|
||||
msg`I'm on Bluesky as ${currentAccount.handle} - come find me! https://bsky.app/download`,
|
||||
),
|
||||
l`I'm on Bluesky as ${currentAccount.handle} - come find me! https://bsky.app/download`,
|
||||
)
|
||||
} catch (err) {
|
||||
Toast.show(_(msg`Failed to launch SMS app`), {type: 'error'})
|
||||
Toast.show(l`Failed to launch SMS app`, {type: 'error'})
|
||||
logger.error('Could not launch SMS', {safeMessage: err})
|
||||
}
|
||||
}}>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {wait} from '#/lib/async/wait'
|
||||
@@ -32,13 +31,12 @@ export function DeviceLocationRequestDialog({
|
||||
}: Props & {
|
||||
control: Dialog.DialogOuterProps['control']
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
return (
|
||||
<Dialog.Outer control={control}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Update your location`)}
|
||||
label={l`Update your location`}
|
||||
style={[web({maxWidth: 380})]}>
|
||||
<DeviceLocationRequestDialogInner
|
||||
onLocationAcquired={onLocationAcquired}
|
||||
@@ -51,7 +49,7 @@ export function DeviceLocationRequestDialog({
|
||||
|
||||
function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {close} = Dialog.useDialogContext()
|
||||
const requestDeviceLocation = useRequestDeviceGeolocation()
|
||||
const cleanError = useCleanError()
|
||||
@@ -78,13 +76,11 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
||||
closeDialog: close,
|
||||
})
|
||||
} else {
|
||||
setError(_(msg`Failed to resolve location. Please try again.`))
|
||||
setError(l`Failed to resolve location. Please try again.`)
|
||||
}
|
||||
} else {
|
||||
setError(
|
||||
_(
|
||||
msg`Unable to access location. You'll need to visit your system settings to enable location services for Bluesky.`,
|
||||
),
|
||||
l`Unable to access location. You'll need to visit your system settings to enable location services for Bluesky.`,
|
||||
)
|
||||
}
|
||||
} catch (e: any) {
|
||||
@@ -114,18 +110,16 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{error && (
|
||||
<View style={[a.pb_xs]}>
|
||||
<Admonition type="error">{error}</Admonition>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View style={[a.gap_sm]}>
|
||||
{!dialogDisabled && (
|
||||
<Button
|
||||
disabled={isRequesting}
|
||||
label={_(msg`Allow location access`)}
|
||||
label={l`Allow location access`}
|
||||
onPress={onPressConfirm}
|
||||
size={IS_WEB ? 'small' : 'large'}
|
||||
color="primary">
|
||||
@@ -138,7 +132,7 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
||||
|
||||
{!IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
onPress={() => close()}
|
||||
size={IS_WEB ? 'small' : 'large'}
|
||||
color="secondary">
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {memo, useEffect, useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs, type AppBskyFeedPost, AtUri} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {EMBED_SCRIPT} from '#/lib/constants'
|
||||
@@ -51,7 +50,7 @@ function EmbedDialogInner({
|
||||
timestamp,
|
||||
}: Omit<EmbedDialogProps, 'control'>) {
|
||||
const t = useTheme()
|
||||
const {_, i18n} = useLingui()
|
||||
const {t: l, i18n} = useLingui()
|
||||
const [copied, setCopied] = useState(false)
|
||||
const [showCustomisation, setShowCustomisation] = useState(false)
|
||||
const [colorMode, setColorMode] = useState<ColorModeValues>('system')
|
||||
@@ -102,7 +101,7 @@ function EmbedDialogInner({
|
||||
}, [i18n, postUri, postCid, record, timestamp, postAuthor, colorMode])
|
||||
|
||||
return (
|
||||
<Dialog.Inner label={_(msg`Embed post`)} style={[{maxWidth: 500}]}>
|
||||
<Dialog.Inner label={l`Embed post`} style={[{maxWidth: 500}]}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<View style={[a.gap_sm]}>
|
||||
<Text style={[a.text_2xl, a.font_bold]}>
|
||||
@@ -121,8 +120,8 @@ function EmbedDialogInner({
|
||||
<Button
|
||||
label={
|
||||
showCustomisation
|
||||
? _(msg`Hide customization options`)
|
||||
: _(msg`Show customization options`)
|
||||
? l`Hide customization options`
|
||||
: l`Show customization options`
|
||||
}
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
@@ -147,21 +146,21 @@ function EmbedDialogInner({
|
||||
<Trans>Color theme</Trans>
|
||||
</Text>
|
||||
<SegmentedControl.Root
|
||||
label={_(msg`Color mode`)}
|
||||
label={l`Color mode`}
|
||||
type="radio"
|
||||
value={colorMode}
|
||||
onChange={setColorMode}>
|
||||
<SegmentedControl.Item value="system" label={_(msg`System`)}>
|
||||
<SegmentedControl.Item value="system" label={l`System`}>
|
||||
<SegmentedControl.ItemText>
|
||||
<Trans>System</Trans>
|
||||
</SegmentedControl.ItemText>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item value="light" label={_(msg`Light`)}>
|
||||
<SegmentedControl.Item value="light" label={l`Light`}>
|
||||
<SegmentedControl.ItemText>
|
||||
<Trans>Light</Trans>
|
||||
</SegmentedControl.ItemText>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item value="dark" label={_(msg`Dark`)}>
|
||||
<SegmentedControl.Item value="dark" label={l`Dark`}>
|
||||
<SegmentedControl.ItemText>
|
||||
<Trans>Dark</Trans>
|
||||
</SegmentedControl.ItemText>
|
||||
@@ -175,7 +174,7 @@ function EmbedDialogInner({
|
||||
<TextField.Root>
|
||||
<TextField.Icon icon={CodeBracketsIcon} />
|
||||
<TextField.Input
|
||||
label={_(msg`Embed HTML code`)}
|
||||
label={l`Embed HTML code`}
|
||||
editable={false}
|
||||
selection={{start: 0, end: snippet.length}}
|
||||
value={snippet}
|
||||
@@ -183,7 +182,7 @@ function EmbedDialogInner({
|
||||
</TextField.Root>
|
||||
</View>
|
||||
<Button
|
||||
label={_(msg`Copy code`)}
|
||||
label={l`Copy code`}
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={() => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {
|
||||
@@ -25,7 +24,7 @@ export function EmbedConsentDialog({
|
||||
source: EmbedPlayerSource
|
||||
onAccept: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const setExternalEmbedPref = useSetExternalEmbedPref()
|
||||
|
||||
const onShowAllPress = useCallback(() => {
|
||||
@@ -51,7 +50,7 @@ export function EmbedConsentDialog({
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`External Media`)}
|
||||
label={l`External Media`}
|
||||
style={web({maxWidth: 400})}>
|
||||
<View style={a.gap_sm}>
|
||||
<Text style={[a.text_2xl, a.font_bold]}>
|
||||
@@ -77,7 +76,7 @@ export function EmbedConsentDialog({
|
||||
</View>
|
||||
<View style={a.gap_md}>
|
||||
<Button
|
||||
label={_(msg`Enable external media`)}
|
||||
label={l`Enable external media`}
|
||||
onPress={onShowAllPress}
|
||||
onAccessibilityEscape={control.close}
|
||||
color="primary"
|
||||
@@ -87,7 +86,7 @@ export function EmbedConsentDialog({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Enable this source only`)}
|
||||
label={l`Enable this source only`}
|
||||
onPress={onShowPress}
|
||||
onAccessibilityEscape={control.close}
|
||||
color="secondary"
|
||||
@@ -97,7 +96,7 @@ export function EmbedConsentDialog({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`No thanks`)}
|
||||
label={l`No thanks`}
|
||||
onAccessibilityEscape={control.close}
|
||||
onPress={onHidePress}
|
||||
color="secondary"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
||||
@@ -32,7 +31,7 @@ export function InAppBrowserConsentDialog() {
|
||||
|
||||
function InAppBrowserConsentInner({href}: {href?: string}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const setInAppBrowser = useSetInAppBrowser()
|
||||
const openLink = useOpenLink()
|
||||
@@ -60,7 +59,7 @@ function InAppBrowserConsentInner({href}: {href?: string}) {
|
||||
}, [control])
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner label={_(msg`How should we open this link?`)}>
|
||||
<Dialog.ScrollableInner label={l`How should we open this link?`}>
|
||||
<View style={[a.gap_2xl]}>
|
||||
<View style={[a.gap_sm]}>
|
||||
<Text style={[a.font_bold, a.text_2xl]}>
|
||||
@@ -75,7 +74,7 @@ function InAppBrowserConsentInner({href}: {href?: string}) {
|
||||
</View>
|
||||
<View style={[a.gap_sm]}>
|
||||
<Button
|
||||
label={_(msg`Use in-app browser`)}
|
||||
label={l`Use in-app browser`}
|
||||
onPress={onUseIAB}
|
||||
size="large"
|
||||
variant="solid"
|
||||
@@ -85,7 +84,7 @@ function InAppBrowserConsentInner({href}: {href?: string}) {
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Use my default browser`)}
|
||||
label={l`Use my default browser`}
|
||||
onPress={onUseLinking}
|
||||
size="large"
|
||||
variant="solid"
|
||||
@@ -96,7 +95,7 @@ function InAppBrowserConsentInner({href}: {href?: string}) {
|
||||
<ButtonIcon position="right" icon={External} />
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
onPress={onCancel}
|
||||
size="large"
|
||||
variant="ghost"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {languageName} from '#/locale/helpers'
|
||||
@@ -107,7 +106,7 @@ export function DialogInner({
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const handleClose = () => {
|
||||
control.close(() => {
|
||||
@@ -218,7 +217,7 @@ export function DialogInner({
|
||||
size="small"
|
||||
color="secondary"
|
||||
shape="round"
|
||||
label={_(msg`Close dialog`)}
|
||||
label={l`Close dialog`}
|
||||
onPress={handleClose}>
|
||||
<ButtonIcon icon={XIcon} />
|
||||
</Button>
|
||||
@@ -229,8 +228,8 @@ export function DialogInner({
|
||||
<SearchInput
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
placeholder={_(msg`Search languages`)}
|
||||
label={_(msg`Search languages`)}
|
||||
placeholder={l`Search languages`}
|
||||
label={l`Search languages`}
|
||||
maxLength={50}
|
||||
onClearText={() => setSearch('')}
|
||||
/>
|
||||
@@ -246,13 +245,13 @@ export function DialogInner({
|
||||
|
||||
const flatListData = [
|
||||
...(isCheckedRecentEmpty
|
||||
? [{type: 'header', label: _(msg`Recently used`)}]
|
||||
? [{type: 'header', label: l`Recently used`}]
|
||||
: []),
|
||||
...displayedLanguages.checkedRecent.map(lang => ({type: 'item', lang})),
|
||||
...displayedLanguages.uncheckedRecent.map(lang => ({type: 'item', lang})),
|
||||
...(isDisplayedLanguagesEmpty
|
||||
? []
|
||||
: [{type: 'header', label: _(msg`All languages`)}]),
|
||||
: [{type: 'header', label: l`All languages`}]),
|
||||
...displayedLanguages.all.map(lang => ({type: 'item', lang})),
|
||||
]
|
||||
|
||||
@@ -264,7 +263,7 @@ export function DialogInner({
|
||||
onChange={setCheckedLanguagesCode2}
|
||||
type="checkbox"
|
||||
maxSelections={maxLanguages}
|
||||
label={_(msg`Select languages`)}
|
||||
label={l`Select languages`}
|
||||
style={web([a.contents])}>
|
||||
<Dialog.InnerFlatList
|
||||
data={flatListData}
|
||||
@@ -319,7 +318,7 @@ export function DialogInner({
|
||||
<Dialog.FlatListFooter
|
||||
onLayout={evt => setFooterHeight(evt.nativeEvent.layout.height)}>
|
||||
<Button
|
||||
label={_(msg`Close dialog`)}
|
||||
label={l`Close dialog`}
|
||||
onPress={handleClose}
|
||||
color="primary"
|
||||
size="large">
|
||||
@@ -335,23 +334,19 @@ export function DialogInner({
|
||||
}
|
||||
|
||||
function DialogError({details}: {details?: string}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const control = Dialog.useDialogContext()
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
style={a.gap_md}
|
||||
label={_(msg`An error has occurred`)}>
|
||||
<Dialog.ScrollableInner style={a.gap_md} label={l`An error has occurred`}>
|
||||
<Dialog.Close />
|
||||
<ErrorScreen
|
||||
title={_(msg`Oh no!`)}
|
||||
message={_(
|
||||
msg`There was an unexpected issue in the application. Please let us know if this happened to you!`,
|
||||
)}
|
||||
title={l`Oh no!`}
|
||||
message={l`There was an unexpected issue in the application. Please let us know if this happened to you!`}
|
||||
details={details}
|
||||
/>
|
||||
<Button
|
||||
label={_(msg`Close dialog`)}
|
||||
label={l`Close dialog`}
|
||||
onPress={() => control.close()}
|
||||
color="primary"
|
||||
size="large">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
||||
@@ -49,7 +48,7 @@ function LinkWarningDialogInner({
|
||||
link?: {href: string; displayText: string; share?: boolean}
|
||||
}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const openLink = useOpenLink()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -79,8 +78,8 @@ function LinkWarningDialogInner({
|
||||
style={web({maxWidth: 450})}
|
||||
label={
|
||||
potentiallyMisleading
|
||||
? _(msg`Potentially misleading link warning`)
|
||||
: _(msg`Leaving Bluesky`)
|
||||
? l`Potentially misleading link warning`
|
||||
: l`Leaving Bluesky`
|
||||
}>
|
||||
<View style={[a.gap_2xl]}>
|
||||
<View style={[a.gap_sm]}>
|
||||
@@ -109,8 +108,8 @@ function LinkWarningDialogInner({
|
||||
gtMobile && [a.flex_row_reverse, a.justify_start],
|
||||
]}>
|
||||
<Button
|
||||
label={link?.share ? _(msg`Share link`) : _(msg`Visit site`)}
|
||||
accessibilityHint={_(msg`Opens link ${link?.href ?? ''}`)}
|
||||
label={link?.share ? l`Share link` : l`Visit site`}
|
||||
accessibilityHint={l`Opens link ${link?.href ?? ''}`}
|
||||
onPress={onPressVisit}
|
||||
size="large"
|
||||
variant="solid"
|
||||
@@ -124,7 +123,7 @@ function LinkWarningDialogInner({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Go back`)}
|
||||
label={l`Go back`}
|
||||
onPress={onCancel}
|
||||
size="large"
|
||||
variant="ghost"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs, sanitizeMutedWordValue} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
@@ -50,7 +49,7 @@ export function MutedWordsDialog() {
|
||||
|
||||
function MutedWordsInner() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {
|
||||
isLoading: isPreferencesLoading,
|
||||
@@ -86,7 +85,7 @@ function MutedWordsInner() {
|
||||
|
||||
if (!sanitizedValue || !surfaces.length) {
|
||||
setField('')
|
||||
setError(_(msg`Please enter a valid word, tag, or phrase to mute`))
|
||||
setError(l`Please enter a valid word, tag, or phrase to mute`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,10 +104,10 @@ function MutedWordsInner() {
|
||||
logger.error(`Failed to save muted word`, {message: e.message})
|
||||
setError(e.message)
|
||||
}
|
||||
}, [_, field, targets, addMutedWord, setField, durations, excludeFollowing])
|
||||
}, [l, field, targets, addMutedWord, setField, durations, excludeFollowing])
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner label={_(msg`Manage your muted words and tags`)}>
|
||||
<Dialog.ScrollableInner label={l`Manage your muted words and tags`}>
|
||||
<View>
|
||||
<Text
|
||||
style={[
|
||||
@@ -133,8 +132,8 @@ function MutedWordsInner() {
|
||||
autoCapitalize="none"
|
||||
autoComplete="off"
|
||||
returnKeyType="done"
|
||||
label={_(msg`Enter a word or tag`)}
|
||||
placeholder={_(msg`Enter a word or tag`)}
|
||||
label={l`Enter a word or tag`}
|
||||
placeholder={l`Enter a word or tag`}
|
||||
value={field}
|
||||
onChangeText={value => {
|
||||
if (error) {
|
||||
@@ -148,7 +147,7 @@ function MutedWordsInner() {
|
||||
|
||||
<View style={[a.pb_xl, a.gap_sm]}>
|
||||
<Toggle.Group
|
||||
label={_(msg`Select how long to mute this word for.`)}
|
||||
label={l`Select how long to mute this word for.`}
|
||||
type="radio"
|
||||
values={durations}
|
||||
onChange={setDurations}>
|
||||
@@ -176,7 +175,7 @@ function MutedWordsInner() {
|
||||
a.gap_sm,
|
||||
]}>
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word until you unmute it`)}
|
||||
label={l`Mute this word until you unmute it`}
|
||||
name="forever"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -191,7 +190,7 @@ function MutedWordsInner() {
|
||||
</Toggle.Item>
|
||||
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word for 24 hours`)}
|
||||
label={l`Mute this word for 24 hours`}
|
||||
name="24_hours"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -215,7 +214,7 @@ function MutedWordsInner() {
|
||||
a.gap_sm,
|
||||
]}>
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word for 7 days`)}
|
||||
label={l`Mute this word for 7 days`}
|
||||
name="7_days"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -230,7 +229,7 @@ function MutedWordsInner() {
|
||||
</Toggle.Item>
|
||||
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word for 30 days`)}
|
||||
label={l`Mute this word for 30 days`}
|
||||
name="30_days"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -248,7 +247,7 @@ function MutedWordsInner() {
|
||||
</Toggle.Group>
|
||||
|
||||
<Toggle.Group
|
||||
label={_(msg`Select what content this mute word should apply to.`)}
|
||||
label={l`Select what content this mute word should apply to.`}
|
||||
type="radio"
|
||||
values={targets}
|
||||
onChange={setTargets}>
|
||||
@@ -264,7 +263,7 @@ function MutedWordsInner() {
|
||||
|
||||
<View style={[a.flex_row, a.align_center, a.gap_sm, a.flex_wrap]}>
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word in post text and tags`)}
|
||||
label={l`Mute this word in post text and tags`}
|
||||
name="content"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -280,7 +279,7 @@ function MutedWordsInner() {
|
||||
</Toggle.Item>
|
||||
|
||||
<Toggle.Item
|
||||
label={_(msg`Mute this word in tags only`)}
|
||||
label={l`Mute this word in tags only`}
|
||||
name="tag"
|
||||
style={[a.flex_1]}>
|
||||
<TargetToggle>
|
||||
@@ -308,7 +307,7 @@ function MutedWordsInner() {
|
||||
<Trans>Options:</Trans>
|
||||
</Text>
|
||||
<Toggle.Item
|
||||
label={_(msg`Do not apply this mute word to users you follow`)}
|
||||
label={l`Do not apply this mute word to users you follow`}
|
||||
name="exclude_following"
|
||||
style={[a.flex_row, a.justify_between]}
|
||||
value={excludeFollowing}
|
||||
@@ -327,7 +326,7 @@ function MutedWordsInner() {
|
||||
<View style={[a.pt_xs]}>
|
||||
<Button
|
||||
disabled={isPending || !field}
|
||||
label={_(msg`Add mute word with chosen settings`)}
|
||||
label={l`Add mute word with chosen settings`}
|
||||
size="large"
|
||||
color="primary"
|
||||
variant="solid"
|
||||
@@ -412,7 +411,6 @@ function MutedWordsInner() {
|
||||
|
||||
{IS_NATIVE && <View style={{height: 20}} />}
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
@@ -423,7 +421,7 @@ function MutedWordRow({
|
||||
word,
|
||||
}: ViewStyleProp & {word: AppBskyActorDefs.MutedWord}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation()
|
||||
const {mutateAsync: updateMutedWord} = useUpdateMutedWordMutation()
|
||||
const control = Prompt.usePromptControl()
|
||||
@@ -449,15 +447,12 @@ function MutedWordRow({
|
||||
<>
|
||||
<Prompt.Basic
|
||||
control={control}
|
||||
title={_(msg`Are you sure?`)}
|
||||
description={_(
|
||||
msg`This will delete "${word.value}" from your muted words. You can always add it back later.`,
|
||||
)}
|
||||
title={l`Are you sure?`}
|
||||
description={l`This will delete "${word.value}" from your muted words. You can always add it back later.`}
|
||||
onConfirm={remove}
|
||||
confirmButtonCta={_(msg`Remove`)}
|
||||
confirmButtonCta={l`Remove`}
|
||||
confirmButtonColor="negative"
|
||||
/>
|
||||
|
||||
<View
|
||||
style={[
|
||||
a.flex_row,
|
||||
@@ -528,7 +523,7 @@ function MutedWordRow({
|
||||
{' · '}
|
||||
</Text>
|
||||
<Menu.Root>
|
||||
<Menu.Trigger label={_(msg`Renew mute word`)}>
|
||||
<Menu.Trigger label={l`Renew mute word`}>
|
||||
{({props}) => (
|
||||
<Text
|
||||
{...props}
|
||||
@@ -548,29 +543,25 @@ function MutedWordRow({
|
||||
</Menu.LabelText>
|
||||
<Menu.Group>
|
||||
<Menu.Item
|
||||
label={_(msg`24 hours`)}
|
||||
label={l`24 hours`}
|
||||
onPress={() => renew(1)}>
|
||||
<Menu.ItemText>
|
||||
<Trans>24 hours</Trans>
|
||||
</Menu.ItemText>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
label={_(msg`7 days`)}
|
||||
onPress={() => renew(7)}>
|
||||
<Menu.Item label={l`7 days`} onPress={() => renew(7)}>
|
||||
<Menu.ItemText>
|
||||
<Trans>7 days</Trans>
|
||||
</Menu.ItemText>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
label={_(msg`30 days`)}
|
||||
label={l`30 days`}
|
||||
onPress={() => renew(30)}>
|
||||
<Menu.ItemText>
|
||||
<Trans>30 days</Trans>
|
||||
</Menu.ItemText>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
label={_(msg`Forever`)}
|
||||
onPress={() => renew()}>
|
||||
<Menu.Item label={l`Forever`} onPress={() => renew()}>
|
||||
<Menu.ItemText>
|
||||
<Trans>Forever</Trans>
|
||||
</Menu.ItemText>
|
||||
@@ -610,7 +601,7 @@ function MutedWordRow({
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={_(msg`Remove mute word from your list`)}
|
||||
label={l`Remove mute word from your list`}
|
||||
size="tiny"
|
||||
shape="round"
|
||||
variant="outline"
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
type AppBskyFeedPostgate,
|
||||
AtUri,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
@@ -109,11 +108,11 @@ export function PostInteractionSettingsControlledDialog({
|
||||
}
|
||||
|
||||
function DialogInner(props: Omit<PostInteractionSettingsFormProps, 'control'>) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Edit post interaction settings`)}
|
||||
label={l`Edit post interaction settings`}
|
||||
style={[web({maxWidth: 400}), a.w_full]}>
|
||||
<Header />
|
||||
<PostInteractionSettingsForm {...props} />
|
||||
@@ -164,7 +163,7 @@ export function PostInteractionSettingsDialogControlledInner(
|
||||
props: PostInteractionSettingsDialogProps,
|
||||
) {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const [isSaving, setIsSaving] = useState(false)
|
||||
|
||||
@@ -237,9 +236,7 @@ export function PostInteractionSettingsDialogControlledInner(
|
||||
safeMessage: e.message,
|
||||
})
|
||||
Toast.show(
|
||||
_(
|
||||
msg`There was an issue. Please check your internet connection and try again.`,
|
||||
),
|
||||
l`There was an issue. Please check your internet connection and try again.`,
|
||||
{
|
||||
type: 'error',
|
||||
},
|
||||
@@ -248,7 +245,7 @@ export function PostInteractionSettingsDialogControlledInner(
|
||||
setIsSaving(false)
|
||||
}
|
||||
}, [
|
||||
_,
|
||||
l,
|
||||
ax,
|
||||
props.postUri,
|
||||
props.rootPostUri,
|
||||
@@ -263,7 +260,7 @@ export function PostInteractionSettingsDialogControlledInner(
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Edit post interaction settings`)}
|
||||
label={l`Edit post interaction settings`}
|
||||
style={[web({maxWidth: 400}), a.w_full]}>
|
||||
{isLoading ? (
|
||||
<View
|
||||
@@ -312,7 +309,7 @@ export function PostInteractionSettingsForm({
|
||||
onChangePersist,
|
||||
}: PostInteractionSettingsFormProps) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const playHaptic = useHaptics()
|
||||
const [showLists, setShowLists] = useState(false)
|
||||
const {
|
||||
@@ -428,7 +425,7 @@ export function PostInteractionSettingsForm({
|
||||
</Text>
|
||||
|
||||
<Toggle.Group
|
||||
label={_(msg`Set who can reply to your post`)}
|
||||
label={l`Set who can reply to your post`}
|
||||
type="radio"
|
||||
maxSelections={1}
|
||||
disabled={replySettingsDisabled}
|
||||
@@ -448,7 +445,7 @@ export function PostInteractionSettingsForm({
|
||||
<Toggle.Item
|
||||
name="everyone"
|
||||
type="checkbox"
|
||||
label={_(msg`Allow anyone to reply`)}
|
||||
label={l`Allow anyone to reply`}
|
||||
style={[a.flex_1]}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel active={selected}>
|
||||
@@ -462,7 +459,7 @@ export function PostInteractionSettingsForm({
|
||||
<Toggle.Item
|
||||
name="nobody"
|
||||
type="checkbox"
|
||||
label={_(msg`Disable replies entirely`)}
|
||||
label={l`Disable replies entirely`}
|
||||
style={[a.flex_1]}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel active={selected}>
|
||||
@@ -477,9 +474,7 @@ export function PostInteractionSettingsForm({
|
||||
</Toggle.Group>
|
||||
|
||||
<Toggle.Group
|
||||
label={_(
|
||||
msg`Set precisely which groups of people can reply to your post`,
|
||||
)}
|
||||
label={l`Set precisely which groups of people can reply to your post`}
|
||||
values={toggleGroupValues}
|
||||
onChange={toggleGroupOnChange}
|
||||
disabled={replySettingsDisabled}>
|
||||
@@ -487,7 +482,7 @@ export function PostInteractionSettingsForm({
|
||||
<Toggle.Item
|
||||
name="followers"
|
||||
type="checkbox"
|
||||
label={_(msg`Allow your followers to reply`)}
|
||||
label={l`Allow your followers to reply`}
|
||||
hitSlop={0}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel active={selected} adjacent="trailing">
|
||||
@@ -501,7 +496,7 @@ export function PostInteractionSettingsForm({
|
||||
<Toggle.Item
|
||||
name="following"
|
||||
type="checkbox"
|
||||
label={_(msg`Allow people you follow to reply`)}
|
||||
label={l`Allow people you follow to reply`}
|
||||
hitSlop={0}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel active={selected} adjacent="both">
|
||||
@@ -515,7 +510,7 @@ export function PostInteractionSettingsForm({
|
||||
<Toggle.Item
|
||||
name="mention"
|
||||
type="checkbox"
|
||||
label={_(msg`Allow people you mention to reply`)}
|
||||
label={l`Allow people you mention to reply`}
|
||||
hitSlop={0}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel active={selected} adjacent="both">
|
||||
@@ -530,8 +525,8 @@ export function PostInteractionSettingsForm({
|
||||
<Button
|
||||
label={
|
||||
showLists
|
||||
? _(msg`Hide lists`)
|
||||
: _(msg`Show lists of users to select from`)
|
||||
? l`Hide lists`
|
||||
: l`Show lists of users to select from`
|
||||
}
|
||||
accessibilityRole="togglebutton"
|
||||
hitSlop={0}
|
||||
@@ -595,7 +590,7 @@ export function PostInteractionSettingsForm({
|
||||
key={list.uri}
|
||||
name={`list:${list.uri}`}
|
||||
type="checkbox"
|
||||
label={_(msg`Allow users in ${list.name} to reply`)}
|
||||
label={l`Allow users in ${list.name} to reply`}
|
||||
hitSlop={0}>
|
||||
{({selected}) => (
|
||||
<Toggle.Panel
|
||||
@@ -619,14 +614,13 @@ export function PostInteractionSettingsForm({
|
||||
</Toggle.Group>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Toggle.Item
|
||||
name="quoteposts"
|
||||
type="checkbox"
|
||||
label={
|
||||
quotesEnabled
|
||||
? _(msg`Disable quote posts of this post`)
|
||||
: _(msg`Enable quote posts of this post`)
|
||||
? l`Disable quote posts of this post`
|
||||
: l`Enable quote posts of this post`
|
||||
}
|
||||
value={quotesEnabled}
|
||||
onChange={onChangeQuotesEnabled}>
|
||||
@@ -639,14 +633,13 @@ export function PostInteractionSettingsForm({
|
||||
</Toggle.Panel>
|
||||
)}
|
||||
</Toggle.Item>
|
||||
|
||||
{typeof persist !== 'undefined' && (
|
||||
<View style={[{minHeight: 24}, a.justify_center]}>
|
||||
{isDirty ? (
|
||||
<Toggle.Item
|
||||
name="persist"
|
||||
type="checkbox"
|
||||
label={_(msg`Save these options for next time`)}
|
||||
label={l`Save these options for next time`}
|
||||
value={persist}
|
||||
onChange={() => onChangePersist?.(!persist)}>
|
||||
<Toggle.Checkbox />
|
||||
@@ -662,10 +655,9 @@ export function PostInteractionSettingsForm({
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
|
||||
<Button
|
||||
disabled={!canSave || isSaving}
|
||||
label={_(msg`Save`)}
|
||||
label={l`Save`}
|
||||
onPress={onSave}
|
||||
color="primary"
|
||||
size="large">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback, useImperativeHandle, useRef, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {BSKY_SERVICE} from '#/lib/constants'
|
||||
@@ -78,7 +77,7 @@ function DialogInner({
|
||||
initialCustomAddress: string
|
||||
}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const {accounts} = useSession()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -135,24 +134,20 @@ function DialogInner({
|
||||
</Text>
|
||||
<SegmentedControl.Root
|
||||
type="tabs"
|
||||
label={_(msg`Hosting provider`)}
|
||||
label={l`Hosting provider`}
|
||||
value={fixedOption}
|
||||
onChange={setFixedOption}>
|
||||
<SegmentedControl.Item
|
||||
testID="bskyServiceSelectBtn"
|
||||
value={BSKY_SERVICE}
|
||||
label={_(msg`Bluesky`)}>
|
||||
<SegmentedControl.ItemText>
|
||||
{_(msg`Bluesky`)}
|
||||
</SegmentedControl.ItemText>
|
||||
label={l`Bluesky`}>
|
||||
<SegmentedControl.ItemText>{l`Bluesky`}</SegmentedControl.ItemText>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item
|
||||
testID="customSelectBtn"
|
||||
value="custom"
|
||||
label={_(msg`Custom`)}>
|
||||
<SegmentedControl.ItemText>
|
||||
{_(msg`Custom`)}
|
||||
</SegmentedControl.ItemText>
|
||||
label={l`Custom`}>
|
||||
<SegmentedControl.ItemText>{l`Custom`}</SegmentedControl.ItemText>
|
||||
</SegmentedControl.Item>
|
||||
</SegmentedControl.Root>
|
||||
|
||||
@@ -217,7 +212,7 @@ function DialogInner({
|
||||
</Trans>
|
||||
)}{' '}
|
||||
<InlineLinkText
|
||||
label={_(msg`Learn more about self hosting your PDS.`)}
|
||||
label={l`Learn more about self hosting your PDS.`}
|
||||
to="https://atproto.com/guides/self-hosting">
|
||||
<Trans>Learn more.</Trans>
|
||||
</InlineLinkText>
|
||||
@@ -234,7 +229,7 @@ function DialogInner({
|
||||
web: 'small',
|
||||
})}
|
||||
onPress={() => control.close()}
|
||||
label={_(msg`Done`)}>
|
||||
label={l`Done`}>
|
||||
<ButtonText>
|
||||
<Trans>Done</Trans>
|
||||
</ButtonText>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
@@ -27,7 +26,7 @@ export function SigninDialog() {
|
||||
|
||||
function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
@@ -44,7 +43,7 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Sign in to Bluesky or create a new account`)}
|
||||
label={l`Sign in to Bluesky or create a new account`}
|
||||
style={[gtMobile ? {width: 'auto', maxWidth: 420} : a.w_full]}>
|
||||
<View style={[!IS_NATIVE && a.p_2xl]}>
|
||||
<View
|
||||
@@ -84,7 +83,7 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={showCreateAccount}
|
||||
label={_(msg`Create an account`)}>
|
||||
label={l`Create an account`}>
|
||||
<ButtonText>
|
||||
<Trans>Create an account</Trans>
|
||||
</ButtonText>
|
||||
@@ -95,7 +94,7 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
||||
color="secondary"
|
||||
size="large"
|
||||
onPress={showSignIn}
|
||||
label={_(msg`Sign in`)}>
|
||||
label={l`Sign in`}>
|
||||
<ButtonText>
|
||||
<Trans>Sign in</Trans>
|
||||
</ButtonText>
|
||||
@@ -104,7 +103,6 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
||||
|
||||
{IS_NATIVE && <View style={{height: 10}} />}
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
|
||||
@@ -4,8 +4,7 @@ import {
|
||||
type AppBskyGraphGetStarterPacksWithMembership,
|
||||
AppBskyGraphStarterpack,
|
||||
} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
@@ -88,7 +87,7 @@ export function StarterPackDialog({
|
||||
}
|
||||
|
||||
function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
@@ -102,10 +101,9 @@ function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
||||
<Trans>You have no starter packs.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={[a.align_center]}>
|
||||
<Button
|
||||
label={_(msg`Create starter pack`)}
|
||||
label={l`Create starter pack`}
|
||||
color="secondary_inverted"
|
||||
size="small"
|
||||
onPress={onStartWizard}>
|
||||
@@ -131,7 +129,7 @@ function StarterPackList({
|
||||
enabled?: boolean
|
||||
}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {data: subject} = useProfileQuery({did: targetDid})
|
||||
|
||||
const {
|
||||
@@ -184,7 +182,7 @@ function StarterPackList({
|
||||
<Trans>Add to starter packs</Trans>
|
||||
</Text>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
onPress={onClose}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
@@ -202,7 +200,7 @@ function StarterPackList({
|
||||
<Trans>New starter pack</Trans>
|
||||
</Text>
|
||||
<Button
|
||||
label={_(msg`Create starter pack`)}
|
||||
label={l`Create starter pack`}
|
||||
color="secondary_inverted"
|
||||
size="small"
|
||||
onPress={onStartWizard}>
|
||||
@@ -260,7 +258,7 @@ function StarterPackItem({
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const isSelf = subject?.did === currentAccount?.did
|
||||
|
||||
@@ -271,26 +269,26 @@ function StarterPackItem({
|
||||
useListMembershipAddMutation({
|
||||
subject,
|
||||
onSuccess: () => {
|
||||
Toast.show(_(msg`Added to starter pack`))
|
||||
Toast.show(l`Added to starter pack`)
|
||||
},
|
||||
onError: err => {
|
||||
if (!isNetworkError(err)) {
|
||||
logger.error('Failed to add to starter pack', {safeMessage: err})
|
||||
}
|
||||
Toast.show(_(msg`Failed to add to starter pack`), {type: 'error'})
|
||||
Toast.show(l`Failed to add to starter pack`, {type: 'error'})
|
||||
},
|
||||
})
|
||||
|
||||
const {mutate: removeMembership, isPending: isPendingRemove} =
|
||||
useListMembershipRemoveMutation({
|
||||
onSuccess: () => {
|
||||
Toast.show(_(msg`Removed from starter pack`))
|
||||
Toast.show(l`Removed from starter pack`)
|
||||
},
|
||||
onError: err => {
|
||||
if (!isNetworkError(err)) {
|
||||
logger.error('Failed to remove from starter pack', {safeMessage: err})
|
||||
}
|
||||
Toast.show(_(msg`Failed to remove from starter pack`), {type: 'error'})
|
||||
Toast.show(l`Failed to remove from starter pack`, {type: 'error'})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -371,9 +369,8 @@ function StarterPackItem({
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={isInPack ? _(msg`Remove`) : _(msg`Add`)}
|
||||
label={isInPack ? l`Remove` : l`Add`}
|
||||
color={isInPack ? 'secondary' : 'primary_subtle'}
|
||||
size="tiny"
|
||||
disabled={isPending || isSelf}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
|
||||
@@ -17,7 +16,7 @@ export function SwitchAccountDialog({
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const {onPressSwitchAccount, pendingDid} = useAccountSwitcher()
|
||||
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||
@@ -44,7 +43,7 @@ export function SwitchAccountDialog({
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner label={_(msg`Switch account`)}>
|
||||
<Dialog.ScrollableInner label={l`Switch account`}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<Text style={[a.text_2xl, a.font_semi_bold]}>
|
||||
<Trans>Switch account</Trans>
|
||||
@@ -53,7 +52,7 @@ export function SwitchAccountDialog({
|
||||
<AccountList
|
||||
onSelectAccount={onSelectAccount}
|
||||
onSelectOther={onPressAddAccount}
|
||||
otherLabel={_(msg`Add account`)}
|
||||
otherLabel={l`Add account`}
|
||||
pendingDid={pendingDid}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
type ComAtprotoRepoApplyWrites,
|
||||
} from '@atproto/api'
|
||||
import {TID} from '@atproto/common-web'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
@@ -38,7 +37,7 @@ export function CreateListFromStarterPackDialog({
|
||||
control: Dialog.DialogControlProps
|
||||
starterPack: AppBskyGraphDefs.StarterPackView
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const agent = useAgent()
|
||||
const ax = useAnalytics()
|
||||
@@ -124,7 +123,7 @@ export function CreateListFromStarterPackDialog({
|
||||
})
|
||||
} catch (e) {
|
||||
logger.error('Failed to add members to list', {safeMessage: e})
|
||||
Toast.show(_(msg`List created, but failed to add some members`), {
|
||||
Toast.show(l`List created, but failed to add some members`, {
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
@@ -145,7 +144,7 @@ export function CreateListFromStarterPackDialog({
|
||||
nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Create list from starter pack`)}
|
||||
label={l`Create list from starter pack`}
|
||||
style={web({maxWidth: 400})}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<Text style={[a.text_xl, a.font_bold]}>
|
||||
@@ -177,7 +176,7 @@ export function CreateListFromStarterPackDialog({
|
||||
a.pt_sm,
|
||||
]}>
|
||||
<Button
|
||||
label={_(msg`Create list`)}
|
||||
label={l`Create list`}
|
||||
onPress={onPressCreate}
|
||||
size={platform({
|
||||
web: 'small',
|
||||
@@ -189,7 +188,7 @@ export function CreateListFromStarterPackDialog({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
onPress={() => control.close()}
|
||||
size={platform({
|
||||
web: 'small',
|
||||
@@ -205,7 +204,6 @@ export function CreateListFromStarterPackDialog({
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
</Dialog.Outer>
|
||||
|
||||
<CreateOrEditListDialog
|
||||
control={createDialogControl}
|
||||
purpose="app.bsky.graph.defs#curatelist"
|
||||
@@ -216,13 +214,12 @@ export function CreateListFromStarterPackDialog({
|
||||
avatar: starterPack.list?.avatar,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Dialog.Outer
|
||||
control={loadingDialogControl}
|
||||
nativeOptions={{preventDismiss: true}}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Adding members to list...`)}
|
||||
label={l`Adding members to list...`}
|
||||
style={web({maxWidth: 400})}>
|
||||
<View style={[a.align_center, a.gap_lg, a.py_5xl]}>
|
||||
<Loader size="xl" />
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback, useEffect, useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyGraphDefs, RichText as RichTextAPI} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
@@ -50,7 +49,7 @@ export function CreateOrEditListDialog({
|
||||
onSave?: (uri: string) => void
|
||||
initialValues?: InitialListValues
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const cancelControl = Dialog.useDialogControl()
|
||||
const [dirty, setDirty] = useState(false)
|
||||
|
||||
@@ -92,13 +91,12 @@ export function CreateOrEditListDialog({
|
||||
onPressCancel={onPressCancel}
|
||||
initialValues={initialValues}
|
||||
/>
|
||||
|
||||
<Prompt.Basic
|
||||
control={cancelControl}
|
||||
title={_(msg`Discard changes?`)}
|
||||
description={_(msg`Are you sure you want to discard your changes?`)}
|
||||
title={l`Discard changes?`}
|
||||
description={l`Are you sure you want to discard your changes?`}
|
||||
onConfirm={() => control.close()}
|
||||
confirmButtonCta={_(msg`Discard`)}
|
||||
confirmButtonCta={l`Discard`}
|
||||
confirmButtonColor="negative"
|
||||
/>
|
||||
</Dialog.Outer>
|
||||
@@ -131,7 +129,7 @@ function DialogInner({
|
||||
}, [list, purpose])
|
||||
const isCurateList = activePurpose === 'app.bsky.graph.defs#curatelist'
|
||||
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const agent = useAgent()
|
||||
const control = Dialog.useDialogContext()
|
||||
@@ -238,8 +236,8 @@ function DialogInner({
|
||||
})
|
||||
Toast.show(
|
||||
isCurateList
|
||||
? _(msg({message: 'User list updated', context: 'toast'}))
|
||||
: _(msg({message: 'Moderation list updated', context: 'toast'})),
|
||||
? l({message: 'User list updated', context: 'toast'})
|
||||
: l({message: 'Moderation list updated', context: 'toast'}),
|
||||
)
|
||||
control.close(() => onSave?.(list.uri))
|
||||
} else {
|
||||
@@ -252,8 +250,8 @@ function DialogInner({
|
||||
})
|
||||
Toast.show(
|
||||
isCurateList
|
||||
? _(msg({message: 'User list created', context: 'toast'}))
|
||||
: _(msg({message: 'Moderation list created', context: 'toast'})),
|
||||
? l({message: 'User list created', context: 'toast'})
|
||||
: l({message: 'Moderation list created', context: 'toast'}),
|
||||
)
|
||||
control.close(() => onSave?.(uri))
|
||||
}
|
||||
@@ -273,7 +271,7 @@ function DialogInner({
|
||||
activePurpose,
|
||||
isCurateList,
|
||||
agent,
|
||||
_,
|
||||
l,
|
||||
])
|
||||
|
||||
const displayNameTooLong = isOverMaxGraphemeCount({
|
||||
@@ -288,7 +286,7 @@ function DialogInner({
|
||||
const cancelButton = useCallback(
|
||||
() => (
|
||||
<Button
|
||||
label={_(msg`Cancel`)}
|
||||
label={l`Cancel`}
|
||||
onPress={onPressCancel}
|
||||
size="small"
|
||||
color="primary"
|
||||
@@ -300,13 +298,13 @@ function DialogInner({
|
||||
</ButtonText>
|
||||
</Button>
|
||||
),
|
||||
[onPressCancel, _],
|
||||
[onPressCancel, l],
|
||||
)
|
||||
|
||||
const saveButton = useCallback(
|
||||
() => (
|
||||
<Button
|
||||
label={_(msg`Save`)}
|
||||
label={l`Save`}
|
||||
onPress={onPressSave}
|
||||
disabled={
|
||||
!dirty ||
|
||||
@@ -327,7 +325,7 @@ function DialogInner({
|
||||
</Button>
|
||||
),
|
||||
[
|
||||
_,
|
||||
l,
|
||||
t,
|
||||
dirty,
|
||||
onPressSave,
|
||||
@@ -360,19 +358,19 @@ function DialogInner({
|
||||
|
||||
const title = list
|
||||
? isCurateList
|
||||
? _(msg`Edit user list`)
|
||||
: _(msg`Edit moderation list`)
|
||||
? l`Edit user list`
|
||||
: l`Edit moderation list`
|
||||
: isCurateList
|
||||
? _(msg`Create user list`)
|
||||
: _(msg`Create moderation list`)
|
||||
? l`Create user list`
|
||||
: l`Create moderation list`
|
||||
|
||||
const displayNamePlaceholder = isCurateList
|
||||
? _(msg`e.g. Great Posters`)
|
||||
: _(msg`e.g. Spammers`)
|
||||
? l`e.g. Great Posters`
|
||||
: l`e.g. Spammers`
|
||||
|
||||
const descriptionPlaceholder = isCurateList
|
||||
? _(msg`e.g. The posters who never miss.`)
|
||||
: _(msg`e.g. Users that repeatedly reply with ads.`)
|
||||
? l`e.g. The posters who never miss.`
|
||||
: l`e.g. Users that repeatedly reply with ads.`
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
@@ -413,7 +411,7 @@ function DialogInner({
|
||||
<Dialog.Input
|
||||
defaultValue={displayName}
|
||||
onChangeText={onChangeDisplayName}
|
||||
label={_(msg`Name`)}
|
||||
label={l`Name`}
|
||||
placeholder={displayNamePlaceholder}
|
||||
testID="editListNameInput"
|
||||
/>
|
||||
@@ -450,7 +448,7 @@ function DialogInner({
|
||||
defaultValue={descriptionRt.text}
|
||||
onChangeText={onChangeDescription}
|
||||
multiline
|
||||
label={_(msg`Description`)}
|
||||
label={l`Description`}
|
||||
placeholder={descriptionPlaceholder}
|
||||
testID="editListDescriptionInput"
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback, useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyGraphDefs, type ModerationOpts} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
@@ -57,7 +56,7 @@ function DialogInner({
|
||||
profile: bsky.profile.AnyProfileView,
|
||||
) => void | undefined
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const {data: listMembers} = useAllListMembersQuery(list.uri)
|
||||
|
||||
@@ -78,7 +77,7 @@ function DialogInner({
|
||||
|
||||
return (
|
||||
<SearchablePeopleList
|
||||
title={_(msg`Add people to list`)}
|
||||
title={l`Add people to list`}
|
||||
renderProfileCard={renderProfileCard}
|
||||
/>
|
||||
)
|
||||
@@ -114,7 +113,7 @@ function UserResult({
|
||||
) => void | undefined
|
||||
moderationOpts?: ModerationOpts
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const membership = useMemo(
|
||||
() => getMembership(listMembers, profile.did),
|
||||
[listMembers, profile.did],
|
||||
@@ -122,7 +121,7 @@ function UserResult({
|
||||
const {mutate: listMembershipAdd, isPending: isAddingPending} =
|
||||
useListMembershipAddMutation({
|
||||
onSuccess: () => {
|
||||
Toast.show(_(msg`Added to list`))
|
||||
Toast.show(l`Added to list`)
|
||||
onChange?.('add', profile)
|
||||
},
|
||||
onError: e =>
|
||||
@@ -133,7 +132,7 @@ function UserResult({
|
||||
const {mutate: listMembershipRemove, isPending: isRemovingPending} =
|
||||
useListMembershipRemoveMutation({
|
||||
onSuccess: () => {
|
||||
Toast.show(_(msg`Removed from list`))
|
||||
Toast.show(l`Removed from list`)
|
||||
onChange?.('remove', profile)
|
||||
},
|
||||
onError: e =>
|
||||
@@ -175,8 +174,8 @@ function UserResult({
|
||||
<Button
|
||||
label={
|
||||
membership === false
|
||||
? _(msg`Add user to list`)
|
||||
: _(msg`Remove user from list`)
|
||||
? l`Add user to list`
|
||||
: l`Remove user from list`
|
||||
}
|
||||
onPress={onToggleMembership}
|
||||
disabled={isMutating}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -15,7 +14,7 @@ import {IS_WEB} from '#/env'
|
||||
|
||||
export function ActivitySubscriptionsNUX() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
@@ -28,9 +27,8 @@ export function ActivitySubscriptionsNUX() {
|
||||
return (
|
||||
<Dialog.Outer control={control} onClose={onClose}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Introducing activity notifications`)}
|
||||
label={l`Introducing activity notifications`}
|
||||
style={[web({maxWidth: 400})]}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
@@ -110,9 +108,7 @@ export function ActivitySubscriptionsNUX() {
|
||||
aspectRatio: 398 / 268,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg`A screenshot of a profile page with a bell icon next to the follow button, indicating the new activity notifications feature.`,
|
||||
)}
|
||||
alt={l`A screenshot of a profile page with a bell icon next to the follow button, indicating the new activity notifications feature.`}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -157,7 +153,7 @@ export function ActivitySubscriptionsNUX() {
|
||||
|
||||
{!IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -17,7 +16,7 @@ import {IS_WEB} from '#/env'
|
||||
|
||||
export function BookmarksAnnouncement() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
@@ -33,9 +32,8 @@ export function BookmarksAnnouncement() {
|
||||
onClose={onClose}
|
||||
nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Introducing saved posts AKA bookmarks`)}
|
||||
label={l`Introducing saved posts AKA bookmarks`}
|
||||
style={[web({maxWidth: 440})]}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
@@ -117,13 +115,11 @@ export function BookmarksAnnouncement() {
|
||||
aspectRatio: 333 / 104,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg({
|
||||
message: `A screenshot of a post with a new button next to the share button that allows you to save the post to your bookmarks. The post is from @jcsalterego.bsky.social and reads "inventing a saturday that immediately follows monday".`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
}),
|
||||
)}
|
||||
alt={l({
|
||||
message: `A screenshot of a post with a new button next to the share button that allows you to save the post to your bookmarks. The post is from @jcsalterego.bsky.social and reads "inventing a saturday that immediately follows monday".`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
})}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -162,7 +158,7 @@ export function BookmarksAnnouncement() {
|
||||
|
||||
{!IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={() => {
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -28,7 +27,7 @@ export const enabled = createIsEnabledCheck(props => {
|
||||
|
||||
export function DraftsAnnouncement() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
@@ -44,9 +43,8 @@ export function DraftsAnnouncement() {
|
||||
onClose={onClose}
|
||||
nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle fill={t.palette.primary_400} />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Introducing drafts`)}
|
||||
label={l`Introducing drafts`}
|
||||
style={[web({maxWidth: 440})]}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
@@ -94,13 +92,11 @@ export function DraftsAnnouncement() {
|
||||
aspectRatio: 393 / 226,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg({
|
||||
message: `A screenshot of the post composer with a new button next to the post button that says "Drafts", with a rainbow firework effect. Below, the text in the composer reads "Hey, did you hear the news? Bluesky has drafts now!!!".`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
}),
|
||||
)}
|
||||
alt={l({
|
||||
message: `A screenshot of the post composer with a new button next to the post button that says "Drafts", with a rainbow firework effect. Below, the text in the composer reads "Hey, did you hear the news? Bluesky has drafts now!!!".`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
})}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -137,7 +133,7 @@ export function DraftsAnnouncement() {
|
||||
|
||||
{!IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={() => control.close()}
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -34,7 +33,7 @@ export const enabled = createIsEnabledCheck(props => {
|
||||
|
||||
export function FindContactsAnnouncement() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
@@ -51,9 +50,8 @@ export function FindContactsAnnouncement() {
|
||||
onClose={onClose}
|
||||
nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Introducing finding friends via contacts`)}
|
||||
label={l`Introducing finding friends via contacts`}
|
||||
style={[web({maxWidth: 440})]}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
@@ -75,9 +73,7 @@ export function FindContactsAnnouncement() {
|
||||
accessibilityIgnoresInvertColors
|
||||
source={require('../../../../assets/images/find_friends_illustration.webp')}
|
||||
style={[a.w_full, {aspectRatio: 1278 / 661}]}
|
||||
alt={_(
|
||||
msg`An illustration depicting user avatars flowing from a contact book into the Bluesky app`,
|
||||
)}
|
||||
alt={l`An illustration depicting user avatars flowing from a contact book into the Bluesky app`}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -113,7 +109,7 @@ export function FindContactsAnnouncement() {
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={_(msg`Import Contacts`)}
|
||||
label={l`Import Contacts`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={() => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {urls} from '#/lib/constants'
|
||||
@@ -19,7 +18,7 @@ import {IS_NATIVE} from '#/env'
|
||||
|
||||
export function InitialVerificationAnnouncement() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
@@ -34,9 +33,8 @@ export function InitialVerificationAnnouncement() {
|
||||
return (
|
||||
<Dialog.Outer control={control} onClose={onClose}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Announcing verification on Bluesky`)}
|
||||
label={l`Announcing verification on Bluesky`}
|
||||
style={[
|
||||
gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
|
||||
]}>
|
||||
@@ -82,9 +80,7 @@ export function InitialVerificationAnnouncement() {
|
||||
aspectRatio: 353 / 160,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg`An illustration showing that Bluesky selects trusted verifiers, and trusted verifiers in turn verify individual user accounts.`,
|
||||
)}
|
||||
alt={l`An illustration showing that Bluesky selects trusted verifiers, and trusted verifiers in turn verify individual user accounts.`}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -117,9 +113,7 @@ export function InitialVerificationAnnouncement() {
|
||||
aspectRatio: 353 / 196,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg`An mockup of a iPhone showing the Bluesky app open to the profile of a verified user with a blue checkmark next to their display name.`,
|
||||
)}
|
||||
alt={l`An mockup of a iPhone showing the Bluesky app open to the profile of a verified user with a blue checkmark next to their display name.`}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -159,7 +153,7 @@ export function InitialVerificationAnnouncement() {
|
||||
<Link
|
||||
overridePresentation
|
||||
to={urls.website.blog.initialVerificationAnnouncement}
|
||||
label={_(msg`Read blog post`)}
|
||||
label={l`Read blog post`}
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
@@ -175,7 +169,7 @@ export function InitialVerificationAnnouncement() {
|
||||
</Link>
|
||||
{IS_NATIVE && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
|
||||
@@ -2,8 +2,7 @@ import {useCallback, useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, select, useTheme, utils, web} from '#/alf'
|
||||
@@ -31,7 +30,7 @@ export const enabled = createIsEnabledCheck(props => {
|
||||
|
||||
export function LiveNowBetaDialog() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
@@ -55,9 +54,8 @@ export function LiveNowBetaDialog() {
|
||||
onClose={onClose}
|
||||
nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle fill={t.palette.primary_700} />
|
||||
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Show when you’re live`)}
|
||||
label={l`Show when you’re live`}
|
||||
style={[web({maxWidth: 440})]}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
@@ -143,13 +141,11 @@ export function LiveNowBetaDialog() {
|
||||
aspectRatio: 652 / 211,
|
||||
},
|
||||
]}
|
||||
alt={_(
|
||||
msg({
|
||||
message: `A screenshot of a post from @esb.lol, showing the user is currently livestreaming content on Twitch. The post reads: "Hello! I'm live on Twitch, and I'm testing Bluesky's latest feature too!"`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
}),
|
||||
)}
|
||||
alt={l({
|
||||
message: `A screenshot of a post from @esb.lol, showing the user is currently livestreaming content on Twitch. The post reads: "Hello! I'm live on Twitch, and I'm testing Bluesky's latest feature too!"`,
|
||||
comment:
|
||||
'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.',
|
||||
})}
|
||||
useAppleWebpCodec
|
||||
/>
|
||||
</View>
|
||||
@@ -189,7 +185,7 @@ export function LiveNowBetaDialog() {
|
||||
|
||||
{!IS_WEB && (
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
size="large"
|
||||
color="primary"
|
||||
onPress={() => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {Fragment} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type ModerationCause} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {listUriToHref} from '#/lib/strings/url-helpers'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -19,23 +18,21 @@ export function BlockedByListDialog({
|
||||
control: DialogControlProps
|
||||
listBlocks: ModerationCause[]
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
<Prompt.Outer control={control} testID="blockedByListDialog">
|
||||
<Prompt.TitleText>{_(msg`User blocked by list`)}</Prompt.TitleText>
|
||||
<Prompt.TitleText>{l`User blocked by list`}</Prompt.TitleText>
|
||||
<View style={[a.gap_sm, a.pb_lg]}>
|
||||
<Text
|
||||
selectable
|
||||
style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}>
|
||||
{_(
|
||||
msg`This account is blocked by one or more of your moderation lists. To unblock, please visit the lists directly and remove this user.`,
|
||||
)}{' '}
|
||||
{l`This account is blocked by one or more of your moderation lists. To unblock, please visit the lists directly and remove this user.`}{' '}
|
||||
</Text>
|
||||
|
||||
<Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}>
|
||||
{_(msg`Lists blocking this user:`)}{' '}
|
||||
{l`Lists blocking this user:`}{' '}
|
||||
{listBlocks.map((block, i) =>
|
||||
block.source.type === 'list' ? (
|
||||
<Fragment key={block.source.list.uri}>
|
||||
@@ -52,7 +49,7 @@ export function BlockedByListDialog({
|
||||
</Text>
|
||||
</View>
|
||||
<Prompt.Actions>
|
||||
<Prompt.Action cta={_(msg`I understand`)} onPress={() => {}} />
|
||||
<Prompt.Action cta={l`I understand`} onPress={() => {}} />
|
||||
</Prompt.Actions>
|
||||
<Dialog.Close />
|
||||
</Prompt.Outer>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useState} from 'react'
|
||||
import {Modal, Pressable, View} from 'react-native'
|
||||
import {SafeAreaView} from 'react-native-safe-area-context'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -19,19 +18,18 @@ export function EmojiPopup({
|
||||
onEmojiSelected: (emoji: string) => void
|
||||
}) {
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Pressable
|
||||
accessibilityLabel={_(msg`Open full emoji list`)}
|
||||
accessibilityLabel={l`Open full emoji list`}
|
||||
accessibilityHint=""
|
||||
accessibilityRole="button"
|
||||
onPress={() => setModalVisible(true)}>
|
||||
{children}
|
||||
</Pressable>
|
||||
|
||||
<Modal
|
||||
animationType="slide"
|
||||
visible={modalVisible}
|
||||
@@ -56,7 +54,7 @@ export function EmojiPopup({
|
||||
<Trans>Add Reaction</Trans>
|
||||
</Text>
|
||||
<Button
|
||||
label={_(msg`Close`)}
|
||||
label={l`Close`}
|
||||
onPress={() => setModalVisible(false)}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useMemo, useState} from 'react'
|
||||
import {useWindowDimensions, View} from 'react-native'
|
||||
import {type ChatBskyConvoDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useSession} from '#/state/session'
|
||||
import {atoms as a, tokens, useTheme} from '#/alf'
|
||||
@@ -25,7 +24,7 @@ export function EmojiReactionPicker({
|
||||
children?: TriggerProps['children']
|
||||
onEmojiSelect: (emoji: string) => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const t = useTheme()
|
||||
const isFromSelf = message.sender?.did === currentAccount?.did
|
||||
@@ -77,7 +76,7 @@ export function EmojiReactionPicker({
|
||||
return (
|
||||
<ContextMenu.Item
|
||||
position={position}
|
||||
label={_(msg`React with ${emoji}`)}
|
||||
label={l`React with ${emoji}`}
|
||||
key={emoji}
|
||||
onPress={() => onEmojiSelect(emoji)}
|
||||
unstyled
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
@@ -22,7 +21,7 @@ export function MessageProfileButton({
|
||||
}: {
|
||||
profile: AppBskyActorDefs.ProfileViewDetailed
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
@@ -35,7 +34,7 @@ export function MessageProfileButton({
|
||||
navigation.navigate('MessagesConversation', {conversation: convo.id})
|
||||
},
|
||||
onError: () => {
|
||||
Toast.show(_(msg`Failed to create conversation`))
|
||||
Toast.show(l`Failed to create conversation`)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -96,7 +95,7 @@ export function MessageProfileButton({
|
||||
color="secondary"
|
||||
variant="solid"
|
||||
shape="round"
|
||||
label={_(msg`Message ${profile.handle}`)}
|
||||
label={l`Message ${profile.handle}`}
|
||||
style={[a.justify_center]}
|
||||
onPress={wrappedOnPress}>
|
||||
<ButtonIcon icon={Message} size="md" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {useCallback, useImperativeHandle, useState} from 'react'
|
||||
import {Keyboard} from 'react-native'
|
||||
import DatePicker from 'react-native-date-picker'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useTheme} from '#/alf'
|
||||
import {type DateFieldProps} from '#/components/forms/DateField/types'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, native, useTheme, web} from '#/alf'
|
||||
import * as TextField from '#/components/forms/TextField'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {useCallback, useImperativeHandle, useState} from 'react'
|
||||
import {Keyboard, View} from 'react-native'
|
||||
import DatePicker from 'react-native-date-picker'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -37,7 +36,7 @@ export function DateField({
|
||||
maximumDate,
|
||||
minimumDate,
|
||||
}: DateFieldProps) {
|
||||
const {_, i18n} = useLingui()
|
||||
const {t: l, i18n} = useLingui()
|
||||
const t = useTheme()
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
@@ -125,7 +124,7 @@ export function DateField({
|
||||
/>
|
||||
</View>
|
||||
<Button
|
||||
label={_(msg`Done`)}
|
||||
label={l`Done`}
|
||||
onPress={() => {
|
||||
/*
|
||||
* Commit the currently shown date even if the user never
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {Keyboard, View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {toNiceDomain} from '#/lib/strings/url-helpers'
|
||||
@@ -26,7 +25,7 @@ export function HostingProvider({
|
||||
}) {
|
||||
const serverInputControl = useDialogControl()
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const onPressSelectService = useCallback(() => {
|
||||
Keyboard.dismiss()
|
||||
@@ -47,7 +46,7 @@ export function HostingProvider({
|
||||
</Text>
|
||||
<Button
|
||||
label={toNiceDomain(serviceUrl)}
|
||||
accessibilityHint={_(msg`Changes hosting provider`)}
|
||||
accessibilityHint={l`Changes hosting provider`}
|
||||
onPress={onPressSelectService}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
@@ -67,7 +66,7 @@ export function HostingProvider({
|
||||
<Button
|
||||
testID="selectServiceButton"
|
||||
label={toNiceDomain(serviceUrl)}
|
||||
accessibilityHint={_(msg`Changes hosting provider`)}
|
||||
accessibilityHint={l`Changes hosting provider`}
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
style={[
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user