Add the ability to create new mutelists
This commit is contained in:
@@ -8,17 +8,25 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {ListCard} from './ListCard'
|
||||
import {ProfileCardFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {Button} from '../util/forms/Button'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {ListsListModel} from 'state/models/lists/lists-list'
|
||||
import {useAnalytics} from 'lib/analytics'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {s} from 'lib/styles'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
|
||||
const LOADING_ITEM = {_reactKey: '__loading__'}
|
||||
const CREATENEW_ITEM = {_reactKey: '__loading__'}
|
||||
const EMPTY_ITEM = {_reactKey: '__empty__'}
|
||||
const ERROR_ITEM = {_reactKey: '__error__'}
|
||||
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
|
||||
@@ -27,17 +35,17 @@ export const ListsList = observer(
|
||||
({
|
||||
listsList,
|
||||
style,
|
||||
showPostFollowBtn,
|
||||
scrollElRef,
|
||||
onPressTryAgain,
|
||||
onPressCreateNew,
|
||||
renderEmptyState,
|
||||
testID,
|
||||
headerOffset = 0,
|
||||
}: {
|
||||
listsList: ListsListModel
|
||||
style?: StyleProp<ViewStyle>
|
||||
showPostFollowBtn?: boolean
|
||||
scrollElRef?: MutableRefObject<FlatList<any> | null>
|
||||
onPressCreateNew: () => void
|
||||
onPressTryAgain?: () => void
|
||||
renderEmptyState?: () => JSX.Element
|
||||
testID?: string
|
||||
@@ -56,6 +64,9 @@ export const ListsList = observer(
|
||||
if (listsList.isEmpty) {
|
||||
items = items.concat([EMPTY_ITEM])
|
||||
} else {
|
||||
if (isDesktopWeb) {
|
||||
items = items.concat([CREATENEW_ITEM])
|
||||
}
|
||||
items = items.concat(listsList.lists)
|
||||
}
|
||||
if (listsList.loadMoreError) {
|
||||
@@ -111,6 +122,8 @@ export const ListsList = observer(
|
||||
return renderEmptyState()
|
||||
}
|
||||
return <View />
|
||||
} else if (item === CREATENEW_ITEM) {
|
||||
return <CreateNewItem onPress={onPressCreateNew} />
|
||||
} else if (item === ERROR_ITEM) {
|
||||
return (
|
||||
<ErrorMessage
|
||||
@@ -130,7 +143,7 @@ export const ListsList = observer(
|
||||
}
|
||||
return <ListCard list={item} />
|
||||
},
|
||||
[listsList, onPressTryAgain, onPressRetryLoadMore, showPostFollowBtn],
|
||||
[listsList, onPressTryAgain, onPressRetryLoadMore, onPressCreateNew],
|
||||
)
|
||||
|
||||
const Footer = React.useCallback(
|
||||
@@ -179,6 +192,35 @@ export const ListsList = observer(
|
||||
},
|
||||
)
|
||||
|
||||
function CreateNewItem({onPress}: {onPress: () => void}) {
|
||||
const palInverted = usePalette('inverted')
|
||||
|
||||
return (
|
||||
<View style={[styles.createNewContainer]}>
|
||||
<Button type="inverted" onPress={onPress} style={styles.createNewButton}>
|
||||
<FontAwesomeIcon
|
||||
icon="plus"
|
||||
style={palInverted.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
<Text type="button" style={palInverted.text}>
|
||||
New Mute-list
|
||||
</Text>
|
||||
</Button>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
createNewContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 16,
|
||||
paddingHorizontal: 18,
|
||||
},
|
||||
createNewButton: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
feedFooter: {paddingTop: 20},
|
||||
})
|
||||
|
||||
@@ -23,6 +23,7 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {useAnalytics} from 'lib/analytics'
|
||||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
|
||||
const MAX_NAME = 64 // todo
|
||||
const MAX_DESCRIPTION = 300 // todo
|
||||
@@ -104,7 +105,9 @@ export function Component({onCreate}: {onCreate?: (uri: string) => void}) {
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView behavior="height">
|
||||
<ScrollView style={[pal.view]} testID="createMuteListModal">
|
||||
<ScrollView
|
||||
style={[pal.view, styles.container]}
|
||||
testID="createMuteListModal">
|
||||
<Text style={[styles.title, pal.text]}>New Mute List</Text>
|
||||
{error !== '' && (
|
||||
<View style={styles.errorContainer}>
|
||||
@@ -190,6 +193,9 @@ export function Component({onCreate}: {onCreate?: (uri: string) => void}) {
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingHorizontal: isDesktopWeb ? 0 : 16,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
|
||||
@@ -68,7 +68,7 @@ export const ModalsContainer = observer(function ModalsContainer() {
|
||||
snapPoints = ReportAccountModal.snapPoints
|
||||
element = <ReportAccountModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'create-mute-list') {
|
||||
snapPoints = ReportAccountModal.snapPoints
|
||||
snapPoints = CreateMuteListModal.snapPoints
|
||||
element = <CreateMuteListModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'delete-account') {
|
||||
snapPoints = DeleteAccountModal.snapPoints
|
||||
|
||||
@@ -20,11 +20,13 @@ export const ViewHeader = observer(function ({
|
||||
canGoBack,
|
||||
hideOnScroll,
|
||||
showOnDesktop,
|
||||
renderButton,
|
||||
}: {
|
||||
title: string
|
||||
canGoBack?: boolean
|
||||
hideOnScroll?: boolean
|
||||
showOnDesktop?: boolean
|
||||
renderButton?: () => JSX.Element
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
@@ -79,7 +81,11 @@ export const ViewHeader = observer(function ({
|
||||
{title}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={canGoBack ? styles.backBtn : styles.backBtnWide} />
|
||||
{renderButton ? (
|
||||
renderButton()
|
||||
) : (
|
||||
<View style={canGoBack ? styles.backBtn : styles.backBtnWide} />
|
||||
)}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import {StyleSheet} from 'react-native'
|
||||
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||
import {
|
||||
useFocusEffect,
|
||||
useNavigation,
|
||||
StackActions,
|
||||
} from '@react-navigation/native'
|
||||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {AtUri} from '@atproto/api'
|
||||
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||
@@ -12,6 +12,7 @@ import {EmptyStateWithButton} from 'view/com/util/EmptyStateWithButton'
|
||||
import {useStores} from 'state/index'
|
||||
import {ListsListModel} from 'state/models/lists/lists-list'
|
||||
import {ListsList} from 'view/com/lists/ListsList'
|
||||
import {Button} from 'view/com/util/forms/Button'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
@@ -65,6 +66,22 @@ export const ModerationMuteListsScreen = withAuthRequired(({route}: Props) => {
|
||||
)
|
||||
}, [onPressNewMuteList])
|
||||
|
||||
const renderHeaderButton = React.useCallback(
|
||||
() => (
|
||||
<Button
|
||||
type="primary-light"
|
||||
onPress={onPressNewMuteList}
|
||||
style={styles.createBtn}>
|
||||
<FontAwesomeIcon
|
||||
icon="plus"
|
||||
style={pal.link as FontAwesomeIconStyle}
|
||||
size={18}
|
||||
/>
|
||||
</Button>
|
||||
),
|
||||
[onPressNewMuteList, pal],
|
||||
)
|
||||
|
||||
return (
|
||||
<CenteredView
|
||||
style={[
|
||||
@@ -74,8 +91,16 @@ export const ModerationMuteListsScreen = withAuthRequired(({route}: Props) => {
|
||||
pal.border,
|
||||
]}
|
||||
testID="moderationMutelistsScreen">
|
||||
<ViewHeader title="Mute-list Subscriptions" showOnDesktop />
|
||||
<ListsList listsList={mutelists} renderEmptyState={renderEmptyState} />
|
||||
<ViewHeader
|
||||
title="Mute-lists"
|
||||
showOnDesktop
|
||||
renderButton={renderHeaderButton}
|
||||
/>
|
||||
<ListsList
|
||||
listsList={mutelists}
|
||||
renderEmptyState={renderEmptyState}
|
||||
onPressCreateNew={onPressNewMuteList}
|
||||
/>
|
||||
</CenteredView>
|
||||
)
|
||||
})
|
||||
@@ -89,36 +114,7 @@ const styles = StyleSheet.create({
|
||||
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,
|
||||
createBtn: {
|
||||
width: 40,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user