Use title case for Starter Pack (#11653)
This commit is contained in:
@@ -296,19 +296,6 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/components/StarterPack/Main/ProfilesList.tsx": {
|
|
||||||
"typescript/no-misused-promises": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/components/StarterPack/ProfileStarterPacks.tsx": {
|
|
||||||
"typescript/no-explicit-any": {
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
"typescript/no-misused-promises": {
|
|
||||||
"count": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/components/StarterPack/QrCodeDialog.tsx": {
|
"src/components/StarterPack/QrCodeDialog.tsx": {
|
||||||
"typescript/no-floating-promises": {
|
"typescript/no-floating-promises": {
|
||||||
"count": 5
|
"count": 5
|
||||||
@@ -398,21 +385,11 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/components/dialogs/StarterPackDialog.tsx": {
|
|
||||||
"typescript/no-misused-promises": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/components/dialogs/SwitchAccount.tsx": {
|
"src/components/dialogs/SwitchAccount.tsx": {
|
||||||
"typescript/no-floating-promises": {
|
"typescript/no-floating-promises": {
|
||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/components/dialogs/lists/CreateListFromStarterPackDialog.tsx": {
|
|
||||||
"typescript/no-floating-promises": {
|
|
||||||
"count": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/components/dialogs/lists/CreateOrEditListDialog.tsx": {
|
"src/components/dialogs/lists/CreateOrEditListDialog.tsx": {
|
||||||
"typescript/no-explicit-any": {
|
"typescript/no-explicit-any": {
|
||||||
"count": 2
|
"count": 2
|
||||||
@@ -857,14 +834,6 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/screens/ProfileList/components/MoreOptionsMenu.tsx": {
|
|
||||||
"typescript/no-floating-promises": {
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
"typescript/no-misused-promises": {
|
|
||||||
"count": 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/screens/ProfileList/components/SubscribeMenu.tsx": {
|
"src/screens/ProfileList/components/SubscribeMenu.tsx": {
|
||||||
"typescript/no-misused-promises": {
|
"typescript/no-misused-promises": {
|
||||||
"count": 2
|
"count": 2
|
||||||
@@ -996,22 +965,6 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/screens/StarterPack/StarterPackScreen.tsx": {
|
|
||||||
"typescript/no-floating-promises": {
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
"typescript/require-await": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/screens/StarterPack/Wizard/index.tsx": {
|
|
||||||
"typescript/no-floating-promises": {
|
|
||||||
"count": 2
|
|
||||||
},
|
|
||||||
"typescript/require-await": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/state/a11y.tsx": {
|
"src/state/a11y.tsx": {
|
||||||
"typescript/no-floating-promises": {
|
"typescript/no-floating-promises": {
|
||||||
"count": 1
|
"count": 1
|
||||||
@@ -1233,11 +1186,6 @@
|
|||||||
"count": 2
|
"count": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/state/queries/starter-packs.ts": {
|
|
||||||
"typescript/require-await": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/state/queries/suggested-follows.ts": {
|
"src/state/queries/suggested-follows.ts": {
|
||||||
"no-unused-vars": {
|
"no-unused-vars": {
|
||||||
"count": 1
|
"count": 1
|
||||||
|
|||||||
+2
-2
@@ -563,12 +563,12 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="StarterPackWizard"
|
name="StarterPackWizard"
|
||||||
getComponent={() => Wizard}
|
getComponent={() => Wizard}
|
||||||
options={{title: title(msg`Create a starter pack`), requireAuth: true}}
|
options={{title: title(msg`Create a Starter Pack`), requireAuth: true}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="StarterPackEdit"
|
name="StarterPackEdit"
|
||||||
getComponent={() => Wizard}
|
getComponent={() => Wizard}
|
||||||
options={{title: title(msg`Edit your starter pack`), requireAuth: true}}
|
options={{title: title(msg`Edit your Starter Pack`), requireAuth: true}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="VideoFeed"
|
name="VideoFeed"
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ function DialogInner({
|
|||||||
if (isMe) {
|
if (isMe) {
|
||||||
if (profile.joinedViaStarterPack) {
|
if (profile.joinedViaStarterPack) {
|
||||||
return _(
|
return _(
|
||||||
msg`You joined Bluesky using a starter pack ${timeAgoString} ago`,
|
msg`You joined Bluesky using a Starter Pack ${timeAgoString} ago`,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return _(msg`You joined Bluesky ${timeAgoString} ago`)
|
return _(msg`You joined Bluesky ${timeAgoString} ago`)
|
||||||
@@ -110,7 +110,7 @@ function DialogInner({
|
|||||||
} else {
|
} else {
|
||||||
if (profile.joinedViaStarterPack) {
|
if (profile.joinedViaStarterPack) {
|
||||||
return _(
|
return _(
|
||||||
msg`${profileName} joined Bluesky using a starter pack ${timeAgoString} ago`,
|
msg`${profileName} joined Bluesky using a Starter Pack ${timeAgoString} ago`,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return _(msg`${profileName} joined Bluesky ${timeAgoString} ago`)
|
return _(msg`${profileName} joined Bluesky ${timeAgoString} ago`)
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import {forwardRef, useCallback, useImperativeHandle, useState} from 'react'
|
|||||||
import {type ListRenderItemInfo, View} from 'react-native'
|
import {type ListRenderItemInfo, View} from 'react-native'
|
||||||
import {AtUri} from '@atproto/syntax'
|
import {AtUri} from '@atproto/syntax'
|
||||||
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
|
|
||||||
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
||||||
@@ -107,6 +106,12 @@ export const ProfilesList = forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onRefresh = async () => {
|
||||||
|
setIsPTRing(true)
|
||||||
|
await refetch()
|
||||||
|
setIsPTRing(false)
|
||||||
|
}
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@@ -140,11 +145,7 @@ export const ProfilesList = forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
desktopFixedHeight
|
desktopFixedHeight
|
||||||
initialNumToRender={initialNumToRender}
|
initialNumToRender={initialNumToRender}
|
||||||
refreshing={isPTRing}
|
refreshing={isPTRing}
|
||||||
onRefresh={async () => {
|
onRefresh={() => void onRefresh()}
|
||||||
setIsPTRing(true)
|
|
||||||
await refetch()
|
|
||||||
setIsPTRing(false)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -159,14 +160,14 @@ function OptedOutControls({
|
|||||||
listUri: string
|
listUri: string
|
||||||
canRemove: boolean
|
canRemove: boolean
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const [isRemoved, setIsRemoved] = useState(false)
|
const [isRemoved, setIsRemoved] = useState(false)
|
||||||
const {mutate: removeMembership, isPending} = useListMembershipRemoveMutation(
|
const {mutate: removeMembership, isPending} = useListMembershipRemoveMutation(
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setIsRemoved(true)
|
setIsRemoved(true)
|
||||||
Toast.show(_(msg`Removed from starter pack`))
|
Toast.show(l`Removed from Starter Pack`)
|
||||||
},
|
},
|
||||||
onError: error =>
|
onError: error =>
|
||||||
Toast.show(cleanError(error), {
|
Toast.show(cleanError(error), {
|
||||||
@@ -183,12 +184,12 @@ function OptedOutControls({
|
|||||||
<Admonition.Icon />
|
<Admonition.Icon />
|
||||||
<Admonition.Content>
|
<Admonition.Content>
|
||||||
<Admonition.Text>
|
<Admonition.Text>
|
||||||
<Trans>Opted out of this starter pack</Trans>
|
<Trans>Opted out of this Starter Pack</Trans>
|
||||||
</Admonition.Text>
|
</Admonition.Text>
|
||||||
</Admonition.Content>
|
</Admonition.Content>
|
||||||
{canRemove ? (
|
{canRemove ? (
|
||||||
<Admonition.Button
|
<Admonition.Button
|
||||||
label={_(msg`Remove user from starter pack`)}
|
label={l`Remove user from Starter Pack`}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
type ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {useGenerateStarterPackMutation} from '#/lib/generate-starterpack'
|
import {useGenerateStarterPackMutation} from '#/lib/generate-starterpack'
|
||||||
@@ -54,7 +52,7 @@ interface ProfileFeedgensProps {
|
|||||||
isMe: boolean
|
isMe: boolean
|
||||||
emptyStateMessage?: string
|
emptyStateMessage?: string
|
||||||
emptyStateButton?: EmptyStateButtonProps
|
emptyStateButton?: EmptyStateButtonProps
|
||||||
emptyStateIcon?: React.ComponentType<any> | React.ReactElement
|
emptyStateIcon?: React.ComponentType | React.ReactElement
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyExtractor(item: app.bsky.graph.defs.StarterPackViewBasic) {
|
function keyExtractor(item: app.bsky.graph.defs.StarterPackViewBasic) {
|
||||||
@@ -90,7 +88,7 @@ export function ProfileStarterPacks({
|
|||||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
const items = data?.pages.flatMap(page => page.starterPacks)
|
const items = data?.pages.flatMap(page => page.starterPacks)
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
const EmptyComponent = useCallback(() => {
|
const EmptyComponent = useCallback(() => {
|
||||||
if (emptyStateMessage || emptyStateButton || emptyStateIcon) {
|
if (emptyStateMessage || emptyStateButton || emptyStateIcon) {
|
||||||
@@ -101,9 +99,7 @@ export function ProfileStarterPacks({
|
|||||||
iconSize="3xl"
|
iconSize="3xl"
|
||||||
message={
|
message={
|
||||||
emptyStateMessage ??
|
emptyStateMessage ??
|
||||||
_(
|
l`Starter Packs let you share your favorite feeds and people with your friends.`
|
||||||
msg`Starter packs let you share your favorite feeds and people with your friends.`,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
button={emptyStateButton}
|
button={emptyStateButton}
|
||||||
/>
|
/>
|
||||||
@@ -111,7 +107,7 @@ export function ProfileStarterPacks({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return <Empty />
|
return <Empty />
|
||||||
}, [_, emptyStateMessage, emptyStateButton, emptyStateIcon])
|
}, [l, emptyStateMessage, emptyStateButton, emptyStateIcon])
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
scrollToTop: () => {},
|
scrollToTop: () => {},
|
||||||
@@ -122,7 +118,7 @@ export function ProfileStarterPacks({
|
|||||||
try {
|
try {
|
||||||
await refetch()
|
await refetch()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to refresh starter packs', {message: err})
|
logger.error('Failed to refresh Starter Packs', {message: err})
|
||||||
}
|
}
|
||||||
setIsPTRing(false)
|
setIsPTRing(false)
|
||||||
}, [refetch, setIsPTRing])
|
}, [refetch, setIsPTRing])
|
||||||
@@ -132,7 +128,7 @@ export function ProfileStarterPacks({
|
|||||||
try {
|
try {
|
||||||
await fetchNextPage()
|
await fetchNextPage()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to load more starter packs', {message: err})
|
logger.error('Failed to load more Starter Packs', {message: err})
|
||||||
}
|
}
|
||||||
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
|
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
|
||||||
|
|
||||||
@@ -179,8 +175,8 @@ export function ProfileStarterPacks({
|
|||||||
}}
|
}}
|
||||||
removeClippedSubviews={true}
|
removeClippedSubviews={true}
|
||||||
desktopFixedHeight
|
desktopFixedHeight
|
||||||
onEndReached={onEndReached}
|
onEndReached={() => void onEndReached()}
|
||||||
onRefresh={onRefresh}
|
onRefresh={() => void onRefresh()}
|
||||||
ListEmptyComponent={
|
ListEmptyComponent={
|
||||||
data ? (isMe ? EmptyComponent : undefined) : FeedLoadingPlaceholder
|
data ? (isMe ? EmptyComponent : undefined) : FeedLoadingPlaceholder
|
||||||
}
|
}
|
||||||
@@ -193,7 +189,7 @@ export function ProfileStarterPacks({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CreateAnother() {
|
function CreateAnother() {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
@@ -207,7 +203,7 @@ function CreateAnother() {
|
|||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
]}>
|
]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create a starter pack`)}
|
label={l`Create a Starter Pack`}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -223,7 +219,7 @@ function CreateAnother() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Empty() {
|
function Empty() {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const confirmDialogControl = useDialogControl()
|
const confirmDialogControl = useDialogControl()
|
||||||
const followersDialogControl = useDialogControl()
|
const followersDialogControl = useDialogControl()
|
||||||
@@ -244,7 +240,7 @@ function Empty() {
|
|||||||
setIsGenerating(false)
|
setIsGenerating(false)
|
||||||
},
|
},
|
||||||
onError: e => {
|
onError: e => {
|
||||||
logger.error('Failed to generate starter pack', {safeMessage: e})
|
logger.error('Failed to generate Starter Pack', {safeMessage: e})
|
||||||
setIsGenerating(false)
|
setIsGenerating(false)
|
||||||
if (e.message.includes('NOT_ENOUGH_FOLLOWERS')) {
|
if (e.message.includes('NOT_ENOUGH_FOLLOWERS')) {
|
||||||
followersDialogControl.open()
|
followersDialogControl.open()
|
||||||
@@ -265,7 +261,7 @@ function Empty() {
|
|||||||
const wrappedOpenConfirmDialog = requireEmailVerification(openConfirmDialog, {
|
const wrappedOpenConfirmDialog = requireEmailVerification(openConfirmDialog, {
|
||||||
instructions: [
|
instructions: [
|
||||||
<Trans key="confirm">
|
<Trans key="confirm">
|
||||||
Before creating a starter pack, you must first verify your email.
|
Before creating a Starter Pack, you must first verify your email.
|
||||||
</Trans>,
|
</Trans>,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -275,7 +271,7 @@ function Empty() {
|
|||||||
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
||||||
instructions: [
|
instructions: [
|
||||||
<Trans key="nav">
|
<Trans key="nav">
|
||||||
Before creating a starter pack, you must first verify your email.
|
Before creating a Starter Pack, you must first verify your email.
|
||||||
</Trans>,
|
</Trans>,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -292,18 +288,18 @@ function Empty() {
|
|||||||
]}>
|
]}>
|
||||||
<View style={[a.gap_xs]}>
|
<View style={[a.gap_xs]}>
|
||||||
<Text style={[a.font_semi_bold, a.text_lg, {color: 'white'}]}>
|
<Text style={[a.font_semi_bold, a.text_lg, {color: 'white'}]}>
|
||||||
<Trans>You haven't created a starter pack yet!</Trans>
|
<Trans>You haven't created a Starter Pack yet!</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[a.text_md, {color: 'white'}]}>
|
<Text style={[a.text_md, {color: 'white'}]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
Starter packs let you easily share your favorite feeds and people
|
Starter Packs let you easily share your favorite feeds and people
|
||||||
with your friends.
|
with your friends.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[a.flex_row, a.gap_md, {marginLeft: 'auto'}]}>
|
<View style={[a.flex_row, a.gap_md, {marginLeft: 'auto'}]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create a starter pack for me`)}
|
label={l`Create a Starter Pack for me`}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -316,7 +312,7 @@ function Empty() {
|
|||||||
{isGenerating && <Loader size="md" />}
|
{isGenerating && <Loader size="md" />}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create a starter pack`)}
|
label={l`Create a Starter Pack`}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -333,11 +329,10 @@ function Empty() {
|
|||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Prompt.Outer control={confirmDialogControl}>
|
<Prompt.Outer control={confirmDialogControl}>
|
||||||
<Prompt.Content>
|
<Prompt.Content>
|
||||||
<Prompt.TitleText>
|
<Prompt.TitleText>
|
||||||
<Trans>Generate a starter pack</Trans>
|
<Trans>Generate a Starter Pack</Trans>
|
||||||
</Prompt.TitleText>
|
</Prompt.TitleText>
|
||||||
<Prompt.DescriptionText>
|
<Prompt.DescriptionText>
|
||||||
<Trans>
|
<Trans>
|
||||||
@@ -349,12 +344,12 @@ function Empty() {
|
|||||||
<Prompt.Actions>
|
<Prompt.Actions>
|
||||||
<Prompt.Action
|
<Prompt.Action
|
||||||
color="primary"
|
color="primary"
|
||||||
cta={_(msg`Choose for me`)}
|
cta={l`Choose for me`}
|
||||||
onPress={generate}
|
onPress={generate}
|
||||||
/>
|
/>
|
||||||
<Prompt.Action
|
<Prompt.Action
|
||||||
color="secondary"
|
color="secondary"
|
||||||
cta={_(msg`Let me choose`)}
|
cta={l`Let me choose`}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigation.navigate('StarterPackWizard', {})
|
navigation.navigate('StarterPackWizard', {})
|
||||||
}}
|
}}
|
||||||
@@ -363,21 +358,17 @@ function Empty() {
|
|||||||
</Prompt.Outer>
|
</Prompt.Outer>
|
||||||
<Prompt.Basic
|
<Prompt.Basic
|
||||||
control={followersDialogControl}
|
control={followersDialogControl}
|
||||||
title={_(msg`Oops!`)}
|
title={l`Oops!`}
|
||||||
description={_(
|
description={l`You must be following at least seven other people to generate a Starter Pack.`}
|
||||||
msg`You must be following at least seven other people to generate a starter pack.`,
|
|
||||||
)}
|
|
||||||
onConfirm={() => {}}
|
onConfirm={() => {}}
|
||||||
showCancel={false}
|
showCancel={false}
|
||||||
/>
|
/>
|
||||||
<Prompt.Basic
|
<Prompt.Basic
|
||||||
control={errorDialogControl}
|
control={errorDialogControl}
|
||||||
title={_(msg`Oops!`)}
|
title={l`Oops!`}
|
||||||
description={_(
|
description={l`An error occurred while generating your Starter Pack. Want to try again?`}
|
||||||
msg`An error occurred while generating your starter pack. Want to try again?`,
|
|
||||||
)}
|
|
||||||
onConfirm={generate}
|
onConfirm={generate}
|
||||||
confirmButtonCta={_(msg`Retry`)}
|
confirmButtonCta={l`Retry`}
|
||||||
/>
|
/>
|
||||||
</LinearGradientBackground>
|
</LinearGradientBackground>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ export function QrCodeDialog({
|
|||||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Create a QR code for a starter pack`)}>
|
label={_(msg`Create a QR code for a Starter Pack`)}>
|
||||||
<View style={[a.flex_1, a.align_center, a.gap_5xl]}>
|
<View style={[a.flex_1, a.align_center, a.gap_5xl]}>
|
||||||
<Suspense fallback={<Loading />}>
|
<Suspense fallback={<Loading />}>
|
||||||
{!link ? (
|
{!link ? (
|
||||||
|
|||||||
@@ -81,11 +81,11 @@ function ShareDialogInner({
|
|||||||
<View style={[!gtMobile && a.gap_lg]}>
|
<View style={[!gtMobile && a.gap_lg]}>
|
||||||
<View style={[a.gap_sm, gtMobile && a.pb_lg]}>
|
<View style={[a.gap_sm, gtMobile && a.pb_lg]}>
|
||||||
<Text style={[a.font_semi_bold, a.text_2xl]}>
|
<Text style={[a.font_semi_bold, a.text_2xl]}>
|
||||||
<Trans>Invite people to this starter pack!</Trans>
|
<Trans>Invite people to this Starter Pack!</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
<Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
Share this starter pack and help people join your community on
|
Share this Starter Pack and help people join your community on
|
||||||
Bluesky.
|
Bluesky.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import {useMemo} from 'react'
|
|||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {AtUri} from '@atproto/syntax'
|
import {AtUri} from '@atproto/syntax'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
@@ -59,7 +57,7 @@ export function Card({
|
|||||||
}) {
|
}) {
|
||||||
const {record, creator, joinedAllTimeCount} = starterPack
|
const {record, creator, joinedAllTimeCount} = starterPack
|
||||||
|
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const isOwnStarterPack = creator?.did === currentAccount?.did
|
const isOwnStarterPack = creator?.did === currentAccount?.did
|
||||||
@@ -84,8 +82,8 @@ export function Card({
|
|||||||
style={[a.leading_snug, t.atoms.text_contrast_medium]}
|
style={[a.leading_snug, t.atoms.text_contrast_medium]}
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{isOwnStarterPack
|
{isOwnStarterPack
|
||||||
? _(msg`Starter pack by you`)
|
? l`Starter Pack by you`
|
||||||
: _(msg`Starter pack by ${sanitizeHandle(creator.handle, '@')}`)}
|
: l`Starter Pack by ${sanitizeHandle(creator.handle, '@')}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -96,7 +94,7 @@ export function Card({
|
|||||||
) : null}
|
) : null}
|
||||||
{!!joinedAllTimeCount && joinedAllTimeCount >= 50 && (
|
{!!joinedAllTimeCount && joinedAllTimeCount >= 50 && (
|
||||||
<Text style={[a.font_semi_bold, t.atoms.text_contrast_medium]}>
|
<Text style={[a.font_semi_bold, t.atoms.text_contrast_medium]}>
|
||||||
<Trans comment="Number of users (always at least 50) who have joined Bluesky using a specific starter pack">
|
<Trans comment="Number of users (always at least 50) who have joined Bluesky using a specific Starter Pack">
|
||||||
<Plural value={joinedAllTimeCount} other="# users have" /> joined!
|
<Plural value={joinedAllTimeCount} other="# users have" /> joined!
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
@@ -110,7 +108,7 @@ export function useStarterPackLink({
|
|||||||
}: {
|
}: {
|
||||||
view: bsky.starterPack.AnyStarterPackView
|
view: bsky.starterPack.AnyStarterPackView
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const qc = useQueryClient()
|
const qc = useQueryClient()
|
||||||
const {rkey, handleOrDid} = useMemo(() => {
|
const {rkey, handleOrDid} = useMemo(() => {
|
||||||
const rkey = new AtUri(view.uri).rkey
|
const rkey = new AtUri(view.uri).rkey
|
||||||
@@ -125,8 +123,8 @@ export function useStarterPackLink({
|
|||||||
return {
|
return {
|
||||||
to: `/starter-pack/${handleOrDid}/${rkey}`,
|
to: `/starter-pack/${handleOrDid}/${rkey}`,
|
||||||
label: bsky.isType(app.bsky.graph.starterpack, view.record)
|
label: bsky.isType(app.bsky.graph.starterpack, view.record)
|
||||||
? _(msg`Navigate to ${view.record.name}`)
|
? l`Navigate to ${view.record.name}`
|
||||||
: _(msg`Navigate to starter pack`),
|
: l`Navigate to Starter Pack`,
|
||||||
precache,
|
precache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +137,7 @@ export function Link({
|
|||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
children: BaseLinkProps['children']
|
children: BaseLinkProps['children']
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const {record} = starterPack
|
const {record} = starterPack
|
||||||
const {rkey, handleOrDid} = useMemo(() => {
|
const {rkey, handleOrDid} = useMemo(() => {
|
||||||
@@ -155,7 +153,7 @@ export function Link({
|
|||||||
return (
|
return (
|
||||||
<BaseLink
|
<BaseLink
|
||||||
to={`/starter-pack/${handleOrDid}/${rkey}`}
|
to={`/starter-pack/${handleOrDid}/${rkey}`}
|
||||||
label={_(msg`Navigate to ${record.name}`)}
|
label={l`Navigate to ${record.name}`}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
precacheResolvedUri(
|
precacheResolvedUri(
|
||||||
queryClient,
|
queryClient,
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import {
|
|||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
type ModerationUI,
|
type ModerationUI,
|
||||||
} from '@bsky/sdk/moderation'
|
} from '@bsky/sdk/moderation'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
|
|
||||||
import {DISCOVER_FEED_URI, STARTER_PACK_MAX_SIZE} from '#/lib/constants'
|
import {DISCOVER_FEED_URI, STARTER_PACK_MAX_SIZE} from '#/lib/constants'
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
@@ -53,15 +51,15 @@ function WizardListCard({
|
|||||||
moderationUi: ModerationUI
|
moderationUi: ModerationUI
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toggle.Item
|
<Toggle.Item
|
||||||
name={type === 'user' ? _(msg`Person toggle`) : _(msg`Feed toggle`)}
|
name={type === 'user' ? l`Person toggle` : l`Feed toggle`}
|
||||||
label={
|
label={
|
||||||
included
|
included
|
||||||
? _(msg`Remove ${displayName} from starter pack`)
|
? l`Remove ${displayName} from Starter Pack`
|
||||||
: _(msg`Add ${displayName} to starter pack`)
|
: l`Add ${displayName} to Starter Pack`
|
||||||
}
|
}
|
||||||
value={included}
|
value={included}
|
||||||
disabled={btnType === 'remove' || disabled}
|
disabled={btnType === 'remove' || disabled}
|
||||||
@@ -109,7 +107,7 @@ function WizardListCard({
|
|||||||
<Checkbox />
|
<Checkbox />
|
||||||
) : !disabled ? (
|
) : !disabled ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Remove`)}
|
label={l`Remove`}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -142,7 +140,7 @@ export function WizardProfileCard({
|
|||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
// Determine the "main" profile for this starter pack - either targetDid or current account
|
// Determine the "main" profile for this Starter Pack - either targetDid or current account
|
||||||
const targetProfileDid = state.targetDid || currentAccount?.did
|
const targetProfileDid = state.targetDid || currentAccount?.did
|
||||||
const isTarget = profile.did === targetProfileDid
|
const isTarget = profile.did === targetProfileDid
|
||||||
const included = isTarget || state.profiles.some(p => p.did === profile.did)
|
const included = isTarget || state.profiles.some(p => p.did === profile.did)
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export function useTopic(
|
|||||||
} else if (link.startsWith('/starter-pack')) {
|
} else if (link.startsWith('/starter-pack')) {
|
||||||
return {
|
return {
|
||||||
type: 'starter-pack',
|
type: 'starter-pack',
|
||||||
label: l`Browse starter pack ${displayName}`,
|
label: l`Browse Starter Pack ${displayName}`,
|
||||||
displayName,
|
displayName,
|
||||||
uri: undefined,
|
uri: undefined,
|
||||||
url: link,
|
url: link,
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
|
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
|
||||||
@@ -67,7 +65,7 @@ export function StarterPackDialog({
|
|||||||
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
||||||
instructions: [
|
instructions: [
|
||||||
<Trans key="nav">
|
<Trans key="nav">
|
||||||
Before creating a starter pack, you must first verify your email.
|
Before creating a Starter Pack, you must first verify your email.
|
||||||
</Trans>,
|
</Trans>,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -85,7 +83,7 @@ export function StarterPackDialog({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -96,18 +94,17 @@ function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
|||||||
fill={t.atoms.border_contrast_medium.borderColor}
|
fill={t.atoms.border_contrast_medium.borderColor}
|
||||||
/>
|
/>
|
||||||
<Text style={[a.text_center]}>
|
<Text style={[a.text_center]}>
|
||||||
<Trans>You have no starter packs.</Trans>
|
<Trans>You have no Starter Packs.</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={[a.align_center]}>
|
<View style={[a.align_center]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create starter pack`)}
|
label={l`Create Starter Pack`}
|
||||||
color="secondary_inverted"
|
color="secondary_inverted"
|
||||||
size="small"
|
size="small"
|
||||||
onPress={onStartWizard}>
|
onPress={onStartWizard}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans comment="Text on button to create a new starter pack">
|
<Trans comment="Text on button to create a new Starter Pack">
|
||||||
Create
|
Create
|
||||||
</Trans>
|
</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
@@ -128,7 +125,7 @@ function StarterPackList({
|
|||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
}) {
|
}) {
|
||||||
const control = Dialog.useDialogContext()
|
const control = Dialog.useDialogContext()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const {data: subject} = useProfileQuery({did: targetDid})
|
const {data: subject} = useProfileQuery({did: targetDid})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -178,10 +175,10 @@ function StarterPackList({
|
|||||||
native(a.pt_lg),
|
native(a.pt_lg),
|
||||||
]}>
|
]}>
|
||||||
<Text style={[a.text_lg, a.font_semi_bold]}>
|
<Text style={[a.text_lg, a.font_semi_bold]}>
|
||||||
<Trans>Add to starter packs</Trans>
|
<Trans>Add to Starter Packs</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={l`Close`}
|
||||||
onPress={onClose}
|
onPress={onClose}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -196,15 +193,15 @@ function StarterPackList({
|
|||||||
<View
|
<View
|
||||||
style={[a.flex_row, a.justify_between, a.align_center, a.py_md]}>
|
style={[a.flex_row, a.justify_between, a.align_center, a.py_md]}>
|
||||||
<Text style={[a.text_md, a.font_semi_bold]}>
|
<Text style={[a.text_md, a.font_semi_bold]}>
|
||||||
<Trans>New starter pack</Trans>
|
<Trans>New Starter Pack</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create starter pack`)}
|
label={l`Create Starter Pack`}
|
||||||
color="secondary_inverted"
|
color="secondary_inverted"
|
||||||
size="small"
|
size="small"
|
||||||
onPress={onStartWizard}>
|
onPress={onStartWizard}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans comment="Text on button to create a new starter pack">
|
<Trans comment="Text on button to create a new Starter Pack">
|
||||||
Create
|
Create
|
||||||
</Trans>
|
</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
@@ -234,7 +231,7 @@ function StarterPackList({
|
|||||||
? () => 'starter_pack_dialog_loader'
|
? () => 'starter_pack_dialog_loader'
|
||||||
: (item: StarterPackWithMembership) => item.starterPack.uri
|
: (item: StarterPackWithMembership) => item.starterPack.uri
|
||||||
}
|
}
|
||||||
onEndReached={onEndReached}
|
onEndReached={() => void onEndReached()}
|
||||||
onEndReachedThreshold={0.1}
|
onEndReachedThreshold={0.1}
|
||||||
ListHeaderComponent={listHeader}
|
ListHeaderComponent={listHeader}
|
||||||
ListEmptyComponent={<Empty onStartWizard={onStartWizard} />}
|
ListEmptyComponent={<Empty onStartWizard={onStartWizard} />}
|
||||||
@@ -257,7 +254,7 @@ function StarterPackItem({
|
|||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const isSelf = subject?.did === currentAccount?.did
|
const isSelf = subject?.did === currentAccount?.did
|
||||||
|
|
||||||
@@ -268,26 +265,26 @@ function StarterPackItem({
|
|||||||
useListMembershipAddMutation({
|
useListMembershipAddMutation({
|
||||||
subject,
|
subject,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Toast.show(_(msg`Added to starter pack`))
|
Toast.show(l`Added to Starter Pack`)
|
||||||
},
|
},
|
||||||
onError: err => {
|
onError: err => {
|
||||||
if (!isNetworkError(err)) {
|
if (!isNetworkError(err)) {
|
||||||
logger.error('Failed to add to starter pack', {safeMessage: 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} =
|
const {mutate: removeMembership, isPending: isPendingRemove} =
|
||||||
useListMembershipRemoveMutation({
|
useListMembershipRemoveMutation({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Toast.show(_(msg`Removed from starter pack`))
|
Toast.show(l`Removed from Starter Pack`)
|
||||||
},
|
},
|
||||||
onError: err => {
|
onError: err => {
|
||||||
if (!isNetworkError(err)) {
|
if (!isNetworkError(err)) {
|
||||||
logger.error('Failed to remove from starter pack', {safeMessage: 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'})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -363,9 +360,8 @@ function StarterPackItem({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
label={isInPack ? _(msg`Remove`) : _(msg`Add`)}
|
label={isInPack ? l`Remove` : l`Add`}
|
||||||
color={isInPack ? 'secondary' : 'primary_subtle'}
|
color={isInPack ? 'secondary' : 'primary_subtle'}
|
||||||
size="tiny"
|
size="tiny"
|
||||||
disabled={isPending || isSelf}
|
disabled={isPending || isSelf}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import {View} from 'react-native'
|
|||||||
import {TID} from '@atproto/common-web'
|
import {TID} from '@atproto/common-web'
|
||||||
import {type $Typed} from '@atproto/lex'
|
import {type $Typed} from '@atproto/lex'
|
||||||
import {AtUri, type AtUriString, toDatetimeString} from '@atproto/syntax'
|
import {AtUri, type AtUriString, toDatetimeString} from '@atproto/syntax'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
@@ -33,7 +32,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
starterPack: app.bsky.graph.defs.StarterPackView
|
starterPack: app.bsky.graph.defs.StarterPackView
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const appviewClient = useAppviewClient()
|
const appviewClient = useAppviewClient()
|
||||||
const pdsClient = usePdsClient()
|
const pdsClient = usePdsClient()
|
||||||
@@ -115,7 +114,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
})(),
|
})(),
|
||||||
)
|
)
|
||||||
|
|
||||||
queryClient.invalidateQueries({queryKey: ['list-members', listUri]})
|
void queryClient.invalidateQueries({queryKey: ['list-members', listUri]})
|
||||||
|
|
||||||
ax.metric('starterPack:convertToList', {
|
ax.metric('starterPack:convertToList', {
|
||||||
starterPack: starterPack.uri,
|
starterPack: starterPack.uri,
|
||||||
@@ -123,7 +122,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to add members to list', {safeMessage: 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',
|
type: 'error',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -133,7 +132,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
|
|
||||||
const onListCreated = (listUri: string) => {
|
const onListCreated = (listUri: string) => {
|
||||||
loadingDialogControl.open()
|
loadingDialogControl.open()
|
||||||
addMembersAndNavigate(listUri)
|
void addMembersAndNavigate(listUri)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -144,24 +143,24 @@ export function CreateListFromStarterPackDialog({
|
|||||||
nativeOptions={{preventExpansion: true}}>
|
nativeOptions={{preventExpansion: true}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Create list from starter pack`)}
|
label={l`Create list from Starter Pack`}
|
||||||
style={web({maxWidth: 400})}>
|
style={web({maxWidth: 400})}>
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
<Text style={[a.text_xl, a.font_bold]}>
|
<Text style={[a.text_xl, a.font_bold]}>
|
||||||
<Trans>Create list from starter pack</Trans>
|
<Trans>Create list from Starter Pack</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text
|
<Text
|
||||||
style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}>
|
style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
This will create a new list with the same name, description, and
|
This will create a new list with the same name, description, and
|
||||||
members as this starter pack.
|
members as this Starter Pack.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Admonition type="tip">
|
<Admonition type="tip">
|
||||||
<Trans>
|
<Trans>
|
||||||
Changes to the starter pack will not be reflected in the list
|
Changes to the Starter Pack will not be reflected in the list
|
||||||
after creation. The list will be an independent copy.
|
after creation. The list will be an independent copy.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Admonition>
|
</Admonition>
|
||||||
@@ -176,7 +175,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
a.pt_sm,
|
a.pt_sm,
|
||||||
]}>
|
]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create list`)}
|
label={l`Create list`}
|
||||||
onPress={onPressCreate}
|
onPress={onPressCreate}
|
||||||
size={platform({
|
size={platform({
|
||||||
web: 'small',
|
web: 'small',
|
||||||
@@ -188,7 +187,7 @@ export function CreateListFromStarterPackDialog({
|
|||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Cancel`)}
|
label={l`Cancel`}
|
||||||
onPress={() => control.close()}
|
onPress={() => control.close()}
|
||||||
size={platform({
|
size={platform({
|
||||||
web: 'small',
|
web: 'small',
|
||||||
@@ -204,7 +203,6 @@ export function CreateListFromStarterPackDialog({
|
|||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
|
|
||||||
<CreateOrEditListDialog
|
<CreateOrEditListDialog
|
||||||
control={createDialogControl}
|
control={createDialogControl}
|
||||||
purpose="app.bsky.graph.defs#curatelist"
|
purpose="app.bsky.graph.defs#curatelist"
|
||||||
@@ -215,13 +213,12 @@ export function CreateListFromStarterPackDialog({
|
|||||||
avatar: starterPack.list?.avatar,
|
avatar: starterPack.list?.avatar,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
control={loadingDialogControl}
|
control={loadingDialogControl}
|
||||||
nativeOptions={{preventDismiss: true}}>
|
nativeOptions={{preventDismiss: true}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Adding members to list...`)}
|
label={l`Adding members to list...`}
|
||||||
style={web({maxWidth: 400})}>
|
style={web({maxWidth: 400})}>
|
||||||
<View style={[a.align_center, a.gap_lg, a.py_5xl]}>
|
<View style={[a.align_center, a.gap_lg, a.py_5xl]}>
|
||||||
<Loader size="xl" />
|
<Loader size="xl" />
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ function DialogInner({
|
|||||||
ImageMeta | undefined | null
|
ImageMeta | undefined | null
|
||||||
>()
|
>()
|
||||||
|
|
||||||
// When creating with pre-filled values (from starter pack), consider dirty
|
// When creating with pre-filled values (from Starter Pack), consider dirty
|
||||||
// immediately so the Save button is enabled
|
// immediately so the Save button is enabled
|
||||||
const hasInitialValuesForCreate = !list && initialValues != null
|
const hasInitialValuesForCreate = !list && initialValues != null
|
||||||
const dirty =
|
const dirty =
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function useLandingEntry() {
|
|||||||
}, 500)
|
}, 500)
|
||||||
|
|
||||||
void (async () => {
|
void (async () => {
|
||||||
// Check for starter pack
|
// Check for Starter Pack
|
||||||
let uri: string | null | undefined
|
let uri: string | null | undefined
|
||||||
|
|
||||||
if (IS_ANDROID) {
|
if (IS_ANDROID) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function useLandingEntry() {
|
|||||||
const href = window.location.href
|
const href = window.location.href
|
||||||
const url = new URL(href)
|
const url = new URL(href)
|
||||||
|
|
||||||
// Check for starter pack
|
// Check for Starter Pack
|
||||||
const atUri = httpStarterPackUriToAtUri(href)
|
const atUri = httpStarterPackUriToAtUri(href)
|
||||||
if (atUri) {
|
if (atUri) {
|
||||||
// Determines if an App Clip is loading this landing page
|
// Determines if an App Clip is loading this landing page
|
||||||
|
|||||||
@@ -1,71 +1,70 @@
|
|||||||
import {useMemo} from 'react'
|
import {useMemo} from 'react'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {type ParsedReportSubject} from './types'
|
import {type ParsedReportSubject} from './types'
|
||||||
|
|
||||||
export function useCopyForSubject(subject: ParsedReportSubject) {
|
export function useCopyForSubject(subject: ParsedReportSubject) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
switch (subject.type) {
|
switch (subject.type) {
|
||||||
case 'account': {
|
case 'account': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this user`),
|
title: l`Report this user`,
|
||||||
subtitle: _(msg`Why should this user be reviewed?`),
|
subtitle: l`Why should this user be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'status': {
|
case 'status': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this livestream`),
|
title: l`Report this livestream`,
|
||||||
subtitle: _(msg`Why should this livestream be reviewed?`),
|
subtitle: l`Why should this livestream be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'post': {
|
case 'post': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this post`),
|
title: l`Report this post`,
|
||||||
subtitle: _(msg`Why should this post be reviewed?`),
|
subtitle: l`Why should this post be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'list': {
|
case 'list': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this list`),
|
title: l`Report this list`,
|
||||||
subtitle: _(msg`Why should this list be reviewed?`),
|
subtitle: l`Why should this list be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'feed': {
|
case 'feed': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this feed`),
|
title: l`Report this feed`,
|
||||||
subtitle: _(msg`Why should this feed be reviewed?`),
|
subtitle: l`Why should this feed be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'starterPack': {
|
case 'starterPack': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this starter pack`),
|
title: l`Report this Starter Pack`,
|
||||||
subtitle: _(msg`Why should this starter pack be reviewed?`),
|
subtitle: l`Why should this Starter Pack be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'convoMessage': {
|
case 'convoMessage': {
|
||||||
switch (subject.view) {
|
switch (subject.view) {
|
||||||
case 'convo': {
|
case 'convo': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this conversation`),
|
title: l`Report this conversation`,
|
||||||
subtitle: _(msg`Why should this conversation be reviewed?`),
|
subtitle: l`Why should this conversation be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'message': {
|
case 'message': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this message`),
|
title: l`Report this message`,
|
||||||
subtitle: _(msg`Why should this message be reviewed?`),
|
subtitle: l`Why should this message be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'convo': {
|
case 'convo': {
|
||||||
return {
|
return {
|
||||||
title: _(msg`Report this conversation`),
|
title: l`Report this conversation`,
|
||||||
subtitle: _(msg`Why should this conversation be reviewed?`),
|
subtitle: l`Why should this conversation be reviewed?`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [_, subject])
|
}, [l, subject])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ export function shortLinkToHref(url: string): string {
|
|||||||
try {
|
try {
|
||||||
const urlp = new URL(url)
|
const urlp = new URL(url)
|
||||||
|
|
||||||
// For now we only support starter packs, but in the future we should add additional paths to this check
|
// For now we only support Starter Packs, but in the future we should add additional paths to this check
|
||||||
const parts = urlp.pathname.split('/').filter(Boolean)
|
const parts = urlp.pathname.split('/').filter(Boolean)
|
||||||
if (parts.length === 1) {
|
if (parts.length === 1) {
|
||||||
return `/starter-pack-short/${parts[0]}`
|
return `/starter-pack-short/${parts[0]}`
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ export const router = new Router<AllNavigatableRoutes>({
|
|||||||
MessagesConversation: '/messages/:conversation',
|
MessagesConversation: '/messages/:conversation',
|
||||||
MessagesConversationSettings: '/messages/:conversation/settings',
|
MessagesConversationSettings: '/messages/:conversation/settings',
|
||||||
MessagesJoinRequests: '/messages/:conversation/requests',
|
MessagesJoinRequests: '/messages/:conversation/requests',
|
||||||
// starter packs
|
// Starter Packs
|
||||||
Start: '/start/:name/:rkey',
|
Start: '/start/:name/:rkey',
|
||||||
StarterPackEdit: '/starter-pack/edit/:rkey',
|
StarterPackEdit: '/starter-pack/edit/:rkey',
|
||||||
StarterPack: '/starter-pack/:name/:rkey',
|
StarterPack: '/starter-pack/:name/:rkey',
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export function StepFinished() {
|
|||||||
})
|
})
|
||||||
starterPack = spRes.starterPack
|
starterPack = spRes.starterPack
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to fetch starter pack', {safeMessage: e})
|
logger.error('Failed to fetch Starter Pack', {safeMessage: e})
|
||||||
// don't tell the user, just get them through onboarding.
|
// don't tell the user, just get them through onboarding.
|
||||||
}
|
}
|
||||||
const starterPackList = starterPack?.list
|
const starterPackList = starterPack?.list
|
||||||
@@ -87,7 +87,7 @@ export function StepFinished() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to fetch starter pack list items', {
|
logger.error('Failed to fetch Starter Pack list items', {
|
||||||
safeMessage: e,
|
safeMessage: e,
|
||||||
})
|
})
|
||||||
// don't tell the user, just get them through onboarding.
|
// don't tell the user, just get them through onboarding.
|
||||||
@@ -132,7 +132,7 @@ export function StepFinished() {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// Any starter pack feeds will be pinned _after_ the defaults
|
// Any Starter Pack feeds will be pinned _after_ the defaults
|
||||||
if (starterPack && starterPack.feeds?.length) {
|
if (starterPack && starterPack.feeds?.length) {
|
||||||
feedsToSave.push(
|
feedsToSave.push(
|
||||||
...starterPack.feeds.map(f => ({
|
...starterPack.feeds.map(f => ({
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function StarterPackCard({
|
|||||||
Toast.show(_(msg`An error occurred while trying to follow all`), {
|
Toast.show(_(msg`An error occurred while trying to follow all`), {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
logger.error('Failed to get list members for starter pack', {
|
logger.error('Failed to get list members for Starter Pack', {
|
||||||
safeMessage: e,
|
safeMessage: e,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function StepSuggestedStarterpacks() {
|
|||||||
<View style={[a.align_start, a.gap_sm]} testID="onboardingInterests">
|
<View style={[a.align_start, a.gap_sm]} testID="onboardingInterests">
|
||||||
<OnboardingPosition />
|
<OnboardingPosition />
|
||||||
<OnboardingTitleText>
|
<OnboardingTitleText>
|
||||||
<Trans comment="Starter packs suggested to the user for them to follow">
|
<Trans comment="Starter Packs suggested to the user for them to follow">
|
||||||
Find people to follow
|
Find people to follow
|
||||||
</Trans>
|
</Trans>
|
||||||
</OnboardingTitleText>
|
</OnboardingTitleText>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function Onboarding() {
|
|||||||
return bcp47Match.basicFilter('en', contentLanguages).length > 0
|
return bcp47Match.basicFilter('en', contentLanguages).length > 0
|
||||||
}, [contentLanguages])
|
}, [contentLanguages])
|
||||||
|
|
||||||
// starter packs screen is currently geared towards english-speaking accounts
|
// Starter Packs screen is currently geared towards english-speaking accounts
|
||||||
const showSuggestedStarterpacks = ENV !== 'e2e' && probablySpeaksEnglish
|
const showSuggestedStarterpacks = ENV !== 'e2e' && probablySpeaksEnglish
|
||||||
|
|
||||||
const findContactsEnabled =
|
const findContactsEnabled =
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {AtUri} from '@atproto/syntax'
|
import {AtUri} from '@atproto/syntax'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ export function MoreOptionsMenu({
|
|||||||
list: app.bsky.graph.defs.ListView
|
list: app.bsky.graph.defs.ListView
|
||||||
savedFeedConfig?: app.bsky.actor.defs.SavedFeed
|
savedFeedConfig?: app.bsky.actor.defs.SavedFeed
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const editListDialogControl = useDialogControl()
|
const editListDialogControl = useDialogControl()
|
||||||
@@ -79,15 +78,15 @@ export function MoreOptionsMenu({
|
|||||||
})
|
})
|
||||||
Toast.show(
|
Toast.show(
|
||||||
action === 'optOut'
|
action === 'optOut'
|
||||||
? _(msg`Opted out of starter pack`)
|
? l`Opted out of Starter Pack`
|
||||||
: _(msg`Opt-out undone`),
|
: l`Opt-out undone`,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onError: error => {
|
onError: error => {
|
||||||
logger.error('Failed to update starter pack opt-out', {
|
logger.error('Failed to update Starter Pack opt-out', {
|
||||||
safeMessage: error,
|
safeMessage: error,
|
||||||
})
|
})
|
||||||
Toast.show(_(msg`Failed to update starter pack opt-out`), {
|
Toast.show(l`Failed to update Starter Pack opt-out`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -96,16 +95,16 @@ export function MoreOptionsMenu({
|
|||||||
const onPressShare = () => {
|
const onPressShare = () => {
|
||||||
const {rkey} = new AtUri(list.uri)
|
const {rkey} = new AtUri(list.uri)
|
||||||
const url = toShareUrl(`/profile/${list.creator.did}/lists/${rkey}`)
|
const url = toShareUrl(`/profile/${list.creator.did}/lists/${rkey}`)
|
||||||
shareUrl(url)
|
void shareUrl(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onRemoveFromSavedFeeds = async () => {
|
const onRemoveFromSavedFeeds = async () => {
|
||||||
if (!savedFeedConfig) return
|
if (!savedFeedConfig) return
|
||||||
try {
|
try {
|
||||||
await removeSavedFeed(savedFeedConfig)
|
await removeSavedFeed(savedFeedConfig)
|
||||||
Toast.show(_(msg`Removed from your feeds`))
|
Toast.show(l`Removed from your feeds`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Toast.show(_(msg`There was an issue contacting the server`), {
|
Toast.show(l`There was an issue contacting the server`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
logger.error('Failed to remove pinned list', {message: e})
|
logger.error('Failed to remove pinned list', {message: e})
|
||||||
@@ -119,7 +118,7 @@ export function MoreOptionsMenu({
|
|||||||
await removeSavedFeed(savedFeedConfig)
|
await removeSavedFeed(savedFeedConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
Toast.show(_(msg({message: 'List deleted', context: 'toast'})))
|
Toast.show(l({message: 'List deleted', context: 'toast'}))
|
||||||
if (navigation.canGoBack()) {
|
if (navigation.canGoBack()) {
|
||||||
navigation.goBack()
|
navigation.goBack()
|
||||||
} else {
|
} else {
|
||||||
@@ -131,9 +130,9 @@ export function MoreOptionsMenu({
|
|||||||
try {
|
try {
|
||||||
if (!savedFeedConfig) return
|
if (!savedFeedConfig) return
|
||||||
await removeSavedFeed(savedFeedConfig)
|
await removeSavedFeed(savedFeedConfig)
|
||||||
Toast.show(_(msg`Unpinned list`))
|
Toast.show(l`Unpinned list`)
|
||||||
} catch {
|
} catch {
|
||||||
Toast.show(_(msg`Failed to unpin list`), {
|
Toast.show(l`Failed to unpin list`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -142,13 +141,11 @@ export function MoreOptionsMenu({
|
|||||||
const onUnsubscribeMute = async () => {
|
const onUnsubscribeMute = async () => {
|
||||||
try {
|
try {
|
||||||
await muteList({uri: list.uri, mute: false})
|
await muteList({uri: list.uri, mute: false})
|
||||||
Toast.show(_(msg({message: 'List unmuted', context: 'toast'})))
|
Toast.show(l({message: 'List unmuted', context: 'toast'}))
|
||||||
ax.metric('moderation:unsubscribedFromList', {listType: 'mute'})
|
ax.metric('moderation:unsubscribedFromList', {listType: 'mute'})
|
||||||
} catch {
|
} catch {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l`There was an issue. Please check your internet connection and try again.`,
|
||||||
msg`There was an issue. Please check your internet connection and try again.`,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,13 +153,11 @@ export function MoreOptionsMenu({
|
|||||||
const onUnsubscribeBlock = async () => {
|
const onUnsubscribeBlock = async () => {
|
||||||
try {
|
try {
|
||||||
await blockList({uri: list.uri, block: false})
|
await blockList({uri: list.uri, block: false})
|
||||||
Toast.show(_(msg({message: 'List unblocked', context: 'toast'})))
|
Toast.show(l({message: 'List unblocked', context: 'toast'}))
|
||||||
ax.metric('moderation:unsubscribedFromList', {listType: 'block'})
|
ax.metric('moderation:unsubscribedFromList', {listType: 'block'})
|
||||||
} catch {
|
} catch {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l`There was an issue. Please check your internet connection and try again.`,
|
||||||
msg`There was an issue. Please check your internet connection and try again.`,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +165,7 @@ export function MoreOptionsMenu({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
<Menu.Trigger label={_(msg`More options`)}>
|
<Menu.Trigger label={l`More options`}>
|
||||||
{({props}) => (
|
{({props}) => (
|
||||||
<Button
|
<Button
|
||||||
label={props.accessibilityLabel}
|
label={props.accessibilityLabel}
|
||||||
@@ -186,7 +181,7 @@ export function MoreOptionsMenu({
|
|||||||
<Menu.Outer showCancel>
|
<Menu.Outer showCancel>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={IS_WEB ? _(msg`Copy link to list`) : _(msg`Share via...`)}
|
label={IS_WEB ? l`Copy link to list` : l`Share via...`}
|
||||||
onPress={onPressShare}>
|
onPress={onPressShare}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
{IS_WEB ? (
|
{IS_WEB ? (
|
||||||
@@ -202,8 +197,8 @@ export function MoreOptionsMenu({
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{savedFeedConfig && (
|
{savedFeedConfig && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Remove from my feeds`)}
|
label={l`Remove from my feeds`}
|
||||||
onPress={onRemoveFromSavedFeeds}>
|
onPress={() => void onRemoveFromSavedFeeds()}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Remove from my feeds</Trans>
|
<Trans>Remove from my feeds</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
@@ -217,7 +212,7 @@ export function MoreOptionsMenu({
|
|||||||
{isOwner ? (
|
{isOwner ? (
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Edit list details`)}
|
label={l`Edit list details`}
|
||||||
onPress={editListDialogControl.open}>
|
onPress={editListDialogControl.open}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Edit list details</Trans>
|
<Trans>Edit list details</Trans>
|
||||||
@@ -225,7 +220,7 @@ export function MoreOptionsMenu({
|
|||||||
<Menu.ItemIcon position="right" icon={PencilLineIcon} />
|
<Menu.ItemIcon position="right" icon={PencilLineIcon} />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Delete list`)}
|
label={l`Delete list`}
|
||||||
onPress={deleteListPromptControl.open}>
|
onPress={deleteListPromptControl.open}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Delete list</Trans>
|
<Trans>Delete list</Trans>
|
||||||
@@ -237,7 +232,7 @@ export function MoreOptionsMenu({
|
|||||||
<>
|
<>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Report list`)}
|
label={l`Report list`}
|
||||||
onPress={reportDialogControl.open}>
|
onPress={reportDialogControl.open}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Report list</Trans>
|
<Trans>Report list</Trans>
|
||||||
@@ -252,8 +247,8 @@ export function MoreOptionsMenu({
|
|||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={
|
label={
|
||||||
referenceListOptOut
|
referenceListOptOut
|
||||||
? _(msg`Undo opt-out from starter pack`)
|
? l`Undo opt-out from Starter Pack`
|
||||||
: _(msg`Opt out of starter pack`)
|
: l`Opt out of Starter Pack`
|
||||||
}
|
}
|
||||||
disabled={isOptOutPending}
|
disabled={isOptOutPending}
|
||||||
onPress={optOutDialogControl.open}>
|
onPress={optOutDialogControl.open}>
|
||||||
@@ -261,7 +256,7 @@ export function MoreOptionsMenu({
|
|||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>Undo opt-out</Trans>
|
<Trans>Undo opt-out</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>Opt out of starter pack</Trans>
|
<Trans>Opt out of Starter Pack</Trans>
|
||||||
)}
|
)}
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
@@ -276,8 +271,8 @@ export function MoreOptionsMenu({
|
|||||||
<Menu.Divider />
|
<Menu.Divider />
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Unpin moderation list`)}
|
label={l`Unpin moderation list`}
|
||||||
onPress={onUnpinModList}>
|
onPress={() => void onUnpinModList()}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Unpin moderation list</Trans>
|
<Trans>Unpin moderation list</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
@@ -293,8 +288,8 @@ export function MoreOptionsMenu({
|
|||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
{isBlocking && (
|
{isBlocking && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Unblock list`)}
|
label={l`Unblock list`}
|
||||||
onPress={onUnsubscribeBlock}>
|
onPress={() => void onUnsubscribeBlock()}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Unblock list</Trans>
|
<Trans>Unblock list</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
@@ -303,8 +298,8 @@ export function MoreOptionsMenu({
|
|||||||
)}
|
)}
|
||||||
{isMuting && (
|
{isMuting && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Unmute list`)}
|
label={l`Unmute list`}
|
||||||
onPress={onUnsubscribeMute}>
|
onPress={() => void onUnsubscribeMute()}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Unmute list</Trans>
|
<Trans>Unmute list</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
@@ -316,37 +311,32 @@ export function MoreOptionsMenu({
|
|||||||
)}
|
)}
|
||||||
</Menu.Outer>
|
</Menu.Outer>
|
||||||
</Menu.Root>
|
</Menu.Root>
|
||||||
|
|
||||||
<CreateOrEditListDialog control={editListDialogControl} list={list} />
|
<CreateOrEditListDialog control={editListDialogControl} list={list} />
|
||||||
|
|
||||||
<Prompt.Basic
|
<Prompt.Basic
|
||||||
control={deleteListPromptControl}
|
control={deleteListPromptControl}
|
||||||
title={_(msg`Delete this list?`)}
|
title={l`Delete this list?`}
|
||||||
description={_(
|
description={l`If you delete this list, you won't be able to recover it.`}
|
||||||
msg`If you delete this list, you won't be able to recover it.`,
|
onConfirm={() => void onPressDelete()}
|
||||||
)}
|
confirmButtonCta={l`Delete`}
|
||||||
onConfirm={onPressDelete}
|
|
||||||
confirmButtonCta={_(msg`Delete`)}
|
|
||||||
confirmButtonColor="negative"
|
confirmButtonColor="negative"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isReferenceList ? (
|
{isReferenceList ? (
|
||||||
<Prompt.Outer control={optOutDialogControl}>
|
<Prompt.Outer control={optOutDialogControl}>
|
||||||
<Prompt.TitleText>
|
<Prompt.TitleText>
|
||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>Undo opt-out?</Trans>
|
<Trans>Undo opt-out?</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>Opt out of this starter pack?</Trans>
|
<Trans>Opt out of this Starter Pack?</Trans>
|
||||||
)}
|
)}
|
||||||
</Prompt.TitleText>
|
</Prompt.TitleText>
|
||||||
<Prompt.DescriptionText>
|
<Prompt.DescriptionText>
|
||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
You will be eligible to appear in this starter pack again.
|
You will be eligible to appear in this Starter Pack again.
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>
|
<Trans>
|
||||||
You will no longer appear in this starter pack. The creator will
|
You will no longer appear in this Starter Pack. The creator will
|
||||||
be able to see that you've opted out and remove you if they
|
be able to see that you've opted out and remove you if they
|
||||||
wish.
|
wish.
|
||||||
</Trans>
|
</Trans>
|
||||||
@@ -356,8 +346,8 @@ export function MoreOptionsMenu({
|
|||||||
<Prompt.Action
|
<Prompt.Action
|
||||||
cta={
|
cta={
|
||||||
referenceListOptOut
|
referenceListOptOut
|
||||||
? _(msg`Undo opt-out`)
|
? l`Undo opt-out`
|
||||||
: _(msg`Opt out of starter pack`)
|
: l`Opt out of Starter Pack`
|
||||||
}
|
}
|
||||||
color={referenceListOptOut ? 'primary' : 'negative'}
|
color={referenceListOptOut ? 'primary' : 'negative'}
|
||||||
disabled={isOptOutPending}
|
disabled={isOptOutPending}
|
||||||
@@ -369,7 +359,6 @@ export function MoreOptionsMenu({
|
|||||||
</Prompt.Actions>
|
</Prompt.Actions>
|
||||||
</Prompt.Outer>
|
</Prompt.Outer>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<ReportDialog
|
<ReportDialog
|
||||||
control={reportDialogControl}
|
control={reportDialogControl}
|
||||||
subject={{
|
subject={{
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ let SearchResults = ({
|
|||||||
},
|
},
|
||||||
noFilters &&
|
noFilters &&
|
||||||
isStarterPacksEnabled && {
|
isStarterPacksEnabled && {
|
||||||
title: l`Starter packs`,
|
title: l`Starter Packs`,
|
||||||
component: (
|
component: (
|
||||||
<SearchScreenStarterPackResults
|
<SearchScreenStarterPackResults
|
||||||
query={query}
|
query={query}
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ export function NotificationSettingsScreen({}: Props) {
|
|||||||
titleText={<Trans>Everything else</Trans>}
|
titleText={<Trans>Everything else</Trans>}
|
||||||
subtitleText={
|
subtitleText={
|
||||||
<Trans>
|
<Trans>
|
||||||
Get notifications for starter pack joins, verification, and other
|
Get notifications for Starter Pack joins, verification, and other
|
||||||
activity.
|
activity.
|
||||||
</Trans>
|
</Trans>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ function LandingScreenLoaded({
|
|||||||
a.text_md,
|
a.text_md,
|
||||||
{color: 'white'},
|
{color: 'white'},
|
||||||
]}>
|
]}>
|
||||||
Starter pack by {`@${creator.handle}`}
|
<Trans>Starter Pack by {`@${creator.handle}`}</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</LinearGradientBackground>
|
</LinearGradientBackground>
|
||||||
<View style={[a.gap_2xl, a.mx_lg, a.my_2xl]}>
|
<View style={[a.gap_2xl, a.mx_lg, a.my_2xl]}>
|
||||||
@@ -299,14 +299,14 @@ function LandingScreenLoaded({
|
|||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Create an account without using this starter pack`)}
|
label={_(msg`Create an account without using this Starter Pack`)}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="large"
|
size="large"
|
||||||
style={[a.py_lg]}
|
style={[a.py_lg]}
|
||||||
onPress={onJoinWithoutPress}>
|
onPress={onJoinWithoutPress}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Create an account without using this starter pack</Trans>
|
<Trans>Create an account without using this Starter Pack</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
@@ -396,7 +396,7 @@ export function AppClipOverlay({
|
|||||||
Download Bluesky to get started!
|
Download Bluesky to get started!
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[a.text_lg, {color: 'white'}]}>
|
<Text style={[a.text_lg, {color: 'white'}]}>
|
||||||
We'll remember the starter pack you chose and use it when you create
|
We’ll remember the Starter Pack you chose and use it when you create
|
||||||
an account in the app.
|
an account in the app.
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import {Image} from 'expo-image'
|
|||||||
import {AtUri} from '@atproto/syntax'
|
import {AtUri} from '@atproto/syntax'
|
||||||
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
||||||
import {RichText as RichTextAPI} from '@bsky/sdk/richtext'
|
import {RichText as RichTextAPI} from '@bsky/sdk/richtext'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
@@ -96,7 +94,7 @@ export function StarterPackScreen({route}: StarterPackScreeProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function StarterPackScreenShort({route}: StarterPackScreenShortProps) {
|
export function StarterPackScreenShort({route}: StarterPackScreenShortProps) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const {
|
const {
|
||||||
data: resolvedStarterPack,
|
data: resolvedStarterPack,
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -111,8 +109,8 @@ export function StarterPackScreenShort({route}: StarterPackScreenShortProps) {
|
|||||||
<ListMaybePlaceholder
|
<ListMaybePlaceholder
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isError={isError}
|
isError={isError}
|
||||||
errorMessage={_(msg`That starter pack could not be found.`)}
|
errorMessage={l`That Starter Pack could not be found.`}
|
||||||
emptyMessage={_(msg`That starter pack could not be found.`)}
|
emptyMessage={l`That Starter Pack could not be found.`}
|
||||||
/>
|
/>
|
||||||
</Layout.Screen>
|
</Layout.Screen>
|
||||||
)
|
)
|
||||||
@@ -130,7 +128,7 @@ export function StarterPackScreenInner({
|
|||||||
routeParams: StarterPackScreeProps['route']['params']
|
routeParams: StarterPackScreeProps['route']['params']
|
||||||
}) {
|
}) {
|
||||||
const {name, rkey} = routeParams
|
const {name, rkey} = routeParams
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
@@ -156,8 +154,8 @@ export function StarterPackScreenInner({
|
|||||||
<ListMaybePlaceholder
|
<ListMaybePlaceholder
|
||||||
isLoading={isLoadingDid || isLoadingStarterPack || !moderationOpts}
|
isLoading={isLoadingDid || isLoadingStarterPack || !moderationOpts}
|
||||||
isError={isErrorDid || isErrorStarterPack || !isValid}
|
isError={isErrorDid || isErrorStarterPack || !isValid}
|
||||||
errorMessage={_(msg`That starter pack could not be found.`)}
|
errorMessage={l`That Starter Pack could not be found.`}
|
||||||
emptyMessage={_(msg`That starter pack could not be found.`)}
|
emptyMessage={l`That Starter Pack could not be found.`}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -187,13 +185,13 @@ function StarterPackScreenLoaded({
|
|||||||
const showPeopleTab = Boolean(starterPack.list)
|
const showPeopleTab = Boolean(starterPack.list)
|
||||||
const showFeedsTab = Boolean(starterPack.feeds?.length)
|
const showFeedsTab = Boolean(starterPack.feeds?.length)
|
||||||
const showPostsTab = Boolean(starterPack.list)
|
const showPostsTab = Boolean(starterPack.list)
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
...(showPeopleTab ? [_(msg`People`)] : []),
|
...(showPeopleTab ? [l`People`] : []),
|
||||||
...(showFeedsTab ? [_(msg`Feeds`)] : []),
|
...(showFeedsTab ? [l`Feeds`] : []),
|
||||||
...(showPostsTab ? [_(msg`Posts`)] : []),
|
...(showPostsTab ? [l`Posts`] : []),
|
||||||
]
|
]
|
||||||
|
|
||||||
const qrCodeDialogControl = useDialogControl()
|
const qrCodeDialogControl = useDialogControl()
|
||||||
@@ -211,7 +209,7 @@ function StarterPackScreenLoaded({
|
|||||||
|
|
||||||
const onOpenShareDialog = useCallback(() => {
|
const onOpenShareDialog = useCallback(() => {
|
||||||
const rkey = new AtUri(starterPack.uri).rkey
|
const rkey = new AtUri(starterPack.uri).rkey
|
||||||
shortenLink(makeStarterPackLink(starterPack.creator.did, rkey)).then(
|
void shortenLink(makeStarterPackLink(starterPack.creator.did, rkey)).then(
|
||||||
res => {
|
res => {
|
||||||
setLink(res.url)
|
setLink(res.url)
|
||||||
},
|
},
|
||||||
@@ -301,7 +299,7 @@ function Header({
|
|||||||
routeParams: StarterPackScreeProps['route']['params']
|
routeParams: StarterPackScreeProps['route']['params']
|
||||||
onOpenShareDialog: () => void
|
onOpenShareDialog: () => void
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {currentAccount, hasSession} = useSession()
|
const {currentAccount, hasSession} = useSession()
|
||||||
const appviewClient = useAppviewClient()
|
const appviewClient = useAppviewClient()
|
||||||
@@ -351,10 +349,10 @@ function Header({
|
|||||||
listItems = await getAllListMembers(appviewClient, starterPack.list.uri)
|
listItems = await getAllListMembers(appviewClient, starterPack.list.uri)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsProcessing(false)
|
setIsProcessing(false)
|
||||||
Toast.show(_(msg`An error occurred while trying to follow all`), {
|
Toast.show(l`An error occurred while trying to follow all`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
logger.error('Failed to get list members for starter pack', {
|
logger.error('Failed to get list members for Starter Pack', {
|
||||||
safeMessage: e,
|
safeMessage: e,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -378,7 +376,7 @@ function Header({
|
|||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsProcessing(false)
|
setIsProcessing(false)
|
||||||
Toast.show(_(msg`An error occurred while trying to follow all`), {
|
Toast.show(l`An error occurred while trying to follow all`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
logger.error('Failed to follow all accounts', {safeMessage: e})
|
logger.error('Failed to follow all accounts', {safeMessage: e})
|
||||||
@@ -392,7 +390,7 @@ function Header({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Toast.show(_(msg`All accounts have been followed!`))
|
Toast.show(l`All accounts have been followed!`)
|
||||||
captureAction(ProgressGuideAction.Follow, dids.length)
|
captureAction(ProgressGuideAction.Follow, dids.length)
|
||||||
ax.metric('starterPack:followAll', {
|
ax.metric('starterPack:followAll', {
|
||||||
logContext: 'StarterPackProfilesList',
|
logContext: 'StarterPackProfilesList',
|
||||||
@@ -427,7 +425,7 @@ function Header({
|
|||||||
<View style={[a.flex_row, a.gap_sm, a.align_center]}>
|
<View style={[a.flex_row, a.gap_sm, a.align_center]}>
|
||||||
{isOwn ? (
|
{isOwn ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Share this starter pack`)}
|
label={l`Share this Starter Pack`}
|
||||||
hitSlop={HITSLOP_20}
|
hitSlop={HITSLOP_20}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -439,7 +437,7 @@ function Header({
|
|||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Follow all`)}
|
label={l`Follow all`}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -465,7 +463,7 @@ function Header({
|
|||||||
{richText ? <RichText value={richText} style={[a.text_md]} /> : null}
|
{richText ? <RichText value={richText} style={[a.text_md]} /> : null}
|
||||||
{!hasSession ? (
|
{!hasSession ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Join Bluesky`)}
|
label={l`Join Bluesky`}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setActiveStarterPack({
|
setActiveStarterPack({
|
||||||
uri: starterPack.uri,
|
uri: starterPack.uri,
|
||||||
@@ -491,12 +489,12 @@ function Header({
|
|||||||
a.text_sm,
|
a.text_sm,
|
||||||
t.atoms.text_contrast_medium,
|
t.atoms.text_contrast_medium,
|
||||||
]}>
|
]}>
|
||||||
<Trans comment="Number of users (always at least 25) who have joined Bluesky using a specific starter pack">
|
<Trans comment="Number of users (always at least 25) who have joined Bluesky using a specific Starter Pack">
|
||||||
<Plural
|
<Plural
|
||||||
value={starterPack.joinedAllTimeCount || 0}
|
value={starterPack.joinedAllTimeCount || 0}
|
||||||
other="# people have"
|
other="# people have"
|
||||||
/>{' '}
|
/>{' '}
|
||||||
joined Bluesky via this starter pack!
|
joined Bluesky via this Starter Pack!
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -517,7 +515,7 @@ function OverflowMenu({
|
|||||||
onOpenShareDialog: () => void
|
onOpenShareDialog: () => void
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
@@ -543,7 +541,7 @@ function OverflowMenu({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onError: e => {
|
onError: e => {
|
||||||
logger.error('Failed to delete starter pack', {safeMessage: e})
|
logger.error('Failed to delete Starter Pack', {safeMessage: e})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -559,21 +557,21 @@ function OverflowMenu({
|
|||||||
})
|
})
|
||||||
Toast.show(
|
Toast.show(
|
||||||
action === 'optOut'
|
action === 'optOut'
|
||||||
? _(msg`Opted out of starter pack`)
|
? l`Opted out of Starter Pack`
|
||||||
: _(msg`Opt-out undone`),
|
: l`Opt-out undone`,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onError: error => {
|
onError: error => {
|
||||||
logger.error('Failed to update starter pack opt-out', {
|
logger.error('Failed to update Starter Pack opt-out', {
|
||||||
safeMessage: error,
|
safeMessage: error,
|
||||||
})
|
})
|
||||||
Toast.show(_(msg`Failed to update starter pack opt-out`), {
|
Toast.show(l`Failed to update Starter Pack opt-out`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const onDeleteStarterPack = async () => {
|
const onDeleteStarterPack = () => {
|
||||||
if (!starterPack.list) {
|
if (!starterPack.list) {
|
||||||
logger.error(`Unable to delete starterpack because list is missing`)
|
logger.error(`Unable to delete starterpack because list is missing`)
|
||||||
return
|
return
|
||||||
@@ -589,12 +587,12 @@ function OverflowMenu({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
<Menu.Trigger label={_(msg`Repost or quote post`)}>
|
<Menu.Trigger label={l`Repost or quote post`}>
|
||||||
{({props}) => (
|
{({props}) => (
|
||||||
<Button
|
<Button
|
||||||
{...props}
|
{...props}
|
||||||
testID="headerDropdownBtn"
|
testID="headerDropdownBtn"
|
||||||
label={_(msg`Open starter pack menu`)}
|
label={l`Open Starter Pack menu`}
|
||||||
hitSlop={HITSLOP_20}
|
hitSlop={HITSLOP_20}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -608,7 +606,7 @@ function OverflowMenu({
|
|||||||
{isOwn ? (
|
{isOwn ? (
|
||||||
<>
|
<>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Edit starter pack`)}
|
label={l`Edit Starter Pack`}
|
||||||
testID="editStarterPackLinkBtn"
|
testID="editStarterPackLinkBtn"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigation.navigate('StarterPackEdit', {
|
navigation.navigate('StarterPackEdit', {
|
||||||
@@ -621,7 +619,7 @@ function OverflowMenu({
|
|||||||
<Menu.ItemIcon icon={Pencil} position="right" />
|
<Menu.ItemIcon icon={Pencil} position="right" />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Delete starter pack`)}
|
label={l`Delete Starter Pack`}
|
||||||
testID="deleteStarterPackBtn"
|
testID="deleteStarterPackBtn"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
deleteDialogControl.open()
|
deleteDialogControl.open()
|
||||||
@@ -632,7 +630,7 @@ function OverflowMenu({
|
|||||||
<Menu.ItemIcon icon={Trash} position="right" />
|
<Menu.ItemIcon icon={Trash} position="right" />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Create a list from this starter pack`)}
|
label={l`Create a list from this Starter Pack`}
|
||||||
testID="convertToListBtn"
|
testID="convertToListBtn"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
convertToListDialogControl.open()
|
convertToListDialogControl.open()
|
||||||
@@ -648,9 +646,7 @@ function OverflowMenu({
|
|||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={
|
label={
|
||||||
IS_WEB
|
IS_WEB ? l`Copy link to Starter Pack` : l`Share via...`
|
||||||
? _(msg`Copy link to starter pack`)
|
|
||||||
: _(msg`Share via...`)
|
|
||||||
}
|
}
|
||||||
testID="shareStarterPackLinkBtn"
|
testID="shareStarterPackLinkBtn"
|
||||||
onPress={onOpenShareDialog}>
|
onPress={onOpenShareDialog}>
|
||||||
@@ -669,10 +665,10 @@ function OverflowMenu({
|
|||||||
</Menu.Group>
|
</Menu.Group>
|
||||||
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Report starter pack`)}
|
label={l`Report Starter Pack`}
|
||||||
onPress={() => reportDialogControl.open()}>
|
onPress={() => reportDialogControl.open()}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Report starter pack</Trans>
|
<Trans>Report Starter Pack</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
<Menu.ItemIcon icon={CircleInfo} position="right" />
|
<Menu.ItemIcon icon={CircleInfo} position="right" />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
@@ -680,8 +676,8 @@ function OverflowMenu({
|
|||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={
|
label={
|
||||||
referenceListOptOut
|
referenceListOptOut
|
||||||
? _(msg`Undo opt-out from starter pack`)
|
? l`Undo opt-out from Starter Pack`
|
||||||
: _(msg`Opt out of starter pack`)
|
: l`Opt out of Starter Pack`
|
||||||
}
|
}
|
||||||
disabled={isOptOutPending}
|
disabled={isOptOutPending}
|
||||||
onPress={() => optOutDialogControl.open()}>
|
onPress={() => optOutDialogControl.open()}>
|
||||||
@@ -689,7 +685,7 @@ function OverflowMenu({
|
|||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>Undo opt-out</Trans>
|
<Trans>Undo opt-out</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>Opt out of starter pack</Trans>
|
<Trans>Opt out of Starter Pack</Trans>
|
||||||
)}
|
)}
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
@@ -698,7 +694,6 @@ function OverflowMenu({
|
|||||||
)}
|
)}
|
||||||
</Menu.Outer>
|
</Menu.Outer>
|
||||||
</Menu.Root>
|
</Menu.Root>
|
||||||
|
|
||||||
{starterPack.list && (
|
{starterPack.list && (
|
||||||
<ReportDialog
|
<ReportDialog
|
||||||
control={reportDialogControl}
|
control={reportDialogControl}
|
||||||
@@ -708,13 +703,12 @@ function OverflowMenu({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Prompt.Outer control={deleteDialogControl}>
|
<Prompt.Outer control={deleteDialogControl}>
|
||||||
<Prompt.TitleText>
|
<Prompt.TitleText>
|
||||||
<Trans>Delete starter pack?</Trans>
|
<Trans>Delete Starter Pack?</Trans>
|
||||||
</Prompt.TitleText>
|
</Prompt.TitleText>
|
||||||
<Prompt.DescriptionText>
|
<Prompt.DescriptionText>
|
||||||
<Trans>Are you sure you want to delete this starter pack?</Trans>
|
<Trans>Are you sure you want to delete this Starter Pack?</Trans>
|
||||||
</Prompt.DescriptionText>
|
</Prompt.DescriptionText>
|
||||||
{deleteError && (
|
{deleteError && (
|
||||||
<View
|
<View
|
||||||
@@ -742,7 +736,7 @@ function OverflowMenu({
|
|||||||
variant="solid"
|
variant="solid"
|
||||||
color="negative"
|
color="negative"
|
||||||
size={gtMobile ? 'small' : 'large'}
|
size={gtMobile ? 'small' : 'large'}
|
||||||
label={_(msg`Yes, delete this starter pack`)}
|
label={l`Yes, delete this Starter Pack`}
|
||||||
onPress={onDeleteStarterPack}>
|
onPress={onDeleteStarterPack}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Delete</Trans>
|
<Trans>Delete</Trans>
|
||||||
@@ -752,24 +746,23 @@ function OverflowMenu({
|
|||||||
<Prompt.Cancel />
|
<Prompt.Cancel />
|
||||||
</Prompt.Actions>
|
</Prompt.Actions>
|
||||||
</Prompt.Outer>
|
</Prompt.Outer>
|
||||||
|
|
||||||
{starterPack.list ? (
|
{starterPack.list ? (
|
||||||
<Prompt.Outer control={optOutDialogControl}>
|
<Prompt.Outer control={optOutDialogControl}>
|
||||||
<Prompt.TitleText>
|
<Prompt.TitleText>
|
||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>Undo opt-out?</Trans>
|
<Trans>Undo opt-out?</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>Opt out of this starter pack?</Trans>
|
<Trans>Opt out of this Starter Pack?</Trans>
|
||||||
)}
|
)}
|
||||||
</Prompt.TitleText>
|
</Prompt.TitleText>
|
||||||
<Prompt.DescriptionText>
|
<Prompt.DescriptionText>
|
||||||
{referenceListOptOut ? (
|
{referenceListOptOut ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
You will be eligible to appear in this starter pack again.
|
You will be eligible to appear in this Starter Pack again.
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>
|
<Trans>
|
||||||
You will no longer appear in this starter pack. The creator will
|
You will no longer appear in this Starter Pack. The creator will
|
||||||
be able to see that you've opted out and remove you if they
|
be able to see that you've opted out and remove you if they
|
||||||
wish.
|
wish.
|
||||||
</Trans>
|
</Trans>
|
||||||
@@ -782,8 +775,8 @@ function OverflowMenu({
|
|||||||
size="large"
|
size="large"
|
||||||
label={
|
label={
|
||||||
referenceListOptOut
|
referenceListOptOut
|
||||||
? _(msg`Undo opt-out`)
|
? l`Undo opt-out`
|
||||||
: _(msg`Opt out of starter pack`)
|
: l`Opt out of Starter Pack`
|
||||||
}
|
}
|
||||||
disabled={isOptOutPending}
|
disabled={isOptOutPending}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
@@ -804,7 +797,6 @@ function OverflowMenu({
|
|||||||
</Prompt.Actions>
|
</Prompt.Actions>
|
||||||
</Prompt.Outer>
|
</Prompt.Outer>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<CreateListFromStarterPackDialog
|
<CreateListFromStarterPackDialog
|
||||||
control={convertToListDialogControl}
|
control={convertToListDialogControl}
|
||||||
starterPack={starterPack}
|
starterPack={starterPack}
|
||||||
@@ -814,7 +806,7 @@ function OverflowMenu({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function InvalidStarterPack({rkey}: {rkey: string}) {
|
function InvalidStarterPack({rkey}: {rkey: string}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
@@ -835,8 +827,8 @@ function InvalidStarterPack({rkey}: {rkey: string}) {
|
|||||||
},
|
},
|
||||||
onError: e => {
|
onError: e => {
|
||||||
setIsProcessing(false)
|
setIsProcessing(false)
|
||||||
logger.error('Failed to delete invalid starter pack', {safeMessage: e})
|
logger.error('Failed to delete invalid Starter Pack', {safeMessage: e})
|
||||||
Toast.show(_(msg`Failed to delete starter pack`), {
|
Toast.show(l`Failed to delete Starter Pack`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -847,7 +839,7 @@ function InvalidStarterPack({rkey}: {rkey: string}) {
|
|||||||
<View style={[a.py_4xl, a.px_xl, a.align_center, a.gap_5xl]}>
|
<View style={[a.py_4xl, a.px_xl, a.align_center, a.gap_5xl]}>
|
||||||
<View style={[a.w_full, a.align_center, a.gap_lg]}>
|
<View style={[a.w_full, a.align_center, a.gap_lg]}>
|
||||||
<Text style={[a.font_semi_bold, a.text_3xl]}>
|
<Text style={[a.font_semi_bold, a.text_3xl]}>
|
||||||
<Trans>Starter pack is invalid</Trans>
|
<Trans>Starter Pack is invalid</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
@@ -858,8 +850,8 @@ function InvalidStarterPack({rkey}: {rkey: string}) {
|
|||||||
gtMobile ? {width: 450} : [a.w_full, a.px_lg],
|
gtMobile ? {width: 450} : [a.w_full, a.px_lg],
|
||||||
]}>
|
]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
The starter pack that you are trying to view is invalid. You may
|
The Starter Pack that you are trying to view is invalid. You may
|
||||||
delete this starter pack instead.
|
delete this Starter Pack instead.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -867,7 +859,7 @@ function InvalidStarterPack({rkey}: {rkey: string}) {
|
|||||||
<Button
|
<Button
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="primary"
|
color="primary"
|
||||||
label={_(msg`Delete starter pack`)}
|
label={l`Delete Starter Pack`}
|
||||||
size="large"
|
size="large"
|
||||||
style={[a.rounded_sm, a.overflow_hidden, {paddingVertical: 10}]}
|
style={[a.rounded_sm, a.overflow_hidden, {paddingVertical: 10}]}
|
||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
@@ -883,7 +875,7 @@ function InvalidStarterPack({rkey}: {rkey: string}) {
|
|||||||
<Button
|
<Button
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
label={_(msg`Return to previous page`)}
|
label={l`Return to previous page`}
|
||||||
size="large"
|
size="large"
|
||||||
style={[a.rounded_sm, a.overflow_hidden, {paddingVertical: 10}]}
|
style={[a.rounded_sm, a.overflow_hidden, {paddingVertical: 10}]}
|
||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ export function StepDetails() {
|
|||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<TextField.LabelText>
|
<TextField.LabelText>
|
||||||
<Trans>What do you want to call your starter pack?</Trans>
|
<Trans>What do you want to call your Starter Pack?</Trans>
|
||||||
</TextField.LabelText>
|
</TextField.LabelText>
|
||||||
<TextField.Root>
|
<TextField.Root>
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
label={
|
label={
|
||||||
name ? _(msg`${name}'s starter pack`) : _(msg`My starter pack`)
|
name ? _(msg`${name}’s Starter Pack`) : _(msg`My Starter Pack`)
|
||||||
}
|
}
|
||||||
value={state.name}
|
value={state.name}
|
||||||
onChangeText={text => dispatch({type: 'SetName', name: text})}
|
onChangeText={text => dispatch({type: 'SetName', name: text})}
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
|||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {AtUri} from '@atproto/syntax'
|
import {AtUri} from '@atproto/syntax'
|
||||||
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
import {type ModerationOpts} from '@bsky/sdk/moderation'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
|
|
||||||
@@ -71,7 +69,7 @@ export function Wizard({
|
|||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
|
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
// Use targetDid if provided (from dialog), otherwise use current account
|
// Use targetDid if provided (from dialog), otherwise use current account
|
||||||
const profileDid = targetDid || currentAccount!.did
|
const profileDid = targetDid || currentAccount!.did
|
||||||
@@ -109,7 +107,7 @@ export function Wizard({
|
|||||||
isLoadingStarterPack || isLoadingProfiles || isLoadingProfile
|
isLoadingStarterPack || isLoadingProfiles || isLoadingProfile
|
||||||
}
|
}
|
||||||
isError={isErrorStarterPack || isErrorProfiles || isErrorProfile}
|
isError={isErrorStarterPack || isErrorProfiles || isErrorProfile}
|
||||||
errorMessage={_(msg`That starter pack could not be found.`)}
|
errorMessage={l`That Starter Pack could not be found.`}
|
||||||
/>
|
/>
|
||||||
</Layout.Screen>
|
</Layout.Screen>
|
||||||
)
|
)
|
||||||
@@ -119,7 +117,7 @@ export function Wizard({
|
|||||||
<ListMaybePlaceholder
|
<ListMaybePlaceholder
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
isError={true}
|
isError={true}
|
||||||
errorMessage={_(msg`That starter pack could not be found.`)}
|
errorMessage={l`That Starter Pack could not be found.`}
|
||||||
/>
|
/>
|
||||||
</Layout.Screen>
|
</Layout.Screen>
|
||||||
)
|
)
|
||||||
@@ -164,7 +162,7 @@ function WizardInner({
|
|||||||
}) {
|
}) {
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const [state, dispatch] = useWizardState()
|
const [state, dispatch] = useWizardState()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
@@ -182,7 +180,7 @@ function WizardInner({
|
|||||||
|
|
||||||
const getDefaultName = () => {
|
const getDefaultName = () => {
|
||||||
const displayName = createSanitizedDisplayName(currentProfile!, true)
|
const displayName = createSanitizedDisplayName(currentProfile!, true)
|
||||||
return _(msg`${displayName}'s Starter Pack`).slice(0, 50)
|
return l`${displayName}’s Starter Pack`.slice(0, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
const wizardUiStrings: Record<
|
const wizardUiStrings: Record<
|
||||||
@@ -190,16 +188,16 @@ function WizardInner({
|
|||||||
{header: string; nextBtn: string; subtitle?: string}
|
{header: string; nextBtn: string; subtitle?: string}
|
||||||
> = {
|
> = {
|
||||||
Details: {
|
Details: {
|
||||||
header: _(msg`Starter Pack`),
|
header: l`Starter Pack`,
|
||||||
nextBtn: _(msg`Next`),
|
nextBtn: l`Next`,
|
||||||
},
|
},
|
||||||
Profiles: {
|
Profiles: {
|
||||||
header: _(msg`Choose People`),
|
header: l`Choose People`,
|
||||||
nextBtn: _(msg`Next`),
|
nextBtn: l`Next`,
|
||||||
},
|
},
|
||||||
Feeds: {
|
Feeds: {
|
||||||
header: _(msg`Choose Feeds`),
|
header: l`Choose Feeds`,
|
||||||
nextBtn: state.feeds.length === 0 ? _(msg`Skip`) : _(msg`Finish`),
|
nextBtn: state.feeds.length === 0 ? l`Skip` : l`Finish`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const currUiStrings = wizardUiStrings[state.currentStep]
|
const currUiStrings = wizardUiStrings[state.currentStep]
|
||||||
@@ -212,7 +210,7 @@ function WizardInner({
|
|||||||
profilesCount: state.profiles.length,
|
profilesCount: state.profiles.length,
|
||||||
feedsCount: state.feeds.length,
|
feedsCount: state.feeds.length,
|
||||||
})
|
})
|
||||||
Image.prefetch([getStarterPackOgCard(currentProfile!.did, rkey)])
|
void Image.prefetch([getStarterPackOgCard(currentProfile!.did, rkey)])
|
||||||
dispatch({type: 'SetProcessing', processing: false})
|
dispatch({type: 'SetProcessing', processing: false})
|
||||||
|
|
||||||
if (fromDialog) {
|
if (fromDialog) {
|
||||||
@@ -241,9 +239,9 @@ function WizardInner({
|
|||||||
const {mutate: createStarterPack} = useCreateStarterPackMutation({
|
const {mutate: createStarterPack} = useCreateStarterPackMutation({
|
||||||
onSuccess: onSuccessCreate,
|
onSuccess: onSuccessCreate,
|
||||||
onError: e => {
|
onError: e => {
|
||||||
logger.error('Failed to create starter pack', {safeMessage: e})
|
logger.error('Failed to create Starter Pack', {safeMessage: e})
|
||||||
dispatch({type: 'SetProcessing', processing: false})
|
dispatch({type: 'SetProcessing', processing: false})
|
||||||
Toast.show(_(msg`Failed to create starter pack`), {
|
Toast.show(l`Failed to create Starter Pack`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -251,15 +249,15 @@ function WizardInner({
|
|||||||
const {mutate: editStarterPack} = useEditStarterPackMutation({
|
const {mutate: editStarterPack} = useEditStarterPackMutation({
|
||||||
onSuccess: onSuccessEdit,
|
onSuccess: onSuccessEdit,
|
||||||
onError: e => {
|
onError: e => {
|
||||||
logger.error('Failed to edit starter pack', {safeMessage: e})
|
logger.error('Failed to edit Starter Pack', {safeMessage: e})
|
||||||
dispatch({type: 'SetProcessing', processing: false})
|
dispatch({type: 'SetProcessing', processing: false})
|
||||||
Toast.show(_(msg`Failed to create starter pack`), {
|
Toast.show(l`Failed to create Starter Pack`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = () => {
|
||||||
dispatch({type: 'SetProcessing', processing: true})
|
dispatch({type: 'SetProcessing', processing: true})
|
||||||
if (currentStarterPack && currentListItems) {
|
if (currentStarterPack && currentListItems) {
|
||||||
editStarterPack({
|
editStarterPack({
|
||||||
@@ -308,8 +306,8 @@ function WizardInner({
|
|||||||
<Layout.Center style={[a.flex_1]}>
|
<Layout.Center style={[a.flex_1]}>
|
||||||
<Layout.Header.Outer>
|
<Layout.Header.Outer>
|
||||||
<Layout.Header.BackButton
|
<Layout.Header.BackButton
|
||||||
label={_(msg`Back`)}
|
label={l`Back`}
|
||||||
accessibilityHint={_(msg`Returns to the previous step`)}
|
accessibilityHint={l`Returns to the previous step`}
|
||||||
onPress={evt => {
|
onPress={evt => {
|
||||||
if (state.currentStep !== 'Details') {
|
if (state.currentStep !== 'Details') {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
@@ -324,7 +322,7 @@ function WizardInner({
|
|||||||
</Layout.Header.Content>
|
</Layout.Header.Content>
|
||||||
{isEditEnabled ? (
|
{isEditEnabled ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Edit`)}
|
label={l`Edit`}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
onPress={editDialogControl.open}>
|
onPress={editDialogControl.open}>
|
||||||
@@ -336,7 +334,6 @@ function WizardInner({
|
|||||||
<Layout.Header.Slot />
|
<Layout.Header.Slot />
|
||||||
)}
|
)}
|
||||||
</Layout.Header.Outer>
|
</Layout.Header.Outer>
|
||||||
|
|
||||||
<Container>
|
<Container>
|
||||||
{state.currentStep === 'Details' ? (
|
{state.currentStep === 'Details' ? (
|
||||||
<StepDetails />
|
<StepDetails />
|
||||||
@@ -355,7 +352,6 @@ function WizardInner({
|
|||||||
<StepFeeds moderationOpts={moderationOpts} />
|
<StepFeeds moderationOpts={moderationOpts} />
|
||||||
) : null}
|
) : null}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
{state.currentStep !== 'Details' && (
|
{state.currentStep !== 'Details' && (
|
||||||
<Footer onNext={onNext} nextBtnText={currUiStrings.nextBtn} />
|
<Footer onNext={onNext} nextBtnText={currUiStrings.nextBtn} />
|
||||||
)}
|
)}
|
||||||
@@ -371,7 +367,7 @@ function WizardInner({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Container({children}: {children: React.ReactNode}) {
|
function Container({children}: {children: React.ReactNode}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const [state, dispatch] = useWizardState()
|
const [state, dispatch] = useWizardState()
|
||||||
|
|
||||||
if (state.currentStep === 'Profiles' || state.currentStep === 'Feeds') {
|
if (state.currentStep === 'Profiles' || state.currentStep === 'Feeds') {
|
||||||
@@ -386,7 +382,7 @@ function Container({children}: {children: React.ReactNode}) {
|
|||||||
{state.currentStep === 'Details' && (
|
{state.currentStep === 'Details' && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Next`)}
|
label={l`Next`}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -490,7 +486,7 @@ function Footer({
|
|||||||
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
||||||
{getName(items[0])}{' '}
|
{getName(items[0])}{' '}
|
||||||
</Text>
|
</Text>
|
||||||
right now! Add more people to your starter pack by searching
|
right now! Add more people to your Starter Pack by searching
|
||||||
above.
|
above.
|
||||||
</Trans>
|
</Trans>
|
||||||
)
|
)
|
||||||
@@ -502,7 +498,7 @@ function Footer({
|
|||||||
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
||||||
{getName(items[1] /* [0] is self, skip it */)}{' '}
|
{getName(items[1] /* [0] is self, skip it */)}{' '}
|
||||||
</Text>
|
</Text>
|
||||||
are included in your starter pack
|
are included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>
|
<Trans>
|
||||||
@@ -514,7 +510,7 @@ function Footer({
|
|||||||
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
||||||
{getName(items[1] /* [0] is self, skip it */)}{' '}
|
{getName(items[1] /* [0] is self, skip it */)}{' '}
|
||||||
</Text>
|
</Text>
|
||||||
are included in your starter pack
|
are included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
)
|
)
|
||||||
) : items.length > 2 ? (
|
) : items.length > 2 ? (
|
||||||
@@ -531,7 +527,7 @@ function Footer({
|
|||||||
one="# other"
|
one="# other"
|
||||||
other="# others"
|
other="# others"
|
||||||
/>{' '}
|
/>{' '}
|
||||||
are included in your starter pack
|
are included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : null /* Should not happen. */
|
) : null /* Should not happen. */
|
||||||
}
|
}
|
||||||
@@ -540,7 +536,7 @@ function Footer({
|
|||||||
items.length === 0 ? (
|
items.length === 0 ? (
|
||||||
<View style={[a.gap_sm]}>
|
<View style={[a.gap_sm]}>
|
||||||
<Text style={[a.font_semi_bold, a.text_center, textStyles]}>
|
<Text style={[a.font_semi_bold, a.text_center, textStyles]}>
|
||||||
<Trans>Add some feeds to your starter pack!</Trans>
|
<Trans>Add some feeds to your Starter Pack!</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[a.text_center, textStyles]}>
|
<Text style={[a.text_center, textStyles]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
@@ -556,7 +552,7 @@ function Footer({
|
|||||||
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
||||||
{getName(items[0])}
|
{getName(items[0])}
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
is included in your starter pack
|
is included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : items.length === 2 ? (
|
) : items.length === 2 ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
@@ -568,7 +564,7 @@ function Footer({
|
|||||||
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
<Text style={[a.font_semi_bold, textStyles]} emoji>
|
||||||
{getName(items[1])}{' '}
|
{getName(items[1])}{' '}
|
||||||
</Text>
|
</Text>
|
||||||
are included in your starter pack
|
are included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : items.length > 2 ? (
|
) : items.length > 2 ? (
|
||||||
<Trans context="feeds">
|
<Trans context="feeds">
|
||||||
@@ -584,7 +580,7 @@ function Footer({
|
|||||||
one="# other"
|
one="# other"
|
||||||
other="# others"
|
other="# others"
|
||||||
/>{' '}
|
/>{' '}
|
||||||
are included in your starter pack
|
are included in your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : null /* Should not happen. */
|
) : null /* Should not happen. */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function useListMembershipAddMutation({
|
|||||||
onError,
|
onError,
|
||||||
}: {
|
}: {
|
||||||
/**
|
/**
|
||||||
* Needed for optimistic update of starter pack query
|
* Needed for optimistic update of Starter Pack query
|
||||||
*/
|
*/
|
||||||
subject?: bsky.profile.AnyProfileView
|
subject?: bsky.profile.AnyProfileView
|
||||||
onSuccess?: (data: {uri: AtUriString; cid: string}) => void
|
onSuccess?: (data: {uri: AtUriString; cid: string}) => void
|
||||||
@@ -66,7 +66,7 @@ export function useListMembershipAddMutation({
|
|||||||
})
|
})
|
||||||
}, 1e3)
|
}, 1e3)
|
||||||
|
|
||||||
// update WITH_MEMBERSHIPS query for starter packs
|
// update WITH_MEMBERSHIPS query for Starter Packs
|
||||||
if (subject) {
|
if (subject) {
|
||||||
queryClient.setQueryData<
|
queryClient.setQueryData<
|
||||||
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
|
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
|
||||||
@@ -161,7 +161,7 @@ export function useListMembershipRemoveMutation({
|
|||||||
})
|
})
|
||||||
}, 1e3)
|
}, 1e3)
|
||||||
|
|
||||||
// update WITH_MEMBERSHIPS query for starter packs
|
// update WITH_MEMBERSHIPS query for Starter Packs
|
||||||
queryClient.setQueryData<
|
queryClient.setQueryData<
|
||||||
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
|
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
|
||||||
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
|
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function makeFollowNotification(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('groupNotifications', () => {
|
describe('groupNotifications', () => {
|
||||||
it('does not group a starter pack follow with an organic follow', () => {
|
it('does not group a Starter Pack follow with an organic follow', () => {
|
||||||
const pack = 'at://did:plc:alice/app.bsky.graph.starterpack/a'
|
const pack = 'at://did:plc:alice/app.bsky.graph.starterpack/a'
|
||||||
|
|
||||||
const grouped = groupNotifications([
|
const grouped = groupNotifications([
|
||||||
@@ -56,7 +56,7 @@ describe('groupNotifications', () => {
|
|||||||
expect(grouped[1].additional).toBeUndefined()
|
expect(grouped[1].additional).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('groups follows by starter pack', () => {
|
it('groups follows by Starter Pack', () => {
|
||||||
const packA = 'at://did:plc:alice/app.bsky.graph.starterpack/a'
|
const packA = 'at://did:plc:alice/app.bsky.graph.starterpack/a'
|
||||||
const packB = 'at://did:plc:bob/app.bsky.graph.starterpack/b'
|
const packB = 'at://did:plc:bob/app.bsky.graph.starterpack/b'
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export function useReferenceListOptOutMutation({
|
|||||||
>({
|
>({
|
||||||
mutationFn: async ({referenceListOptOut}) => {
|
mutationFn: async ({referenceListOptOut}) => {
|
||||||
if (!starterPack.list) {
|
if (!starterPack.list) {
|
||||||
throw new Error('Starter pack does not have a reference list')
|
throw new Error('Starter Pack does not have a reference list')
|
||||||
}
|
}
|
||||||
|
|
||||||
let nextOptOut: AtUriString | undefined
|
let nextOptOut: AtUriString | undefined
|
||||||
@@ -292,7 +292,7 @@ export function useCreateStarterPackMutation({
|
|||||||
})
|
})
|
||||||
onSuccess(data)
|
onSuccess(data)
|
||||||
},
|
},
|
||||||
onError: async error => {
|
onError: error => {
|
||||||
onError(error)
|
onError(error)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -333,7 +333,7 @@ export function useEditStarterPackMutation({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bsky.isType(app.bsky.graph.starterpack, currentStarterPack.record)) {
|
if (!bsky.isType(app.bsky.graph.starterpack, currentStarterPack.record)) {
|
||||||
throw new Error('Invalid starter pack')
|
throw new Error('Invalid Starter Pack')
|
||||||
}
|
}
|
||||||
|
|
||||||
const removedItems = currentListItems.filter(
|
const removedItems = currentListItems.filter(
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ const syntheticFullView = {
|
|||||||
list: {
|
list: {
|
||||||
uri: 'at://did:plc:abc/app.bsky.graph.list/123',
|
uri: 'at://did:plc:abc/app.bsky.graph.list/123',
|
||||||
cid: '',
|
cid: '',
|
||||||
name: 'Starter pack',
|
name: 'Starter Pack',
|
||||||
purpose: 'app.bsky.graph.defs#referencelist',
|
purpose: 'app.bsky.graph.defs#referencelist',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Type-level assertions for the view alias: it must accept both the basic and
|
* Type-level assertions for the view alias: it must accept both the basic and
|
||||||
* the full starter pack view. Compile-time only - a failure surfaces as a
|
* the full Starter Pack view. Compile-time only - a failure surfaces as a
|
||||||
* typecheck error.
|
* typecheck error.
|
||||||
*/
|
*/
|
||||||
type Assignable<From, To> = From extends To ? true : false
|
type Assignable<From, To> = From extends To ? true : false
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function isView(v: unknown): v is app.bsky.graph.defs.StarterPackView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts both forms of a full starter pack view used by the app:
|
* Accepts both forms of a full Starter Pack view used by the app:
|
||||||
*
|
*
|
||||||
* - direct lexicon refs returned by the app view, where `$type` may be omitted
|
* - direct lexicon refs returned by the app view, where `$type` may be omitted
|
||||||
* - trusted synthetic cache entries, which carry `$type` but may contain
|
* - trusted synthetic cache entries, which carry `$type` but may contain
|
||||||
@@ -39,7 +39,7 @@ export function isTrustedView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches any starter pack view exported by our SDK.
|
* Matches any Starter Pack view exported by our SDK.
|
||||||
*/
|
*/
|
||||||
export type AnyStarterPackView =
|
export type AnyStarterPackView =
|
||||||
app.bsky.graph.defs.StarterPackViewBasic | app.bsky.graph.defs.StarterPackView
|
app.bsky.graph.defs.StarterPackViewBasic | app.bsky.graph.defs.StarterPackView
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
|
|||||||
/*
|
/*
|
||||||
* Back from the login or create-account step. Where it returns depends on how
|
* Back from the login or create-account step. Where it returns depends on how
|
||||||
* the view was entered:
|
* the view was entered:
|
||||||
* - Entered on the splash or a landing screen (starter pack, group chat
|
* - Entered on the splash or a landing screen (Starter Pack, group chat
|
||||||
* invite): return there, i.e. the screen the user actually saw first.
|
* invite): return there, i.e. the screen the user actually saw first.
|
||||||
* - Dropped directly onto login/create-account (e.g. tapping "Create
|
* - Dropped directly onto login/create-account (e.g. tapping "Create
|
||||||
* account" elsewhere in the app): there is no preceding screen in this
|
* account" elsewhere in the app): there is no preceding screen in this
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ let NotificationFeedItem = ({
|
|||||||
* see `src/state/queries/notifications/util.ts`
|
* see `src/state/queries/notifications/util.ts`
|
||||||
*/
|
*/
|
||||||
a11yLabel = starterPackName
|
a11yLabel = starterPackName
|
||||||
? l`${firstAuthorName} followed you back via starter pack ${starterPackName}`
|
? l`${firstAuthorName} followed you back via Starter Pack ${starterPackName}`
|
||||||
: l`${firstAuthorName} followed you back`
|
: l`${firstAuthorName} followed you back`
|
||||||
notificationContent = <Trans>{firstAuthorLink} followed you back</Trans>
|
notificationContent = <Trans>{firstAuthorLink} followed you back</Trans>
|
||||||
} else {
|
} else {
|
||||||
@@ -347,8 +347,8 @@ let NotificationFeedItem = ({
|
|||||||
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
||||||
one: `${formattedAuthorsCount} other`,
|
one: `${formattedAuthorsCount} other`,
|
||||||
other: `${formattedAuthorsCount} others`,
|
other: `${formattedAuthorsCount} others`,
|
||||||
})} followed you via starter pack ${starterPackName}`
|
})} followed you via Starter Pack ${starterPackName}`
|
||||||
: l`${firstAuthorName} followed you via starter pack ${starterPackName}`
|
: l`${firstAuthorName} followed you via Starter Pack ${starterPackName}`
|
||||||
: hasMultipleAuthors
|
: hasMultipleAuthors
|
||||||
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
||||||
one: `${formattedAuthorsCount} other`,
|
one: `${formattedAuthorsCount} other`,
|
||||||
@@ -407,8 +407,8 @@ let NotificationFeedItem = ({
|
|||||||
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
? l`${firstAuthorName} and ${plural(additionalAuthorsCount, {
|
||||||
one: `${formattedAuthorsCount} other`,
|
one: `${formattedAuthorsCount} other`,
|
||||||
other: `${formattedAuthorsCount} others`,
|
other: `${formattedAuthorsCount} others`,
|
||||||
})} signed up with your starter pack`
|
})} signed up with your Starter Pack`
|
||||||
: l`${firstAuthorName} signed up with your starter pack`
|
: l`${firstAuthorName} signed up with your Starter Pack`
|
||||||
notificationContent = hasMultipleAuthors ? (
|
notificationContent = hasMultipleAuthors ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
{firstAuthorLink} and{' '}
|
{firstAuthorLink} and{' '}
|
||||||
@@ -419,10 +419,10 @@ let NotificationFeedItem = ({
|
|||||||
other={`${formattedAuthorsCount} others`}
|
other={`${formattedAuthorsCount} others`}
|
||||||
/>
|
/>
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
signed up with your starter pack
|
signed up with your Starter Pack
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>{firstAuthorLink} signed up with your starter pack</Trans>
|
<Trans>{firstAuthorLink} signed up with your Starter Pack</Trans>
|
||||||
)
|
)
|
||||||
icon = (
|
icon = (
|
||||||
<View style={{height: 30, width: 30}}>
|
<View style={{height: 30, width: 30}}>
|
||||||
@@ -735,8 +735,8 @@ function FollowedViaStarterPack({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={[native(a.pt_xs), t.atoms.text_contrast_medium]}>
|
<Text style={[native(a.pt_xs), t.atoms.text_contrast_medium]}>
|
||||||
<Trans comment="When the source of a follow is a starter pack, i.e., 'via starter pack {starterPackName}'.">
|
<Trans comment="When the source of a follow is a Starter Pack, i.e., 'via Starter Pack {starterPackName}'.">
|
||||||
via starter pack{' '}
|
via Starter Pack{' '}
|
||||||
<StarterPackIcon
|
<StarterPackIcon
|
||||||
size="sm"
|
size="sm"
|
||||||
gradient="sky"
|
gradient="sky"
|
||||||
|
|||||||
@@ -365,10 +365,10 @@ let ProfileMenu = ({
|
|||||||
)}
|
)}
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
testID="profileHeaderDropdownStarterPackAddRemoveBtn"
|
testID="profileHeaderDropdownStarterPackAddRemoveBtn"
|
||||||
label={l`Add to starter packs`}
|
label={l`Add to Starter Packs`}
|
||||||
onPress={onPressAddToStarterPacks}>
|
onPress={onPressAddToStarterPacks}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Add to starter packs</Trans>
|
<Trans>Add to Starter Packs</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
<Menu.ItemIcon icon={StarterPackIcon} />
|
<Menu.ItemIcon icon={StarterPackIcon} />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {Pressable, View} from 'react-native'
|
import {Pressable, View} from 'react-native'
|
||||||
import Animated, {useAnimatedRef} from 'react-native-reanimated'
|
import Animated, {useAnimatedRef} from 'react-native-reanimated'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
@@ -47,7 +45,7 @@ export function ProfileSubpageHeader({
|
|||||||
avatarType: UserAvatarType | 'starter-pack'
|
avatarType: UserAvatarType | 'starter-pack'
|
||||||
}>) {
|
}>) {
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const {isMobile} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
const {openLightbox} = useLightboxControls()
|
const {openLightbox} = useLightboxControls()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
@@ -90,7 +88,6 @@ export function ProfileSubpageHeader({
|
|||||||
<Layout.Header.Content />
|
<Layout.Header.Content />
|
||||||
{children}
|
{children}
|
||||||
</Layout.Header.Outer>
|
</Layout.Header.Outer>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
@@ -105,7 +102,7 @@ export function ProfileSubpageHeader({
|
|||||||
testID="headerAviButton"
|
testID="headerAviButton"
|
||||||
onPress={onPressAvi}
|
onPress={onPressAvi}
|
||||||
accessibilityRole="image"
|
accessibilityRole="image"
|
||||||
accessibilityLabel={_(msg`View the avatar`)}
|
accessibilityLabel={l`View the avatar`}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
style={{width: 58}}>
|
style={{width: 58}}>
|
||||||
{avatarType === 'starter-pack' ? (
|
{avatarType === 'starter-pack' ? (
|
||||||
@@ -166,10 +163,10 @@ export function ProfileSubpageHeader({
|
|||||||
)
|
)
|
||||||
) : purpose === 'app.bsky.graph.defs#referencelist' ? (
|
) : purpose === 'app.bsky.graph.defs#referencelist' ? (
|
||||||
isOwner ? (
|
isOwner ? (
|
||||||
<Trans>Starter pack by you</Trans>
|
<Trans>Starter Pack by you</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>
|
<Trans>
|
||||||
Starter pack by{' '}
|
Starter Pack by{' '}
|
||||||
<TextLink
|
<TextLink
|
||||||
text={sanitizeHandle(creator.handle || '', '@')}
|
text={sanitizeHandle(creator.handle || '', '@')}
|
||||||
href={makeProfileLink(creator)}
|
href={makeProfileLink(creator)}
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ function ProfileScreenLoaded({
|
|||||||
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
const wrappedNavToWizard = requireEmailVerification(navToWizard, {
|
||||||
instructions: [
|
instructions: [
|
||||||
<Trans key="nav">
|
<Trans key="nav">
|
||||||
Before creating a starter pack, you must first verify your email.
|
Before creating a Starter Pack, you must first verify your email.
|
||||||
</Trans>,
|
</Trans>,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user