Remove FontAwesome (#10528)

Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
Samuel Newman
2026-05-26 00:29:46 +03:00
committed by GitHub
parent f5dcce1718
commit 98cdeef5b2
19 changed files with 469 additions and 844 deletions
-5
View File
@@ -683,11 +683,6 @@
"count": 1 "count": 1
} }
}, },
"src/view/screens/DebugMod.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 1
}
},
"src/view/shell/createNativeStackNavigatorWithAuth.tsx": { "src/view/shell/createNativeStackNavigatorWithAuth.tsx": {
"@typescript-eslint/no-explicit-any": { "@typescript-eslint/no-explicit-any": {
"count": 1 "count": 1
-4
View File
@@ -17,10 +17,6 @@ jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter', () => {
} }
}) })
jest.mock('@fortawesome/react-native-fontawesome', () => ({
FontAwesomeIcon: '',
}))
jest.mock('react-native-safe-area-context', () => { jest.mock('react-native-safe-area-context', () => {
const inset = {top: 0, right: 0, bottom: 0, left: 0} const inset = {top: 0, right: 0, bottom: 0, left: 0}
return { return {
-4
View File
@@ -116,10 +116,6 @@
"@formatjs/intl-locale": "^4.2.13", "@formatjs/intl-locale": "^4.2.13",
"@formatjs/intl-numberformat": "^8.15.6", "@formatjs/intl-numberformat": "^8.15.6",
"@formatjs/intl-pluralrules": "^5.4.6", "@formatjs/intl-pluralrules": "^5.4.6",
"@fortawesome/fontawesome-svg-core": "^6.1.1",
"@fortawesome/free-regular-svg-icons": "^6.1.1",
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/react-native-fontawesome": "^0.3.2",
"@growthbook/growthbook": "^1.6.5", "@growthbook/growthbook": "^1.6.5",
"@growthbook/growthbook-react": "^1.6.5", "@growthbook/growthbook-react": "^1.6.5",
"@ipld/dag-cbor": "^9.2.7", "@ipld/dag-cbor": "^9.2.7",
-62
View File
@@ -313,18 +313,6 @@ importers:
'@formatjs/intl-pluralrules': '@formatjs/intl-pluralrules':
specifier: ^5.4.6 specifier: ^5.4.6
version: 5.4.6 version: 5.4.6
'@fortawesome/fontawesome-svg-core':
specifier: ^6.1.1
version: 6.7.2
'@fortawesome/free-regular-svg-icons':
specifier: ^6.1.1
version: 6.7.2
'@fortawesome/free-solid-svg-icons':
specifier: ^6.1.1
version: 6.7.2
'@fortawesome/react-native-fontawesome':
specifier: ^0.3.2
version: 0.3.2(@fortawesome/fontawesome-svg-core@6.7.2)(react-native-svg@15.12.1(patch_hash=31401fa6ff01498773afb51a7b066821c471eb3e71b0764a10017938beed49e9)(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))
'@growthbook/growthbook': '@growthbook/growthbook':
specifier: ^1.6.5 specifier: ^1.6.5
version: 1.6.5 version: 1.6.5
@@ -2105,29 +2093,6 @@ packages:
'@formatjs/intl-pluralrules@5.4.6': '@formatjs/intl-pluralrules@5.4.6':
resolution: {integrity: sha512-2HlOq+c7KsSps829SJ3B5987coX5mzKx9NbPcNwQ07eq8FBHgB3HfMoxt5HvLsdk4oQwCjAEnocbtd+wVwZ2Kg==} resolution: {integrity: sha512-2HlOq+c7KsSps829SJ3B5987coX5mzKx9NbPcNwQ07eq8FBHgB3HfMoxt5HvLsdk4oQwCjAEnocbtd+wVwZ2Kg==}
'@fortawesome/fontawesome-common-types@6.7.2':
resolution: {integrity: sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==}
engines: {node: '>=6'}
'@fortawesome/fontawesome-svg-core@6.7.2':
resolution: {integrity: sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==}
engines: {node: '>=6'}
'@fortawesome/free-regular-svg-icons@6.7.2':
resolution: {integrity: sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==}
engines: {node: '>=6'}
'@fortawesome/free-solid-svg-icons@6.7.2':
resolution: {integrity: sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==}
engines: {node: '>=6'}
'@fortawesome/react-native-fontawesome@0.3.2':
resolution: {integrity: sha512-CiWfJWSZHRg12VXlaeFnaa5yJVPOrjsSFEvF6ntz3cnjg4oN3cvauL+JATacMCl0v9xzib32qC1WZAvvGkfB4w==}
peerDependencies:
'@fortawesome/fontawesome-svg-core': ~1 || ~6
react-native: '>= 0.67'
react-native-svg: '>= 11.x'
'@gorhom/portal@1.0.14': '@gorhom/portal@1.0.14':
resolution: {integrity: sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==} resolution: {integrity: sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==}
peerDependencies: peerDependencies:
@@ -6087,9 +6052,6 @@ packages:
resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
engines: {node: '>=14.18.0'} engines: {node: '>=14.18.0'}
humps@2.0.1:
resolution: {integrity: sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==}
husky@9.1.7: husky@9.1.7:
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -11144,28 +11106,6 @@ snapshots:
decimal.js: 10.6.0 decimal.js: 10.6.0
tslib: 2.8.1 tslib: 2.8.1
'@fortawesome/fontawesome-common-types@6.7.2': {}
'@fortawesome/fontawesome-svg-core@6.7.2':
dependencies:
'@fortawesome/fontawesome-common-types': 6.7.2
'@fortawesome/free-regular-svg-icons@6.7.2':
dependencies:
'@fortawesome/fontawesome-common-types': 6.7.2
'@fortawesome/free-solid-svg-icons@6.7.2':
dependencies:
'@fortawesome/fontawesome-common-types': 6.7.2
'@fortawesome/react-native-fontawesome@0.3.2(@fortawesome/fontawesome-svg-core@6.7.2)(react-native-svg@15.12.1(patch_hash=31401fa6ff01498773afb51a7b066821c471eb3e71b0764a10017938beed49e9)(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))':
dependencies:
'@fortawesome/fontawesome-svg-core': 6.7.2
humps: 2.0.1
prop-types: 15.8.1
react-native: 0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0)
react-native-svg: 15.12.1(patch_hash=31401fa6ff01498773afb51a7b066821c471eb3e71b0764a10017938beed49e9)(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
'@gorhom/portal@1.0.14(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)': '@gorhom/portal@1.0.14(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
nanoid: 3.3.12 nanoid: 3.3.12
@@ -15769,8 +15709,6 @@ snapshots:
human-signals@4.3.1: {} human-signals@4.3.1: {}
humps@2.0.1: {}
husky@9.1.7: {} husky@9.1.7: {}
hyphenate-style-name@1.1.0: {} hyphenate-style-name@1.1.0: {}
-1
View File
@@ -1,5 +1,4 @@
import '#/logger/sentry/setup' import '#/logger/sentry/setup'
import '#/view/icons'
import {Fragment, useEffect, useState} from 'react' import {Fragment, useEffect, useState} from 'react'
import {GestureHandlerRootView} from 'react-native-gesture-handler' import {GestureHandlerRootView} from 'react-native-gesture-handler'
-1
View File
@@ -1,5 +1,4 @@
import '#/logger/sentry/setup' // must be near top import '#/logger/sentry/setup' // must be near top
import '#/view/icons'
import './style.css' import './style.css'
import {Fragment, useEffect, useState} from 'react' import {Fragment, useEffect, useState} from 'react'
@@ -7,7 +7,6 @@ import {
AtUri, AtUri,
type ModerationOpts, type ModerationOpts,
} from '@atproto/api' } from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro' import {Trans} from '@lingui/react/macro'
@@ -29,6 +28,7 @@ import {Button, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
import * as FeedCard from '#/components/FeedCard' import * as FeedCard from '#/components/FeedCard'
import {useRichText} from '#/components/hooks/useRichText' import {useRichText} from '#/components/hooks/useRichText'
import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/icons/Trending'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {LinearGradientBackground} from '#/components/LinearGradientBackground' import {LinearGradientBackground} from '#/components/LinearGradientBackground'
import {ListMaybePlaceholder} from '#/components/Lists' import {ListMaybePlaceholder} from '#/components/Lists'
@@ -209,18 +209,16 @@ function LandingScreenLoaded({
<Button <Button
label={_(msg`Join Bluesky`)} label={_(msg`Join Bluesky`)}
onPress={onJoinPress} onPress={onJoinPress}
variant="solid"
color="primary" color="primary"
size="large"> size="large">
<ButtonText style={[a.text_lg]}> <ButtonText style={[a.text_lg]}>
<Trans>Join Bluesky</Trans> <Trans>Join Bluesky</Trans>
</ButtonText> </ButtonText>
</Button> </Button>
<View style={[a.flex_row, a.align_center, a.gap_sm]}> <View style={[a.flex_row, a.align_center, a.gap_xs]}>
<FontAwesomeIcon <TrendingIcon
icon="arrow-trend-up" width={16}
size={12} style={{color: t.atoms.text_contrast_medium.color}}
color={t.atoms.text_contrast_medium.color}
/> />
<Text <Text
style={[ style={[
@@ -8,7 +8,6 @@ import {
type ModerationOpts, type ModerationOpts,
RichText as RichTextAPI, RichText as RichTextAPI,
} from '@atproto/api' } from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Plural, Trans} from '@lingui/react/macro' import {Plural, Trans} from '@lingui/react/macro'
@@ -58,6 +57,7 @@ import {DotGrid3x1_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons
import {ListSparkle_Stroke2_Corner0_Rounded as ListSparkle} from '#/components/icons/ListSparkle' import {ListSparkle_Stroke2_Corner0_Rounded as ListSparkle} from '#/components/icons/ListSparkle'
import {Pencil_Stroke2_Corner0_Rounded as Pencil} from '#/components/icons/Pencil' import {Pencil_Stroke2_Corner0_Rounded as Pencil} from '#/components/icons/Pencil'
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash' import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/icons/Trending'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {ListMaybePlaceholder} from '#/components/Lists' import {ListMaybePlaceholder} from '#/components/Lists'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
@@ -482,7 +482,6 @@ function Header({
}) })
requestSwitchToAccount({requestedAccount: 'new'}) requestSwitchToAccount({requestedAccount: 'new'})
}} }}
variant="solid"
color="primary" color="primary"
size="large"> size="large">
<ButtonText style={[a.text_lg]}> <ButtonText style={[a.text_lg]}>
@@ -491,11 +490,10 @@ function Header({
</Button> </Button>
) : null} ) : null}
{joinedAllTimeCount >= 25 ? ( {joinedAllTimeCount >= 25 ? (
<View style={[a.flex_row, a.align_center, a.gap_sm]}> <View style={[a.flex_row, a.align_center, a.gap_xs]}>
<FontAwesomeIcon <TrendingIcon
icon="arrow-trend-up" width={16}
size={12} style={{color: t.atoms.text_contrast_medium.color}}
color={t.atoms.text_contrast_medium.color}
/> />
<Text <Text
style={[ style={[
+2 -8
View File
@@ -1,6 +1,5 @@
import {useEffect, useState} from 'react' import {useEffect, useState} from 'react'
import {Pressable, View} from 'react-native' import {Pressable, View} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro' import {Trans} from '@lingui/react/macro'
@@ -17,6 +16,7 @@ import {
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {AppLanguageDropdown} from '#/components/AppLanguageDropdown' import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {TimesLarge_Stroke2_Corner0_Rounded as TimesIcon} from '#/components/icons/Times'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link' import {InlineLinkText} from '#/components/Link'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
@@ -61,13 +61,7 @@ export const SplashScreen = ({
zIndex: 100, zIndex: 100,
}} }}
onPress={onDismiss}> onPress={onDismiss}>
<FontAwesomeIcon <TimesIcon width={24} style={t.atoms.text} />
icon="x"
size={24}
style={{
color: String(t.atoms.text.color),
}}
/>
</Pressable> </Pressable>
)} )}
+8 -17
View File
@@ -11,7 +11,6 @@ import {
type ViewStyle, type ViewStyle,
} from 'react-native' } from 'react-native'
import {Image} from 'expo-image' import {Image} from 'expo-image'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro' import {Trans} from '@lingui/react/macro'
@@ -23,6 +22,10 @@ import {type ComposerImage, cropImage} from '#/state/gallery'
import {atoms as a, tokens, useTheme} from '#/alf' import {atoms as a, tokens, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition' import {Admonition} from '#/components/Admonition'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check'
import {Pencil_Stroke2_Corner0_Rounded as PencilIcon} from '#/components/icons/Pencil'
import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus'
import {TimesLarge_Stroke2_Corner0_Rounded as TimesIcon} from '#/components/icons/Times'
import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {MediaInsetBorder} from '#/components/MediaInsetBorder'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
@@ -198,17 +201,9 @@ const GalleryItem = ({
onPress={onAltTextEdit} onPress={onAltTextEdit}
style={[styles.altTextControl, altTextControlStyle]}> style={[styles.altTextControl, altTextControlStyle]}>
{image.alt.length !== 0 ? ( {image.alt.length !== 0 ? (
<FontAwesomeIcon <CheckIcon width={10} style={{color: t.palette.white}} />
icon="check"
size={10}
style={{color: t.palette.white}}
/>
) : ( ) : (
<FontAwesomeIcon <PlusIcon width={10} style={{color: t.palette.white}} />
icon="plus"
size={10}
style={{color: t.palette.white}}
/>
)} )}
<Text style={styles.altTextControlLabel} accessible={false}> <Text style={styles.altTextControlLabel} accessible={false}>
<Trans>ALT</Trans> <Trans>ALT</Trans>
@@ -222,7 +217,7 @@ const GalleryItem = ({
accessibilityHint="" accessibilityHint=""
onPress={onImageEdit} onPress={onImageEdit}
style={styles.imageControl}> style={styles.imageControl}>
<FontAwesomeIcon icon="pen" size={12} style={{color: colors.white}} /> <PencilIcon width={12} style={{color: colors.white}} />
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity <TouchableOpacity
testID="removePhotoButton" testID="removePhotoButton"
@@ -231,11 +226,7 @@ const GalleryItem = ({
accessibilityHint="" accessibilityHint=""
onPress={onRemove} onPress={onRemove}
style={styles.imageControl}> style={styles.imageControl}>
<FontAwesomeIcon <TimesIcon width={16} style={{color: colors.white}} />
icon="xmark"
size={16}
style={{color: colors.white}}
/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<TouchableOpacity <TouchableOpacity
+17 -38
View File
@@ -1,10 +1,6 @@
import {useCallback, useEffect, useRef} from 'react' import {useCallback, useEffect, useRef} from 'react'
import {StyleSheet, View} from 'react-native' import {StyleSheet, View} from 'react-native'
import { import {Trans, useLingui} from '@lingui/react/macro'
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {Trans} from '@lingui/react/macro'
import {useNavigation} from '@react-navigation/native' import {useNavigation} from '@react-navigation/native'
import {DISCOVER_FEED_URI} from '#/lib/constants' import {DISCOVER_FEED_URI} from '#/lib/constants'
@@ -14,9 +10,11 @@ import {type NavigationProp} from '#/lib/routes/types'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {useFeedFeedbackContext} from '#/state/feed-feedback' import {useFeedFeedbackContext} from '#/state/feed-feedback'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import {IS_WEB} from '#/env' import {IS_WEB} from '#/env'
import {Button} from '../util/forms/Button'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
export function CustomFeedEmptyState() { export function CustomFeedEmptyState() {
@@ -40,8 +38,8 @@ export function CustomFeedEmptyState() {
} }
} }
}, [feedFeedback.feedSourceInfo, currentAccount?.did]) }, [feedFeedback.feedSourceInfo, currentAccount?.did])
const {t: l} = useLingui()
const pal = usePalette('default') const pal = usePalette('default')
const palInverted = usePalette('inverted')
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const onPressFindAccounts = useCallback(() => { const onPressFindAccounts = useCallback(() => {
@@ -64,19 +62,18 @@ export function CustomFeedEmptyState() {
language settings. language settings.
</Trans> </Trans>
</Text> </Text>
<Button <View style={[a.mt_xl, a.align_center]}>
type="inverted" <Button
style={styles.emptyBtn} label={l`Find accounts to follow`}
onPress={onPressFindAccounts}> onPress={onPressFindAccounts}
<Text type="lg-medium" style={palInverted.text}> color="secondary_inverted"
<Trans>Find accounts to follow</Trans> size="large">
</Text> <ButtonText>
<FontAwesomeIcon <Trans>Find accounts to follow</Trans>
icon="angle-right" </ButtonText>
style={palInverted.text as FontAwesomeIconStyle} <ButtonIcon icon={ChevronRightIcon} />
size={14} </Button>
/> </View>
</Button>
</View> </View>
) )
} }
@@ -93,22 +90,4 @@ const styles = StyleSheet.create({
marginLeft: 'auto', marginLeft: 'auto',
marginRight: 'auto', marginRight: 'auto',
}, },
emptyBtn: {
marginVertical: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 18,
paddingHorizontal: 24,
borderRadius: 30,
},
feedsTip: {
position: 'absolute',
left: 22,
},
feedsTipArrow: {
marginLeft: 32,
marginTop: 8,
},
}) })
+29 -42
View File
@@ -1,23 +1,21 @@
import {useCallback} from 'react' import {useCallback} from 'react'
import {StyleSheet, View} from 'react-native' import {StyleSheet, View} from 'react-native'
import { import {Trans, useLingui} from '@lingui/react/macro'
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
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'
import {MagnifyingGlassIcon} from '#/lib/icons' import {MagnifyingGlassIcon} from '#/lib/icons'
import {type NavigationProp} from '#/lib/routes/types' import {type NavigationProp} from '#/lib/routes/types'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {IS_WEB} from '#/env' import {IS_WEB} from '#/env'
import {Button} from '../util/forms/Button'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
export function FollowingEmptyState() { export function FollowingEmptyState() {
const {t: l} = useLingui()
const pal = usePalette('default') const pal = usePalette('default')
const palInverted = usePalette('inverted')
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const onPressFindAccounts = useCallback(() => { const onPressFindAccounts = useCallback(() => {
@@ -45,36 +43,34 @@ export function FollowingEmptyState() {
happening. happening.
</Trans> </Trans>
</Text> </Text>
<Button <View style={[a.mt_xl, a.align_center]}>
type="inverted" <Button
style={styles.emptyBtn} label={l`Find accounts to follow`}
onPress={onPressFindAccounts}> onPress={onPressFindAccounts}
<Text type="lg-medium" style={palInverted.text}> color="secondary_inverted"
<Trans>Find accounts to follow</Trans> size="large">
</Text> <ButtonText>
<FontAwesomeIcon <Trans>Find accounts to follow</Trans>
icon="angle-right" </ButtonText>
style={palInverted.text as FontAwesomeIconStyle} <ButtonIcon icon={ChevronRightIcon} />
size={14} </Button>
/> </View>
</Button>
<Text type="xl-medium" style={[s.textCenter, pal.text, s.mt20]}> <Text type="xl-medium" style={[s.textCenter, pal.text, s.mt20]}>
<Trans>You can also discover new Custom Feeds to follow.</Trans> <Trans>You can also discover new Custom Feeds to follow.</Trans>
</Text> </Text>
<Button <View style={[a.mt_md, a.align_center]}>
type="inverted" <Button
style={[styles.emptyBtn, s.mt10]} label={l`Discover new custom feeds`}
onPress={onPressDiscoverFeeds}> onPress={onPressDiscoverFeeds}
<Text type="lg-medium" style={palInverted.text}> color="secondary_inverted"
<Trans>Discover new custom feeds</Trans> size="large">
</Text> <ButtonText>
<FontAwesomeIcon <Trans>Discover new custom feeds</Trans>
icon="angle-right" </ButtonText>
style={palInverted.text as FontAwesomeIconStyle} <ButtonIcon icon={ChevronRightIcon} />
size={14} </Button>
/> </View>
</Button>
</View> </View>
</View> </View>
) )
@@ -98,13 +94,4 @@ const styles = StyleSheet.create({
marginLeft: 'auto', marginLeft: 'auto',
marginRight: 'auto', marginRight: 'auto',
}, },
emptyBtn: {
marginVertical: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 18,
paddingHorizontal: 24,
borderRadius: 30,
},
}) })
+29 -42
View File
@@ -1,22 +1,20 @@
import {useCallback} from 'react' import {useCallback} from 'react'
import {Dimensions, StyleSheet, View} from 'react-native' import {Dimensions, StyleSheet, View} from 'react-native'
import { import {Trans, useLingui} from '@lingui/react/macro'
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
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'
import {type NavigationProp} from '#/lib/routes/types' import {type NavigationProp} from '#/lib/routes/types'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {IS_WEB} from '#/env' import {IS_WEB} from '#/env'
import {Button} from '../util/forms/Button'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
export function FollowingEndOfFeed() { export function FollowingEndOfFeed() {
const {t: l} = useLingui()
const pal = usePalette('default') const pal = usePalette('default')
const palInverted = usePalette('inverted')
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const onPressFindAccounts = useCallback(() => { const onPressFindAccounts = useCallback(() => {
@@ -46,36 +44,34 @@ export function FollowingEndOfFeed() {
follow. follow.
</Trans> </Trans>
</Text> </Text>
<Button <View style={[a.mt_xl, a.align_center]}>
type="inverted" <Button
style={styles.emptyBtn} label={l`Find accounts to follow`}
onPress={onPressFindAccounts}> onPress={onPressFindAccounts}
<Text type="lg-medium" style={palInverted.text}> color="secondary_inverted"
<Trans>Find accounts to follow</Trans> size="large">
</Text> <ButtonText>
<FontAwesomeIcon <Trans>Find accounts to follow</Trans>
icon="angle-right" </ButtonText>
style={palInverted.text as FontAwesomeIconStyle} <ButtonIcon icon={ChevronRightIcon} />
size={14} </Button>
/> </View>
</Button>
<Text type="xl-medium" style={[s.textCenter, pal.text, s.mt20]}> <Text type="xl-medium" style={[s.textCenter, pal.text, s.mt20]}>
<Trans>You can also discover new Custom Feeds to follow.</Trans> <Trans>You can also discover new Custom Feeds to follow.</Trans>
</Text> </Text>
<Button <View style={[a.mt_md, a.align_center]}>
type="inverted" <Button
style={[styles.emptyBtn, s.mt10]} label={l`Discover new custom feeds`}
onPress={onPressDiscoverFeeds}> onPress={onPressDiscoverFeeds}
<Text type="lg-medium" style={palInverted.text}> color="secondary_inverted"
<Trans>Discover new custom feeds</Trans> size="large">
</Text> <ButtonText>
<FontAwesomeIcon <Trans>Discover new custom feeds</Trans>
icon="angle-right" </ButtonText>
style={palInverted.text as FontAwesomeIconStyle} <ButtonIcon icon={ChevronRightIcon} />
size={14} </Button>
/> </View>
</Button>
</View> </View>
</View> </View>
) )
@@ -93,13 +89,4 @@ const styles = StyleSheet.create({
width: '100%', width: '100%',
maxWidth: 460, maxWidth: 460,
}, },
emptyBtn: {
marginVertical: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 18,
paddingHorizontal: 24,
borderRadius: 30,
},
}) })
+2 -9
View File
@@ -1,10 +1,7 @@
import {StyleSheet} from 'react-native' import {StyleSheet} from 'react-native'
import {
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateIcon} from '#/components/icons/ArrowRotate'
import {Button} from './forms/Button' import {Button} from './forms/Button'
import {Text} from './text/Text' import {Text} from './text/Text'
@@ -18,11 +15,7 @@ export function LoadMoreRetryBtn({
const pal = usePalette('default') const pal = usePalette('default')
return ( return (
<Button type="default-light" onPress={onPress} style={styles.loadMoreRetry}> <Button type="default-light" onPress={onPress} style={styles.loadMoreRetry}>
<FontAwesomeIcon <ArrowRotateIcon width={18} style={pal.textLight} />
icon="arrow-rotate-left"
style={pal.textLight as FontAwesomeIconStyle}
size={18}
/>
<Text style={[pal.textLight, styles.label]}>{label}</Text> <Text style={[pal.textLight, styles.label]}>{label}</Text>
</Button> </Button>
) )
+21 -7
View File
@@ -5,13 +5,13 @@ import {
Pressable, Pressable,
type StyleProp, type StyleProp,
StyleSheet, StyleSheet,
Text as RNText,
View, View,
type ViewStyle, type ViewStyle,
} from 'react-native' } from 'react-native'
import Svg, {Circle, Path, Rect} from 'react-native-svg' import Svg, {Circle, Path, Rect} from 'react-native-svg'
import {Image as ExpoImage} from 'expo-image' import {Image as ExpoImage} from 'expo-image'
import {type ModerationUI} from '@atproto/api' import {type ModerationUI} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro' import {Trans} from '@lingui/react/macro'
@@ -270,13 +270,27 @@ let UserAvatar = ({
a.right_0, a.right_0,
a.bottom_0, a.bottom_0,
a.rounded_full, a.rounded_full,
{backgroundColor: t.palette.white}, {width: 16, height: 16},
a.align_center,
a.justify_center,
{backgroundColor: t.palette.pink},
{transform: [{scale: size / 42}]},
]}> ]}>
<FontAwesomeIcon <RNText
icon="exclamation-circle" style={[
style={{color: t.palette.negative_400}} a.text_sm,
size={Math.floor(size / 3)} a.font_bold,
/> a.text_center,
{
color: t.palette.white,
includeFontPadding: false,
textAlignVertical: 'center',
},
]}
minimumFontScale={1}
maxFontSizeMultiplier={1}>
!
</RNText>
</View> </View>
) )
}, [moderation?.alert, size, t]) }, [moderation?.alert, size, t])
+41 -71
View File
@@ -1,21 +1,12 @@
import { import {type StyleProp, View, type ViewStyle} from 'react-native'
type StyleProp, import {useLingui} from '@lingui/react/macro'
StyleSheet,
TouchableOpacity,
View,
type ViewStyle,
} from 'react-native'
import {
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {usePalette} from '#/lib/hooks/usePalette' import {atoms as a, useGutters, useTheme, utils} from '#/alf'
import {useTheme} from '#/lib/ThemeContext' import {Button} from '#/components/Button'
import {ArrowRotateClockwise_Stroke2_Corner0_Rounded as ArrowRotateIcon} from '#/components/icons/ArrowRotate'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {Text} from '../text/Text' import {Text} from '#/components/Typography'
export function ErrorMessage({ export function ErrorMessage({
message, message,
@@ -28,72 +19,51 @@ export function ErrorMessage({
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
onPressTryAgain?: () => void onPressTryAgain?: () => void
}) { }) {
const theme = useTheme() const {t: l} = useLingui()
const pal = usePalette('error') const t = useTheme()
const {_} = useLingui() const gutter = useGutters(['base'])
return ( return (
<Layout.Center> <Layout.Center>
<View testID="errorMessageView" style={[styles.outer, pal.view, style]}> <View
<View testID="errorMessageView"
style={[ style={[
styles.errorIcon, a.flex_row,
{backgroundColor: theme.palette.error.icon}, a.align_center,
]}> gutter,
<FontAwesomeIcon a.py_sm,
icon="exclamation" {backgroundColor: t.palette.pink},
style={pal.text as FontAwesomeIconStyle} a.gap_md,
size={16} style,
/> ]}>
</View> <WarningIcon size="md" fill={t.palette.white} />
<Text <Text
type="sm-medium" style={[
style={[styles.message, pal.text]} a.flex_1,
a.font_medium,
a.leading_snug,
a.text_md,
{color: t.palette.white},
]}
numberOfLines={numberOfLines}> numberOfLines={numberOfLines}>
{message} {message}
</Text> </Text>
{onPressTryAgain && ( {onPressTryAgain && (
<TouchableOpacity <Button
testID="errorMessageTryAgainButton" testID="errorMessageTryAgainButton"
style={styles.btn}
onPress={onPressTryAgain} onPress={onPressTryAgain}
accessibilityRole="button" label={l`Retry`}
accessibilityLabel={_(msg`Retry`)} accessibilityHint={l`Retries the last action, which errored out`}
accessibilityHint={_( size="small"
msg`Retries the last action, which errored out`, shape="round"
)}> variant="ghost"
<FontAwesomeIcon hoverStyle={{
icon="arrows-rotate" backgroundColor: utils.alpha(t.palette.white, 0.2),
style={{color: theme.palette.error.icon}} }}>
size={18} <ArrowRotateIcon size="md" fill={t.palette.white} />
/> </Button>
</TouchableOpacity>
)} )}
</View> </View>
</Layout.Center> </Layout.Center>
) )
} }
const styles = StyleSheet.create({
outer: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 8,
paddingHorizontal: 8,
},
errorIcon: {
borderRadius: 12,
width: 24,
height: 24,
alignItems: 'center',
justifyContent: 'center',
marginRight: 8,
},
message: {
flex: 1,
paddingRight: 10,
},
btn: {
paddingHorizontal: 4,
paddingVertical: 4,
},
})
+2 -9
View File
@@ -1,8 +1,4 @@
import {View} from 'react-native' import {View} from 'react-native'
import {
FontAwesomeIcon,
type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro' import {Trans} from '@lingui/react/macro'
@@ -11,6 +7,7 @@ import {usePalette} from '#/lib/hooks/usePalette'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateCounterClockwiseIcon} from '#/components/icons/ArrowRotate' import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateCounterClockwiseIcon} from '#/components/icons/ArrowRotate'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
@@ -56,11 +53,7 @@ export function ErrorScreen({
a.justify_center, a.justify_center,
{backgroundColor: t.palette.contrast_950}, {backgroundColor: t.palette.contrast_950},
]}> ]}>
<FontAwesomeIcon <WarningIcon width={24} style={pal.textInverted} />
icon="exclamation"
style={pal.textInverted as FontAwesomeIconStyle}
size={24}
/>
</View> </View>
</View> </View>
<Text style={[a.text_center, a.font_bold, a.text_2xl, a.mb_md]}> <Text style={[a.text_center, a.font_bold, a.text_2xl, a.mb_md]}>
-220
View File
@@ -1,220 +0,0 @@
import {library} from '@fortawesome/fontawesome-svg-core'
import {faAddressCard} from '@fortawesome/free-regular-svg-icons/faAddressCard'
import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
import {faCalendar as farCalendar} from '@fortawesome/free-regular-svg-icons/faCalendar'
import {faCircle} from '@fortawesome/free-regular-svg-icons/faCircle'
import {faCircleCheck as farCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck'
import {faCirclePlay} from '@fortawesome/free-regular-svg-icons/faCirclePlay'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone as farClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
import {faCommentDots} from '@fortawesome/free-regular-svg-icons/faCommentDots'
import {faComments} from '@fortawesome/free-regular-svg-icons/faComments'
import {faCompass} from '@fortawesome/free-regular-svg-icons/faCompass'
import {faEyeSlash as farEyeSlash} from '@fortawesome/free-regular-svg-icons/faEyeSlash'
import {faFaceSmile} from '@fortawesome/free-regular-svg-icons/faFaceSmile'
import {faFloppyDisk} from '@fortawesome/free-regular-svg-icons/faFloppyDisk'
import {faHand as farHand} from '@fortawesome/free-regular-svg-icons/faHand'
import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
import {faImage as farImage} from '@fortawesome/free-regular-svg-icons/faImage'
import {faMessage} from '@fortawesome/free-regular-svg-icons/faMessage'
import {faPaste} from '@fortawesome/free-regular-svg-icons/faPaste'
import {faSquare} from '@fortawesome/free-regular-svg-icons/faSquare'
import {faSquareCheck} from '@fortawesome/free-regular-svg-icons/faSquareCheck'
import {faSquarePlus} from '@fortawesome/free-regular-svg-icons/faSquarePlus'
import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan'
import {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown'
import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight'
import {faAngleUp} from '@fortawesome/free-solid-svg-icons/faAngleUp'
import {faArrowDown} from '@fortawesome/free-solid-svg-icons/faArrowDown'
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft'
import {faArrowRight} from '@fortawesome/free-solid-svg-icons/faArrowRight'
import {faArrowRightFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowRightFromBracket'
import {faArrowRotateLeft} from '@fortawesome/free-solid-svg-icons/faArrowRotateLeft'
import {faArrowsRotate} from '@fortawesome/free-solid-svg-icons/faArrowsRotate'
import {faArrowTrendUp} from '@fortawesome/free-solid-svg-icons/faArrowTrendUp'
import {faArrowUp} from '@fortawesome/free-solid-svg-icons/faArrowUp'
import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket'
import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare'
import {faAt} from '@fortawesome/free-solid-svg-icons/faAt'
import {faBan} from '@fortawesome/free-solid-svg-icons/faBan'
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark'
import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera'
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown'
import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight'
import {faCircleCheck} from '@fortawesome/free-solid-svg-icons/faCircleCheck'
import {faCircleDot} from '@fortawesome/free-solid-svg-icons/faCircleDot'
import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation'
import {faClipboardCheck} from '@fortawesome/free-solid-svg-icons/faClipboardCheck'
import {faClone} from '@fortawesome/free-solid-svg-icons/faClone'
import {faCommentSlash} from '@fortawesome/free-solid-svg-icons/faCommentSlash'
import {faDownload} from '@fortawesome/free-solid-svg-icons/faDownload'
import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis'
import {faEnvelope} from '@fortawesome/free-solid-svg-icons/faEnvelope'
import {faExclamation} from '@fortawesome/free-solid-svg-icons/faExclamation'
import {faEye} from '@fortawesome/free-solid-svg-icons/faEye'
import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter'
import {faFire} from '@fortawesome/free-solid-svg-icons/faFire'
import {faFlask} from '@fortawesome/free-solid-svg-icons/faFlask'
import {faGear} from '@fortawesome/free-solid-svg-icons/faGear'
import {faGlobe} from '@fortawesome/free-solid-svg-icons/faGlobe'
import {faHand} from '@fortawesome/free-solid-svg-icons/faHand'
import {faHashtag} from '@fortawesome/free-solid-svg-icons/faHashtag'
import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
import {faHouse} from '@fortawesome/free-solid-svg-icons/faHouse'
import {faImage} from '@fortawesome/free-solid-svg-icons/faImage'
import {faInfo} from '@fortawesome/free-solid-svg-icons/faInfo'
import {faLanguage} from '@fortawesome/free-solid-svg-icons/faLanguage'
import {faLink} from '@fortawesome/free-solid-svg-icons/faLink'
import {faList} from '@fortawesome/free-solid-svg-icons/faList'
import {faListUl} from '@fortawesome/free-solid-svg-icons/faListUl'
import {faLock} from '@fortawesome/free-solid-svg-icons/faLock'
import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass'
import {faNoteSticky} from '@fortawesome/free-solid-svg-icons/faNoteSticky'
import {faPaintRoller} from '@fortawesome/free-solid-svg-icons/faPaintRoller'
import {faPause} from '@fortawesome/free-solid-svg-icons/faPause'
import {faPen} from '@fortawesome/free-solid-svg-icons/faPen'
import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib'
import {faPenToSquare} from '@fortawesome/free-solid-svg-icons/faPenToSquare'
import {faPhone} from '@fortawesome/free-solid-svg-icons/faPhone'
import {faPlay} from '@fortawesome/free-solid-svg-icons/faPlay'
import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus'
import {faQuoteLeft} from '@fortawesome/free-solid-svg-icons/faQuoteLeft'
import {faReply} from '@fortawesome/free-solid-svg-icons/faReply'
import {faRetweet} from '@fortawesome/free-solid-svg-icons/faRetweet'
import {faRss} from '@fortawesome/free-solid-svg-icons/faRss'
import {faSatelliteDish} from '@fortawesome/free-solid-svg-icons/faSatelliteDish'
import {faServer} from '@fortawesome/free-solid-svg-icons/faServer'
import {faShare} from '@fortawesome/free-solid-svg-icons/faShare'
import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare'
import {faShield} from '@fortawesome/free-solid-svg-icons/faShield'
import {faSignal} from '@fortawesome/free-solid-svg-icons/faSignal'
import {faSliders} from '@fortawesome/free-solid-svg-icons/faSliders'
import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack'
import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket'
import {faUniversalAccess} from '@fortawesome/free-solid-svg-icons/faUniversalAccess'
import {faUserCheck} from '@fortawesome/free-solid-svg-icons/faUserCheck'
import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus'
import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers'
import {faUserSlash} from '@fortawesome/free-solid-svg-icons/faUserSlash'
import {faUsersSlash} from '@fortawesome/free-solid-svg-icons/faUsersSlash'
import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark'
import {faX} from '@fortawesome/free-solid-svg-icons/faX'
import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark'
library.add(
faAddressCard,
faAngleDown,
faAngleLeft,
faAngleRight,
faAngleUp,
faArrowLeft,
faArrowRight,
faArrowUp,
faArrowDown,
faArrowRightFromBracket,
faArrowUpFromBracket,
faArrowUpRightFromSquare,
faArrowRotateLeft,
faArrowTrendUp,
faArrowsRotate,
faAt,
faBan,
faBars,
faBell,
farBell,
faBookmark,
farBookmark,
farCalendar,
faCamera,
faCheck,
faChevronRight,
faCircle,
faCircleCheck,
farCircleCheck,
faCircleDot,
faCircleExclamation,
faCirclePlay,
faCircleUser,
faClipboardCheck,
faClone,
farClone,
faComment,
faCommentDots,
faCommentSlash,
faComments,
faCompass,
faDownload,
faEllipsis,
faEnvelope,
faEye,
faExclamation,
farEyeSlash,
faFaceSmile,
faFire,
faFlask,
faFloppyDisk,
faGear,
faGlobe,
faHand,
farHand,
faHashtag,
faHeart,
fasHeart,
faHouse,
faImage,
farImage,
faInfo,
faLanguage,
faLink,
faList,
faListUl,
faLock,
faMagnifyingGlass,
faMessage,
faNoteSticky,
faPaintRoller,
faPaste,
faPause,
faPen,
faPenNib,
faPenToSquare,
faPhone,
faPlay,
faPlus,
faQuoteLeft,
faReply,
faRetweet,
faRss,
faSatelliteDish,
faServer,
faShare,
faShareFromSquare,
faShield,
faSignal,
faSliders,
faSquare,
faSquareCheck,
faSquarePlus,
faUniversalAccess,
faUser,
faUsers,
faUserCheck,
faUserSlash,
faUserPlus,
faUserXmark,
faUsersSlash,
faThumbtack,
faTicket,
faTrashCan,
faX,
faXmark,
faChevronDown,
faFilter,
)
+308 -290
View File
@@ -1,5 +1,6 @@
import {useMemo, useState} from 'react' import {useMemo, useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useSharedValue} from 'react-native-reanimated'
import { import {
type AppBskyActorDefs, type AppBskyActorDefs,
type AppBskyFeedDefs, type AppBskyFeedDefs,
@@ -54,6 +55,7 @@ import * as ProfileCard from '#/components/ProfileCard'
import {H1, H3, P, Text} from '#/components/Typography' import {H1, H3, P, Text} from '#/components/Typography'
import {ScreenHider} from '../../components/moderation/ScreenHider' import {ScreenHider} from '../../components/moderation/ScreenHider'
import {NotificationFeedItem} from '../com/notifications/NotificationFeedItem' import {NotificationFeedItem} from '../com/notifications/NotificationFeedItem'
import {PagerHeaderProvider} from '../com/pager/PagerHeaderContext'
import {PostFeedItem} from '../com/posts/PostFeedItem' import {PostFeedItem} from '../com/posts/PostFeedItem'
const LABEL_VALUES: (keyof typeof LABELS)[] = Object.keys( const LABEL_VALUES: (keyof typeof LABELS)[] = Object.keys(
@@ -272,325 +274,341 @@ export const DebugModScreen = ({}: NativeStackScreenProps<
return moderatePost(post, modOpts) return moderatePost(post, modOpts)
}, [post, modOpts]) }, [post, modOpts])
const sv = useSharedValue(0)
return ( return (
<Layout.Screen> <Layout.Screen>
<moderationOptsOverrideContext.Provider value={modOpts}> <PagerHeaderProvider headerHeight={0} scrollY={sv}>
<ScrollView> <moderationOptsOverrideContext.Provider value={modOpts}>
<CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}> <ScrollView>
<H1 style={[a.text_5xl, a.font_semi_bold, a.pb_lg]}> <CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}>
Moderation states <H1 style={[a.text_5xl, a.font_semi_bold, a.pb_lg]}>
</H1> Moderation states
</H1>
<Heading title="" subtitle="Scenario" /> <Heading title="" subtitle="Scenario" />
<ToggleButton.Group <ToggleButton.Group
label="Scenario" label="Scenario"
values={scenario} values={scenario}
onChange={setScenario}> onChange={setScenario}>
<ToggleButton.Button name="label" label="Label"> <ToggleButton.Button name="label" label="Label">
<ToggleButton.ButtonText>Label</ToggleButton.ButtonText> <ToggleButton.ButtonText>Label</ToggleButton.ButtonText>
</ToggleButton.Button> </ToggleButton.Button>
<ToggleButton.Button name="block" label="Block"> <ToggleButton.Button name="block" label="Block">
<ToggleButton.ButtonText>Block</ToggleButton.ButtonText> <ToggleButton.ButtonText>Block</ToggleButton.ButtonText>
</ToggleButton.Button> </ToggleButton.Button>
<ToggleButton.Button name="mute" label="Mute"> <ToggleButton.Button name="mute" label="Mute">
<ToggleButton.ButtonText>Mute</ToggleButton.ButtonText> <ToggleButton.ButtonText>Mute</ToggleButton.ButtonText>
</ToggleButton.Button> </ToggleButton.Button>
</ToggleButton.Group> </ToggleButton.Group>
{scenario[0] === 'label' && ( {scenario[0] === 'label' && (
<> <>
<View <View
style={[ style={[
a.border, a.border,
a.rounded_sm, a.rounded_sm,
a.mt_lg, a.mt_lg,
a.mb_lg, a.mb_lg,
a.p_lg, a.p_lg,
t.atoms.border_contrast_medium, t.atoms.border_contrast_medium,
]}> ]}>
<Toggle.Group
label="Toggle"
type="radio"
values={label}
onChange={setLabel}>
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
{LABEL_VALUES.map(labelValue => {
let targetFixed = target[0]
if (
targetFixed !== 'account' &&
targetFixed !== 'profile'
) {
targetFixed = 'content'
}
const disabled =
isSelfLabel &&
LABELS[labelValue].flags.includes('no-self')
return (
<Toggle.Item
key={labelValue}
name={labelValue}
label={labelStrings[labelValue].name}
disabled={disabled}
style={disabled ? {opacity: 0.5} : undefined}>
<Toggle.Radio />
<Toggle.LabelText>{labelValue}</Toggle.LabelText>
</Toggle.Item>
)
})}
<Toggle.Item
name="custom"
label="Custom label"
disabled={isSelfLabel}
style={isSelfLabel ? {opacity: 0.5} : undefined}>
<Toggle.Radio />
<Toggle.LabelText>Custom label</Toggle.LabelText>
</Toggle.Item>
</View>
</Toggle.Group>
{label[0] === 'custom' ? (
<CustomLabelForm
def={customLabelDef}
setDef={setCustomLabelDef}
/>
) : (
<>
<View style={{height: 10}} />
<Divider />
</>
)}
<View style={{height: 10}} />
<SmallToggler label="Advanced">
<Toggle.Group <Toggle.Group
label="Toggle" label="Toggle"
type="checkbox" type="radio"
values={scenarioSwitches} values={label}
onChange={setScenarioSwitches}> onChange={setLabel}>
<View <View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}> {LABEL_VALUES.map(labelValue => {
<Toggle.Item name="targetMe" label="Target is me"> let targetFixed = target[0]
<Toggle.Checkbox /> if (
<Toggle.LabelText>Target is me</Toggle.LabelText> targetFixed !== 'account' &&
</Toggle.Item> targetFixed !== 'profile'
<Toggle.Item name="following" label="Following target"> ) {
<Toggle.Checkbox /> targetFixed = 'content'
<Toggle.LabelText>Following target</Toggle.LabelText> }
</Toggle.Item> const disabled =
<Toggle.Item name="selfLabel" label="Self label"> isSelfLabel &&
<Toggle.Checkbox /> LABELS[labelValue].flags.includes('no-self')
<Toggle.LabelText>Self label</Toggle.LabelText> return (
</Toggle.Item> <Toggle.Item
<Toggle.Item name="noAdult" label="Adult disabled"> key={labelValue}
<Toggle.Checkbox /> name={labelValue}
<Toggle.LabelText>Adult disabled</Toggle.LabelText> label={labelStrings[labelValue].name}
</Toggle.Item> disabled={disabled}
<Toggle.Item name="loggedOut" label="Signed out"> style={disabled ? {opacity: 0.5} : undefined}>
<Toggle.Checkbox /> <Toggle.Radio />
<Toggle.LabelText>Signed out</Toggle.LabelText> <Toggle.LabelText>{labelValue}</Toggle.LabelText>
</Toggle.Item>
)
})}
<Toggle.Item
name="custom"
label="Custom label"
disabled={isSelfLabel}
style={isSelfLabel ? {opacity: 0.5} : undefined}>
<Toggle.Radio />
<Toggle.LabelText>Custom label</Toggle.LabelText>
</Toggle.Item> </Toggle.Item>
</View> </View>
</Toggle.Group> </Toggle.Group>
{LABELS[label[0] as keyof typeof LABELS]?.configurable !== {label[0] === 'custom' ? (
false && ( <CustomLabelForm
<View style={[a.mt_md]}> def={customLabelDef}
<Text setDef={setCustomLabelDef}
style={[ />
a.font_semi_bold, ) : (
a.text_xs, <>
t.atoms.text, <View style={{height: 10}} />
a.pb_sm, <Divider />
]}> </>
Preference )}
</Text>
<Toggle.Group <View style={{height: 10}} />
label="Preference"
type="radio" <SmallToggler label="Advanced">
values={visibility} <Toggle.Group
onChange={setVisiblity}> label="Toggle"
<View type="checkbox"
values={scenarioSwitches}
onChange={setScenarioSwitches}>
<View
style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}>
<Toggle.Item name="targetMe" label="Target is me">
<Toggle.Checkbox />
<Toggle.LabelText>Target is me</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item
name="following"
label="Following target">
<Toggle.Checkbox />
<Toggle.LabelText>
Following target
</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="selfLabel" label="Self label">
<Toggle.Checkbox />
<Toggle.LabelText>Self label</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="noAdult" label="Adult disabled">
<Toggle.Checkbox />
<Toggle.LabelText>Adult disabled</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="loggedOut" label="Signed out">
<Toggle.Checkbox />
<Toggle.LabelText>Signed out</Toggle.LabelText>
</Toggle.Item>
</View>
</Toggle.Group>
{LABELS[label[0] as keyof typeof LABELS]?.configurable !==
false && (
<View style={[a.mt_md]}>
<Text
style={[ style={[
a.flex_row, a.font_semi_bold,
a.gap_md, a.text_xs,
a.flex_wrap, t.atoms.text,
a.align_center, a.pb_sm,
]}> ]}>
<Toggle.Item name="hide" label="Hide"> Preference
</Text>
<Toggle.Group
label="Preference"
type="radio"
values={visibility}
onChange={setVisiblity}>
<View
style={[
a.flex_row,
a.gap_md,
a.flex_wrap,
a.align_center,
]}>
<Toggle.Item name="hide" label="Hide">
<Toggle.Radio />
<Toggle.LabelText>Hide</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="warn" label="Warn">
<Toggle.Radio />
<Toggle.LabelText>Warn</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="ignore" label="Ignore">
<Toggle.Radio />
<Toggle.LabelText>Ignore</Toggle.LabelText>
</Toggle.Item>
</View>
</Toggle.Group>
</View>
)}
</SmallToggler>
</View>
<View style={[a.flex_row, a.flex_wrap, a.gap_md]}>
<View>
<Text
style={[
a.font_semi_bold,
a.text_xs,
t.atoms.text,
a.pl_md,
a.pb_xs,
]}>
Target
</Text>
<View
style={[
a.border,
a.rounded_full,
a.px_md,
a.py_sm,
t.atoms.border_contrast_medium,
t.atoms.bg,
]}>
<Toggle.Group
label="Target"
type="radio"
values={target}
onChange={setTarget}>
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
<Toggle.Item name="account" label="Account">
<Toggle.Radio /> <Toggle.Radio />
<Toggle.LabelText>Hide</Toggle.LabelText> <Toggle.LabelText>Account</Toggle.LabelText>
</Toggle.Item> </Toggle.Item>
<Toggle.Item name="warn" label="Warn"> <Toggle.Item name="profile" label="Profile">
<Toggle.Radio /> <Toggle.Radio />
<Toggle.LabelText>Warn</Toggle.LabelText> <Toggle.LabelText>Profile</Toggle.LabelText>
</Toggle.Item> </Toggle.Item>
<Toggle.Item name="ignore" label="Ignore"> <Toggle.Item name="post" label="Post">
<Toggle.Radio /> <Toggle.Radio />
<Toggle.LabelText>Ignore</Toggle.LabelText> <Toggle.LabelText>Post</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="embed" label="Embed">
<Toggle.Radio />
<Toggle.LabelText>Embed</Toggle.LabelText>
</Toggle.Item> </Toggle.Item>
</View> </View>
</Toggle.Group> </Toggle.Group>
</View> </View>
)}
</SmallToggler>
</View>
<View style={[a.flex_row, a.flex_wrap, a.gap_md]}>
<View>
<Text
style={[
a.font_semi_bold,
a.text_xs,
t.atoms.text,
a.pl_md,
a.pb_xs,
]}>
Target
</Text>
<View
style={[
a.border,
a.rounded_full,
a.px_md,
a.py_sm,
t.atoms.border_contrast_medium,
t.atoms.bg,
]}>
<Toggle.Group
label="Target"
type="radio"
values={target}
onChange={setTarget}>
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
<Toggle.Item name="account" label="Account">
<Toggle.Radio />
<Toggle.LabelText>Account</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="profile" label="Profile">
<Toggle.Radio />
<Toggle.LabelText>Profile</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="post" label="Post">
<Toggle.Radio />
<Toggle.LabelText>Post</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item name="embed" label="Embed">
<Toggle.Radio />
<Toggle.LabelText>Embed</Toggle.LabelText>
</Toggle.Item>
</View>
</Toggle.Group>
</View> </View>
</View> </View>
</View>
</>
)}
<Spacer />
<Heading title="" subtitle="Results" />
<ToggleButton.Group
label="Results"
values={view}
onChange={setView}>
<ToggleButton.Button name="post" label="Post">
<ToggleButton.ButtonText>Post</ToggleButton.ButtonText>
</ToggleButton.Button>
<ToggleButton.Button name="notifications" label="Notifications">
<ToggleButton.ButtonText>Notifications</ToggleButton.ButtonText>
</ToggleButton.Button>
<ToggleButton.Button name="account" label="Account">
<ToggleButton.ButtonText>Account</ToggleButton.ButtonText>
</ToggleButton.Button>
<ToggleButton.Button name="data" label="Data">
<ToggleButton.ButtonText>Data</ToggleButton.ButtonText>
</ToggleButton.Button>
</ToggleButton.Group>
<View
style={[
a.border,
a.rounded_sm,
a.mt_lg,
a.p_md,
t.atoms.border_contrast_medium,
]}>
{view[0] === 'post' && (
<>
<Heading title="Post" subtitle="in feed" />
<MockPostFeedItem post={post} moderation={postModeration} />
<Heading title="Post" subtitle="viewed directly" />
<MockPostThreadItem post={post} moderationOpts={modOpts} />
<Heading title="Post" subtitle="reply in thread" />
<MockPostThreadItem
post={post}
moderationOpts={modOpts}
isReply
/>
</> </>
)} )}
{view[0] === 'notifications' && ( <Spacer />
<>
<Heading title="Notification" subtitle="quote or reply" />
<MockNotifItem notif={replyNotif} moderationOpts={modOpts} />
<View style={{height: 20}} />
<Heading title="Notification" subtitle="follow or like" />
<MockNotifItem notif={followNotif} moderationOpts={modOpts} />
</>
)}
{view[0] === 'account' && ( <Heading title="" subtitle="Results" />
<>
<Heading title="Account" subtitle="in listing" />
<MockAccountCard
profile={profile}
moderation={profileModeration}
/>
<Heading title="Account" subtitle="viewing directly" /> <ToggleButton.Group
<MockAccountScreen label="Results"
profile={profile} values={view}
moderation={profileModeration} onChange={setView}>
moderationOpts={modOpts} <ToggleButton.Button name="post" label="Post">
/> <ToggleButton.ButtonText>Post</ToggleButton.ButtonText>
</> </ToggleButton.Button>
)} <ToggleButton.Button name="notifications" label="Notifications">
<ToggleButton.ButtonText>
Notifications
</ToggleButton.ButtonText>
</ToggleButton.Button>
<ToggleButton.Button name="account" label="Account">
<ToggleButton.ButtonText>Account</ToggleButton.ButtonText>
</ToggleButton.Button>
<ToggleButton.Button name="data" label="Data">
<ToggleButton.ButtonText>Data</ToggleButton.ButtonText>
</ToggleButton.Button>
</ToggleButton.Group>
{view[0] === 'data' && ( <View
<> style={[
<ModerationUIView a.border,
label="Profile Moderation UI" a.rounded_sm,
mod={profileModeration} a.mt_lg,
/> a.p_md,
<ModerationUIView t.atoms.border_contrast_medium,
label="Post Moderation UI" ]}>
mod={postModeration} {view[0] === 'post' && (
/> <>
<DataView <Heading title="Post" subtitle="in feed" />
label={label[0]} <MockPostFeedItem post={post} moderation={postModeration} />
data={LABELS[label[0] as keyof typeof LABELS]}
/>
<DataView
label="Profile Moderation Data"
data={profileModeration}
/>
<DataView
label="Post Moderation Data"
data={postModeration}
/>
</>
)}
</View>
<View style={{height: 400}} /> <Heading title="Post" subtitle="viewed directly" />
</CenteredView> <MockPostThreadItem post={post} moderationOpts={modOpts} />
</ScrollView>
</moderationOptsOverrideContext.Provider> <Heading title="Post" subtitle="reply in thread" />
<MockPostThreadItem
post={post}
moderationOpts={modOpts}
isReply
/>
</>
)}
{view[0] === 'notifications' && (
<>
<Heading title="Notification" subtitle="quote or reply" />
<MockNotifItem
notif={replyNotif}
moderationOpts={modOpts}
/>
<View style={{height: 20}} />
<Heading title="Notification" subtitle="follow or like" />
<MockNotifItem
notif={followNotif}
moderationOpts={modOpts}
/>
</>
)}
{view[0] === 'account' && (
<>
<Heading title="Account" subtitle="in listing" />
<MockAccountCard
profile={profile}
moderation={profileModeration}
/>
<Heading title="Account" subtitle="viewing directly" />
<MockAccountScreen
profile={profile}
moderation={profileModeration}
moderationOpts={modOpts}
/>
</>
)}
{view[0] === 'data' && (
<>
<ModerationUIView
label="Profile Moderation UI"
mod={profileModeration}
/>
<ModerationUIView
label="Post Moderation UI"
mod={postModeration}
/>
<DataView
label={label[0]}
data={LABELS[label[0] as keyof typeof LABELS]}
/>
<DataView
label="Profile Moderation Data"
data={profileModeration}
/>
<DataView
label="Post Moderation Data"
data={postModeration}
/>
</>
)}
</View>
<View style={{height: 400}} />
</CenteredView>
</ScrollView>
</moderationOptsOverrideContext.Provider>
</PagerHeaderProvider>
</Layout.Screen> </Layout.Screen>
) )
} }
@@ -760,7 +778,7 @@ function SmallToggler({
) )
} }
function DataView({label, data}: {label: string; data: any}) { function DataView({label, data}: {label: string; data: unknown}) {
return ( return (
<Toggler label={label}> <Toggler label={label}>
<Text style={[{fontFamily: 'monospace'}, a.p_md]}> <Text style={[{fontFamily: 'monospace'}, a.p_md]}>