diff options
Diffstat (limited to 'src/view/screens')
-rw-r--r-- | src/view/screens/AppPasswords.tsx | 2 | ||||
-rw-r--r-- | src/view/screens/BlockedAccounts.tsx | 172 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 25 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 22 |
4 files changed, 218 insertions, 3 deletions
diff --git a/src/view/screens/AppPasswords.tsx b/src/view/screens/AppPasswords.tsx index f957a45e0..4e20558b7 100644 --- a/src/view/screens/AppPasswords.tsx +++ b/src/view/screens/AppPasswords.tsx @@ -27,7 +27,7 @@ export const AppPasswords = withAuthRequired( useFocusEffect( React.useCallback(() => { - screen('Settings') + screen('AppPasswords') store.shell.setMinimalShellMode(false) }, [screen, store]), ) diff --git a/src/view/screens/BlockedAccounts.tsx b/src/view/screens/BlockedAccounts.tsx new file mode 100644 index 000000000..195068510 --- /dev/null +++ b/src/view/screens/BlockedAccounts.tsx @@ -0,0 +1,172 @@ +import React, {useMemo} from 'react' +import { + ActivityIndicator, + FlatList, + RefreshControl, + StyleSheet, + View, +} from 'react-native' +import {AppBskyActorDefs as ActorDefs} from '@atproto/api' +import {Text} from '../com/util/text/Text' +import {useStores} from 'state/index' +import {usePalette} from 'lib/hooks/usePalette' +import {isDesktopWeb} from 'platform/detection' +import {withAuthRequired} from 'view/com/auth/withAuthRequired' +import {observer} from 'mobx-react-lite' +import {NativeStackScreenProps} from '@react-navigation/native-stack' +import {CommonNavigatorParams} from 'lib/routes/types' +import {BlockedAccountsModel} from 'state/models/lists/blocked-accounts' +import {useAnalytics} from 'lib/analytics' +import {useFocusEffect} from '@react-navigation/native' +import {ViewHeader} from '../com/util/ViewHeader' +import {CenteredView} from 'view/com/util/Views' +import {ProfileCard} from 'view/com/profile/ProfileCard' + +type Props = NativeStackScreenProps<CommonNavigatorParams, 'BlockedAccounts'> +export const BlockedAccounts = withAuthRequired( + observer(({}: Props) => { + const pal = usePalette('default') + const store = useStores() + const {screen} = useAnalytics() + const blockedAccounts = useMemo( + () => new BlockedAccountsModel(store), + [store], + ) + + useFocusEffect( + React.useCallback(() => { + screen('BlockedAccounts') + store.shell.setMinimalShellMode(false) + blockedAccounts.refresh() + }, [screen, store, blockedAccounts]), + ) + + const onRefresh = React.useCallback(() => { + blockedAccounts.refresh() + }, [blockedAccounts]) + const onEndReached = React.useCallback(() => { + blockedAccounts + .loadMore() + .catch(err => + store.log.error('Failed to load more blocked accounts', err), + ) + }, [blockedAccounts, store]) + + const renderItem = ({ + item, + index, + }: { + item: ActorDefs.ProfileView + index: number + }) => ( + <ProfileCard + testID={`blockedAccount-${index}`} + key={item.did} + profile={item} + overrideModeration + /> + ) + return ( + <CenteredView + style={[ + styles.container, + isDesktopWeb && styles.containerDesktop, + pal.view, + pal.border, + ]} + testID="blockedAccountsScreen"> + <ViewHeader title="Blocked Accounts" showOnDesktop /> + <Text + type="sm" + style={[ + styles.description, + pal.text, + isDesktopWeb && styles.descriptionDesktop, + ]}> + Blocked accounts cannot reply in your threads, mention you, or + otherwise interact with you. You will not see their content and they + will be prevented from seeing yours. + </Text> + {!blockedAccounts.hasContent ? ( + <View style={[pal.border, !isDesktopWeb && styles.flex1]}> + <View style={[styles.empty, pal.viewLight]}> + <Text type="lg" style={[pal.text, styles.emptyText]}> + You have not blocked any accounts yet. To block an account, go + to their profile and selected "Block account" from the menu on + their account. + </Text> + </View> + </View> + ) : ( + <FlatList + style={[!isDesktopWeb && styles.flex1]} + data={blockedAccounts.blocks} + keyExtractor={(item: ActorDefs.ProfileView) => item.did} + refreshControl={ + <RefreshControl + refreshing={blockedAccounts.isRefreshing} + onRefresh={onRefresh} + tintColor={pal.colors.text} + titleColor={pal.colors.text} + /> + } + onEndReached={onEndReached} + renderItem={renderItem} + initialNumToRender={15} + ListFooterComponent={() => ( + <View style={styles.footer}> + {blockedAccounts.isLoading && <ActivityIndicator />} + </View> + )} + extraData={blockedAccounts.isLoading} + // @ts-ignore our .web version only -prf + desktopFixedHeight + /> + )} + </CenteredView> + ) + }), +) + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingBottom: isDesktopWeb ? 0 : 100, + }, + containerDesktop: { + borderLeftWidth: 1, + borderRightWidth: 1, + }, + title: { + textAlign: 'center', + marginTop: 12, + marginBottom: 12, + }, + description: { + textAlign: 'center', + paddingHorizontal: 30, + marginBottom: 14, + }, + descriptionDesktop: { + marginTop: 14, + }, + + flex1: { + flex: 1, + }, + empty: { + paddingHorizontal: 20, + paddingVertical: 20, + borderRadius: 16, + marginHorizontal: 24, + marginTop: 10, + }, + emptyText: { + textAlign: 'center', + }, + + footer: { + height: 200, + paddingTop: 20, + }, +}) diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 4be117932..5fb212554 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -116,6 +116,24 @@ export const ProfileScreen = withAuthRequired( } else if (item === ProfileUiModel.LOADING_ITEM) { return <PostFeedLoadingPlaceholder /> } else if (item._reactKey === '__error__') { + if (uiState.feed.isBlocking) { + return ( + <EmptyState + icon="ban" + message="Posts hidden" + style={styles.emptyState} + /> + ) + } + if (uiState.feed.isBlockedBy) { + return ( + <EmptyState + icon="ban" + message="Posts hidden" + style={styles.emptyState} + /> + ) + } return ( <View style={s.p5}> <ErrorMessage @@ -137,7 +155,12 @@ export const ProfileScreen = withAuthRequired( } return <View /> }, - [onPressTryAgain, uiState.profile.did], + [ + onPressTryAgain, + uiState.profile.did, + uiState.feed.isBlocking, + uiState.feed.isBlockedBy, + ], ) return ( diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index 89e2d78b4..ef02e8189 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -255,7 +255,7 @@ export const SettingsScreen = withAuthRequired( <View style={styles.spacer20} /> <Text type="xl-bold" style={[pal.text, styles.heading]}> - Advanced + Moderation </Text> <TouchableOpacity testID="contentFilteringBtn" @@ -272,6 +272,26 @@ export const SettingsScreen = withAuthRequired( </Text> </TouchableOpacity> <Link + testID="blockedAccountsBtn" + style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]} + href="/settings/blocked-accounts"> + <View style={[styles.iconContainer, pal.btn]}> + <FontAwesomeIcon + icon="ban" + style={pal.text as FontAwesomeIconStyle} + /> + </View> + <Text type="lg" style={pal.text}> + Blocked accounts + </Text> + </Link> + + <View style={styles.spacer20} /> + + <Text type="xl-bold" style={[pal.text, styles.heading]}> + Advanced + </Text> + <Link testID="appPasswordBtn" style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]} href="/settings/app-passwords"> |