create simple redirect template for support redirects

This commit is contained in:
Samuel Newman
2026-03-19 13:24:42 +02:00
parent 2a87f6f6b5
commit 46a48df6c9
13 changed files with 214 additions and 276 deletions
+2 -3
View File
@@ -17,7 +17,6 @@ import * as Sentry from '@sentry/react-native'
import {Provider as HideBottomBarBorderProvider} from '#/lib/hooks/useHideBottomBarBorder'
import {QueryProvider} from '#/lib/react-query'
import {s} from '#/lib/styles'
import {ThemeProvider} from '#/lib/ThemeContext'
import {Provider as TranslateOnDeviceProvider} from '#/lib/translation'
import I18nProvider from '#/locale/i18nProvider'
@@ -59,7 +58,7 @@ import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
import {TestCtrls} from '#/view/com/testing/TestCtrls'
import {Shell} from '#/view/shell'
import {ThemeProvider as Alf} from '#/alf'
import {atoms as a, ThemeProvider as Alf} from '#/alf'
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
import {Provider as ContextMenuProvider} from '#/components/ContextMenu'
import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
@@ -176,7 +175,7 @@ function InnerApp() {
<EmailVerificationProvider>
<HideBottomBarBorderProvider>
<GestureHandlerRootView
style={s.h100pct}>
style={a.h_full}>
<GlobalGestureEventsProvider>
<IntentDialogProvider>
<TranslateOnDeviceProvider>
+5 -6
View File
@@ -51,8 +51,6 @@ import {
snoozeEmailConfirmationPrompt,
} from '#/state/shell/reminders'
import {useCloseAllActiveElements} from '#/state/util'
import {CommunityGuidelinesScreen} from '#/view/screens/CommunityGuidelines'
import {CopyrightPolicyScreen} from '#/view/screens/CopyrightPolicy'
import {DebugModScreen} from '#/view/screens/DebugMod'
import {FeedsScreen} from '#/view/screens/Feeds'
import {HomeScreen} from '#/view/screens/Home'
@@ -60,15 +58,11 @@ import {ListsScreen} from '#/view/screens/Lists'
import {ModerationBlockedAccounts} from '#/view/screens/ModerationBlockedAccounts'
import {ModerationModlistsScreen} from '#/view/screens/ModerationModlists'
import {ModerationMutedAccounts} from '#/view/screens/ModerationMutedAccounts'
import {NotFoundScreen} from '#/view/screens/NotFound'
import {NotificationsScreen} from '#/view/screens/Notifications'
import {PostThreadScreen} from '#/view/screens/PostThread'
import {PrivacyPolicyScreen} from '#/view/screens/PrivacyPolicy'
import {ProfileScreen} from '#/view/screens/Profile'
import {ProfileFeedLikedByScreen} from '#/view/screens/ProfileFeedLikedBy'
import {StorybookScreen} from '#/view/screens/Storybook'
import {SupportScreen} from '#/view/screens/Support'
import {TermsOfServiceScreen} from '#/view/screens/TermsOfService'
import {BottomBar} from '#/view/shell/bottom-bar/BottomBar'
import {createNativeStackNavigatorWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth'
import {BookmarksScreen} from '#/screens/Bookmarks'
@@ -130,6 +124,11 @@ import {
StarterPackScreenShort,
} from '#/screens/StarterPack/StarterPackScreen'
import {Wizard} from '#/screens/StarterPack/Wizard'
import {CommunityGuidelinesScreen} from '#/screens/Support/CommunityGuidelines'
import {CopyrightPolicyScreen} from '#/screens/Support/CopyrightPolicy'
import {PrivacyPolicyScreen} from '#/screens/Support/PrivacyPolicy'
import {SupportScreen} from '#/screens/Support/Support'
import {TermsOfServiceScreen} from '#/screens/Support/TermsOfService'
import TopicScreen from '#/screens/Topic'
import {VideoFeed} from '#/screens/VideoFeed'
import {type Theme, useTheme} from '#/alf'
@@ -0,0 +1,22 @@
import {useLingui} from '@lingui/react/macro'
import {urls} from '#/lib/constants'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {RedirectTemplate} from './components/RedirectTemplate'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
'CommunityGuidelines'
>
export const CommunityGuidelinesScreen = (_props: Props) => {
const {t: l} = useLingui()
return (
<RedirectTemplate
title={l`Community Guidelines`}
link={urls.website.support.community}
/>
)
}
+19
View File
@@ -0,0 +1,19 @@
import {useLingui} from '@lingui/react/macro'
import {urls} from '#/lib/constants'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {RedirectTemplate} from './components/RedirectTemplate'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'CopyrightPolicy'>
export const CopyrightPolicyScreen = (_props: Props) => {
const {t: l} = useLingui()
return (
<RedirectTemplate
title={l`Copyright Policy`}
link={urls.website.support.copyright}
/>
)
}
+17
View File
@@ -0,0 +1,17 @@
import {useLingui} from '@lingui/react/macro'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {urls} from '#/lib/constants'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {RedirectTemplate} from './components/RedirectTemplate'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'>
export const PrivacyPolicyScreen = (_props: Props) => {
const {t: l} = useLingui()
return (
<RedirectTemplate
title={l`Privacy Policy`}
link={urls.website.support.privacy}
/>
)
}
+67
View File
@@ -0,0 +1,67 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {HELP_DESK_URL} from '#/lib/constants'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {useSetMinimalShellMode} from '#/state/shell'
import {atoms as a, native, useGutters, useTheme} from '#/alf'
import {ArrowTopRight_Stroke2_Corner0_Rounded as ExternalLinkIcon} from '#/components/icons/Arrow'
import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
import {Text} from '#/components/Typography'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'>
export const SupportScreen = (_props: Props) => {
const setMinimalShellMode = useSetMinimalShellMode()
const gutters = useGutters(['wide', 'base'])
const t = useTheme()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<Layout.Header.Outer>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>
<Trans>Support</Trans>
</Layout.Header.TitleText>
</Layout.Header.Content>
<Layout.Header.Slot />
</Layout.Header.Outer>
<Layout.Content>
<View style={gutters}>
<Text style={[a.text_lg, a.leading_snug]}>
<Trans>
The support form has been moved. If you need help, please visit{' '}
<InlineLinkText
to={HELP_DESK_URL}
label={HELP_DESK_URL}
style={[a.text_lg, a.leading_snug]}>
{HELP_DESK_URL}
<ExternalLinkIcon
size="md"
style={[
{
color: t.palette.primary_500,
verticalAlign: 'middle',
},
native({marginTop: -3}),
]}
/>
</InlineLinkText>{' '}
to get in touch with us.
</Trans>
</Text>
</View>
</Layout.Content>
</Layout.Screen>
)
}
+19
View File
@@ -0,0 +1,19 @@
import {useLingui} from '@lingui/react/macro'
import {urls} from '#/lib/constants'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {RedirectTemplate} from './components/RedirectTemplate'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'TermsOfService'>
export const TermsOfServiceScreen = (_props: Props) => {
const {t: l} = useLingui()
return (
<RedirectTemplate
title={l`Terms of Service`}
link={urls.website.support.tos}
/>
)
}
@@ -0,0 +1,63 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {useSetMinimalShellMode} from '#/state/shell'
import {atoms as a, native, useGutters, useTheme} from '#/alf'
import {ArrowTopRight_Stroke2_Corner0_Rounded as ExternalLinkIcon} from '#/components/icons/Arrow'
import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
import {Text} from '#/components/Typography'
/**
* Generic screen component for redirects.
*/
export function RedirectTemplate({title, link}: {title: string; link: string}) {
const setMinimalShellMode = useSetMinimalShellMode()
const gutters = useGutters(['wide', 'base'])
const t = useTheme()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<Layout.Header.Outer>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>{title}</Layout.Header.TitleText>
</Layout.Header.Content>
<Layout.Header.Slot />
</Layout.Header.Outer>
<Layout.Content>
<View style={gutters}>
<Text style={[a.text_lg, a.leading_snug]}>
<Trans>
The {title} has been moved to{' '}
<InlineLinkText
to={link}
label={link}
style={[a.text_lg, a.leading_snug]}>
{link}
<ExternalLinkIcon
size="md"
style={[
{
color: t.palette.primary_500,
verticalAlign: 'middle',
},
native({marginTop: -3}),
]}
/>
</InlineLinkText>
</Trans>
</Text>
</View>
</Layout.Content>
</Layout.Screen>
)
}
-56
View File
@@ -1,56 +0,0 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
import * as Layout from '#/components/Layout'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
'CommunityGuidelines'
>
export const CommunityGuidelinesScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Community Guidelines`)} />
<ScrollView style={[s.hContentRegion, pal.view]}>
<View style={[s.p20]}>
<Text style={pal.text}>
<Trans>
The Community Guidelines have been moved to{' '}
<TextLink
style={pal.link}
href="https://bsky.social/about/support/community-guidelines"
text="bsky.social/about/support/community-guidelines"
/>
</Trans>
</Text>
</View>
<View style={s.footerSpacer} />
</ScrollView>
</Layout.Screen>
)
}
-53
View File
@@ -1,53 +0,0 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
import * as Layout from '#/components/Layout'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'CopyrightPolicy'>
export const CopyrightPolicyScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Copyright Policy`)} />
<ScrollView style={[s.hContentRegion, pal.view]}>
<View style={[s.p20]}>
<Text style={pal.text}>
<Trans>
The Copyright Policy has been moved to{' '}
<TextLink
style={pal.link}
href="https://bsky.social/about/support/copyright"
text="bsky.social/about/support/copyright"
/>
</Trans>
</Text>
</View>
<View style={s.footerSpacer} />
</ScrollView>
</Layout.Screen>
)
}
-53
View File
@@ -1,53 +0,0 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
import * as Layout from '#/components/Layout'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'>
export const PrivacyPolicyScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Privacy Policy`)} />
<ScrollView style={[s.hContentRegion, pal.view]}>
<View style={[s.p20]}>
<Text style={pal.text}>
<Trans>
The Privacy Policy has been moved to{' '}
<TextLink
style={pal.link}
href="https://bsky.social/about/support/privacy-policy"
text="bsky.social/about/support/privacy-policy"
/>
</Trans>
</Text>
</View>
<View style={s.footerSpacer} />
</ScrollView>
</Layout.Screen>
)
}
-54
View File
@@ -1,54 +0,0 @@
import {useCallback} from 'react'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {HELP_DESK_URL} from '#/lib/constants'
import {usePalette} from '#/lib/hooks/usePalette'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ViewHeader} from '#/view/com/util/ViewHeader'
import {CenteredView} from '#/view/com/util/Views'
import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'>
export const SupportScreen = (_props: Props) => {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Support`)} />
<CenteredView>
<Text type="title-xl" style={[pal.text, s.p20, s.pb5]}>
<Trans>Support</Trans>
</Text>
<Text style={[pal.text, s.p20]}>
<Trans>
The support form has been moved. If you need help, please{' '}
<TextLink
href={HELP_DESK_URL}
text={_(msg`click here`)}
style={pal.link}
/>{' '}
or visit {HELP_DESK_URL} to get in touch with us.
</Trans>
</Text>
</CenteredView>
</Layout.Screen>
)
}
-51
View File
@@ -1,51 +0,0 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
import * as Layout from '#/components/Layout'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'TermsOfService'>
export const TermsOfServiceScreen = (_props: Props) => {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Terms of Service`)} />
<ScrollView style={[s.hContentRegion, pal.view]}>
<View style={[s.p20]}>
<Text style={pal.text}>
<Trans>The Terms of Service have been moved to</Trans>{' '}
<TextLink
style={pal.link}
href="https://bsky.social/about/support/tos"
text="bsky.social/about/support/tos"
/>
</Text>
</View>
<View style={s.footerSpacer} />
</ScrollView>
</Layout.Screen>
)
}