1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Consolidate swipe to delete views

This commit is contained in:
xmflsct
2023-01-27 18:44:48 +01:00
parent aa5a607666
commit 738194d108
7 changed files with 189 additions and 175 deletions

View File

@ -2,7 +2,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { Fragment } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { View } from 'react-native'
import { View, ViewStyle } from 'react-native'
import { TouchableNativeFeedback } from 'react-native-gesture-handler'
import Icon from './Icon'
import CustomText from './Text'
@ -11,9 +11,10 @@ export type Props = {
onPress: () => void
filter: Mastodon.Filter<'v2'>
button?: React.ReactNode
style?: ViewStyle
}
export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
export const Filter: React.FC<Props> = ({ onPress, filter, button, style }) => {
const { t } = useTranslation(['common', 'screenTabs'])
const { colors } = useTheme()
@ -24,7 +25,8 @@ export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
paddingVertical: StyleConstants.Spacing.S,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.backgroundDefault
backgroundColor: colors.backgroundDefault,
...style
}}
>
<View style={{ flex: 1 }}>
@ -83,12 +85,7 @@ export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
{filter.context.map((c, index) => (
<Fragment key={index}>
<CustomText
style={{
color: colors.secondary,
textDecorationColor: colors.disabled,
textDecorationLine: 'underline',
textDecorationStyle: 'solid'
}}
style={{ color: colors.secondary }}
children={t(`screenTabs:me.preferencesFilters.contexts.${c}`)}
/>
<CustomText children={t('common:separator')} />

View File

@ -12,7 +12,7 @@ const Hr: React.FC<{ style?: ViewStyle }> = ({ style }) => {
borderTopColor: colors.border,
borderTopWidth: 1,
height: 1,
marginVertical: StyleConstants.Spacing.S
paddingVertical: StyleConstants.Spacing.S
},
style
]}

View File

@ -0,0 +1,57 @@
import { StyleConstants } from '@utils/styles/constants'
import { ColorValue, TouchableNativeFeedback, View } from 'react-native'
import { SwipeListView } from 'react-native-swipe-list-view'
import haptics from './haptics'
import Icon, { IconName } from './Icon'
import ComponentSeparator from './Separator'
export type Props = {
actions: {
onPress: (item: any) => void
color: ColorValue
icon: IconName
haptic?: Parameters<typeof haptics>['0']
}[]
}
export const SwipeToActions = <T extends unknown>({
actions,
...rest
}: Props & SwipeListView<T>['props']) => {
const perActionWidth = StyleConstants.Spacing.L * 2 + StyleConstants.Font.Size.L
return (
<SwipeListView
renderHiddenItem={({ item }) => (
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'flex-end' }}>
{actions.map((action, index) => (
<TouchableNativeFeedback
key={index}
onPress={() => {
haptics(action.haptic || 'Light')
action.onPress({ item })
}}
>
<View
style={{
paddingHorizontal: StyleConstants.Spacing.L,
flexBasis: perActionWidth,
backgroundColor: action.color,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Icon name={action.icon} color='white' size={StyleConstants.Font.Size.L} />
</View>
</TouchableNativeFeedback>
))}
</View>
)}
rightOpenValue={-perActionWidth * actions.length}
disableRightSwipe
closeOnRowPress
ItemSeparatorComponent={ComponentSeparator}
{...rest}
/>
)
}

View File

@ -1,6 +1,6 @@
import { HeaderLeft } from '@components/Header'
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import { SwipeToActions } from '@components/SwipeToActions'
import CustomText from '@components/Text'
import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created'
import apiInstance from '@utils/api/instance'
@ -10,10 +10,8 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Dimensions, Modal, Platform, Pressable, View } from 'react-native'
import { Dimensions, Modal, Pressable, View } from 'react-native'
import FastImage from 'react-native-fast-image'
import { PanGestureHandler } from 'react-native-gesture-handler'
import { SwipeListView } from 'react-native-swipe-list-view'
import ComposeContext from './utils/createContext'
import { formatText } from './utils/processText'
import { ComposeStateDraft, ExtendedAttachment } from './utils/types'
@ -39,9 +37,7 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
useEffect(() => {
navigation.setOptions({
title: t('content.draftsList.header.title'),
headerLeft: () => (
<HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />
)
headerLeft: () => <HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />
})
}, [])
@ -49,8 +45,6 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
const [drafts] = useAccountStorage.object('drafts')
const [checkingAttachments, setCheckingAttachments] = useState(false)
const actionWidth = StyleConstants.Font.Size.L + StyleConstants.Spacing.Global.PagePadding * 4
return (
<>
<View
@ -61,7 +55,8 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
padding: StyleConstants.Spacing.S,
borderColor: colors.border,
borderWidth: 1,
borderRadius: StyleConstants.Spacing.S
borderRadius: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.S
}}
>
<Icon
@ -74,8 +69,10 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
{t('content.draftsList.warning')}
</CustomText>
</View>
<PanGestureHandler enabled={Platform.OS === 'ios'}>
<SwipeListView
<SwipeToActions
actions={[
{ onPress: ({ item }) => removeDraft(item.timestamp), color: colors.red, icon: 'trash' }
]}
data={drafts.filter(draft => draft.timestamp !== timestamp)}
renderItem={({ item }: { item: ComposeStateDraft }) => {
return (
@ -168,41 +165,8 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
</Pressable>
)
}}
renderHiddenItem={({ item }) => (
<Pressable
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
backgroundColor: colors.red
}}
onPress={() => removeDraft(item.timestamp)}
children={
<View
style={{
flexBasis:
StyleConstants.Font.Size.L + StyleConstants.Spacing.Global.PagePadding * 4,
justifyContent: 'center',
alignItems: 'center'
}}
children={
<Icon
name='trash'
size={StyleConstants.Font.Size.L}
color={colors.primaryOverlay}
/>
}
/>
}
/>
)}
disableRightSwipe={true}
rightOpenValue={-actionWidth}
previewOpenValue={-actionWidth / 2}
ItemSeparatorComponent={ComponentSeparator}
keyExtractor={item => item.timestamp?.toString()}
/>
</PanGestureHandler>
<Modal
transparent
animationType='fade'

View File

@ -416,12 +416,12 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
<Stack.Screen
name='Screen-Compose-DraftsList'
component={ComposeDraftsList}
options={{ presentation: 'modal' }}
options={{ presentation: 'modal', headerShadowVisible: false }}
/>
<Stack.Screen
name='Screen-Compose-EditAttachment'
component={ComposeEditAttachment}
options={{ presentation: 'modal' }}
options={{ presentation: 'modal', headerShadowVisible: false }}
/>
</Stack.Navigator>
</ComposeContext.Provider>

View File

@ -1,22 +1,17 @@
import { Filter } from '@components/Filter'
import { HeaderLeft, HeaderRight } from '@components/Header'
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import { SwipeToActions } from '@components/SwipeToActions'
import apiInstance from '@utils/api/instance'
import { TabMePreferencesStackScreenProps } from '@utils/navigation/navigators'
import { useFiltersQuery } from '@utils/queryHooks/filters'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import { SwipeListView } from 'react-native-swipe-list-view'
const TabMePreferencesFilters: React.FC<
TabMePreferencesStackScreenProps<'Tab-Me-Preferences-Filters'>
> = ({ navigation }) => {
const { colors } = useTheme()
const { t } = useTranslation(['common', 'screenTabs'])
useEffect(() => {
navigation.setOptions({
@ -38,40 +33,31 @@ const TabMePreferencesFilters: React.FC<
const { data, refetch } = useFiltersQuery<'v2'>({ version: 'v2' })
return (
<SwipeListView
contentContainerStyle={{ padding: StyleConstants.Spacing.Global.PagePadding }}
renderHiddenItem={({ item }) => (
<Pressable
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end',
backgroundColor: colors.red
}}
onPress={() => {
<SwipeToActions
actions={[
{
onPress: ({ item }) => {
apiInstance({ method: 'delete', version: 'v2', url: `filters/${item.id}` }).then(() =>
refetch()
)
}}
>
<View style={{ paddingHorizontal: StyleConstants.Spacing.L }}>
<Icon name='trash' color='white' size={StyleConstants.Font.Size.L} />
</View>
</Pressable>
)}
rightOpenValue={-(StyleConstants.Spacing.L * 2 + StyleConstants.Font.Size.L)}
disableRightSwipe
closeOnRowPress
},
color: colors.red,
icon: 'trash'
}
]}
data={data?.sort(filter =>
filter.expires_at ? new Date().getTime() - new Date(filter.expires_at).getTime() : 1
)}
renderItem={({ item: filter }) => (
<Filter
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
paddingVertical: StyleConstants.Spacing.M
}}
filter={filter}
onPress={() => navigation.navigate('Tab-Me-Preferences-Filter', { type: 'edit', filter })}
/>
)}
ItemSeparatorComponent={ComponentSeparator}
/>
)
}

View File

@ -1,8 +1,9 @@
import { HeaderLeft } from '@components/Header'
import { Message } from '@components/Message'
import { useNavigationState } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import { TabMePreferencesStackParamList, TabMeStackScreenProps } from '@utils/navigation/navigators'
import React, { useRef } from 'react'
import React, { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import FlashMessage from 'react-native-flash-message'
import TabMePreferencesFilter from './Filter'
@ -17,6 +18,15 @@ const TabMePreferences: React.FC<TabMeStackScreenProps<'Tab-Me-Preferences'>> =
const { t } = useTranslation('screenTabs')
const messageRef = useRef<FlashMessage>(null)
const isNested =
(useNavigationState(
state => state.routes.find(route => route.name === 'Tab-Me-Preferences')?.state?.routes.length
) || 0) > 1
useEffect(() => {
navigation.setOptions({ gestureEnabled: !isNested })
}, [isNested])
return (
<>
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}>