1
0
mirror of https://github.com/tooot-app/app synced 2025-03-10 00:20:11 +01:00

Refined filter view

This commit is contained in:
xmflsct 2023-01-26 13:59:42 +01:00
parent 2a806695ca
commit e8eb62e2d0
9 changed files with 304 additions and 225 deletions

View File

@ -235,12 +235,7 @@ const ComponentInstance: React.FC<Props> = ({
/> />
</View> </View>
) : null} ) : null}
<View <View style={{ marginTop: StyleConstants.Spacing.L }}>
style={{
marginTop: StyleConstants.Spacing.L,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<View <View
style={{ style={{
flexDirection: 'row', flexDirection: 'row',

View File

@ -0,0 +1,29 @@
import { useHeaderHeight } from '@react-navigation/elements'
import { StyleConstants } from '@utils/styles/constants'
import { forwardRef, PropsWithChildren, RefObject } from 'react'
import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
export const ModalScrollView = forwardRef(
({ children }: PropsWithChildren, ref: RefObject<ScrollView>) => {
const headerHeight = useHeaderHeight()
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
keyboardVerticalOffset={headerHeight}
>
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
<ScrollView
ref={ref}
keyboardShouldPersistTaps='always'
contentContainerStyle={{ padding: StyleConstants.Spacing.Global.PagePadding }}
>
{children}
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
)
}
)

View File

@ -309,7 +309,11 @@ const ParseHTML: React.FC<Props> = ({
height: numberOfLines === 1 && !expanded ? 0 : undefined height: numberOfLines === 1 && !expanded ? 0 : undefined
}} }}
numberOfLines={ numberOfLines={
typeof totalLines === 'number' ? (expanded ? 999 : numberOfLines) : MAX_ALLOWED_LINES typeof totalLines === 'number'
? expanded
? 999
: numberOfLines
: Math.max(MAX_ALLOWED_LINES, numberOfLines)
} }
selectable={selectable} selectable={selectable}
/> />

View File

@ -210,7 +210,8 @@
"hide": "Hidden completely" "hide": "Hidden completely"
}, },
"keywords": "Matches for these keywords", "keywords": "Matches for these keywords",
"keyword": "Keyword" "keyword": "Keyword",
"statuses": "Matches these toots"
}, },
"profile": { "profile": {
"feedback": { "feedback": {

View File

@ -1,5 +1,6 @@
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { HeaderLeft, HeaderRight } from '@components/Header' import { HeaderLeft, HeaderRight } from '@components/Header'
import { ModalScrollView } from '@components/ModalScrollView'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import apiInstance from '@utils/api/instance' import apiInstance from '@utils/api/instance'
import { ScreenComposeStackScreenProps } from '@utils/navigation/navigators' import { ScreenComposeStackScreenProps } from '@utils/navigation/navigators'
@ -7,8 +8,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react' import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Alert, KeyboardAvoidingView, Platform, ScrollView, TextInput } from 'react-native' import { Alert, TextInput } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import ComposeContext from './utils/createContext' import ComposeContext from './utils/createContext'
const ComposeEditAttachment: React.FC< const ComposeEditAttachment: React.FC<
@ -34,9 +34,7 @@ const ComposeEditAttachment: React.FC<
useEffect(() => { useEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: t('content.editAttachment.header.title'), title: t('content.editAttachment.header.title'),
headerLeft: () => ( headerLeft: () => <HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />,
<HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />
),
headerRight: () => ( headerRight: () => (
<HeaderRight <HeaderRight
accessibilityLabel={t('content.editAttachment.header.right.accessibilityLabel')} accessibilityLabel={t('content.editAttachment.header.right.accessibilityLabel')}
@ -88,59 +86,48 @@ const ComposeEditAttachment: React.FC<
}, [theAttachment]) }, [theAttachment])
return ( return (
<KeyboardAvoidingView <ModalScrollView>
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} <CustomText fontStyle='M' style={{ color: colors.primaryDefault }} fontWeight='Bold'>
style={{ flex: 1 }} {t('content.editAttachment.content.altText.heading')}
> </CustomText>
<SafeAreaView <TextInput
style={{ flex: 1, padding: StyleConstants.Spacing.Global.PagePadding }} style={{
edges={['left', 'right', 'bottom']} height: StyleConstants.Font.Size.M * 11 + StyleConstants.Spacing.Global.PagePadding * 2,
> ...StyleConstants.FontStyle.M,
<ScrollView> marginTop: StyleConstants.Spacing.M,
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }} fontWeight='Bold'> marginBottom: StyleConstants.Spacing.S,
{t('content.editAttachment.content.altText.heading')} padding: StyleConstants.Spacing.Global.PagePadding,
</CustomText> borderWidth: 1,
<TextInput borderColor: colors.border,
style={{ color: colors.primaryDefault
height: }}
StyleConstants.Font.Size.M * 11 + StyleConstants.Spacing.Global.PagePadding * 2, maxLength={1500}
...StyleConstants.FontStyle.M, multiline
marginTop: StyleConstants.Spacing.M, onChangeText={e =>
marginBottom: StyleConstants.Spacing.S, composeDispatch({
padding: StyleConstants.Spacing.Global.PagePadding, type: 'attachment/edit',
borderWidth: 1, payload: {
borderColor: colors.border, ...theAttachment,
color: colors.primaryDefault description: e
}}
maxLength={1500}
multiline
onChangeText={e =>
composeDispatch({
type: 'attachment/edit',
payload: {
...theAttachment,
description: e
}
})
} }
placeholder={t('content.editAttachment.content.altText.placeholder')} })
placeholderTextColor={colors.secondary} }
value={theAttachment.description} placeholder={t('content.editAttachment.content.altText.placeholder')}
/> placeholderTextColor={colors.secondary}
<CustomText value={theAttachment.description}
fontStyle='S' />
style={{ <CustomText
textAlign: 'right', fontStyle='S'
marginRight: StyleConstants.Spacing.S, style={{
marginBottom: StyleConstants.Spacing.M, textAlign: 'right',
color: colors.secondary marginRight: StyleConstants.Spacing.S,
}} marginBottom: StyleConstants.Spacing.M,
> color: colors.secondary
{theAttachment.description?.length || 0} / 1500 }}
</CustomText> >
</ScrollView> {theAttachment.description?.length || 0} / 1500
</SafeAreaView> </CustomText>
</KeyboardAvoidingView> </ModalScrollView>
) )
} }

View File

@ -4,22 +4,24 @@ import { HeaderLeft, HeaderRight } from '@components/Header'
import Hr from '@components/Hr' import Hr from '@components/Hr'
import ComponentInput from '@components/Input' import ComponentInput from '@components/Input'
import { MenuRow } from '@components/Menu' import { MenuRow } from '@components/Menu'
import { ModalScrollView } from '@components/ModalScrollView'
import Selections from '@components/Selections' import Selections from '@components/Selections'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { useActionSheet } from '@expo/react-native-action-sheet' import { useActionSheet } from '@expo/react-native-action-sheet'
import apiInstance from '@utils/api/instance' import apiInstance from '@utils/api/instance'
import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles' import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles'
import browserPackage from '@utils/helpers/browserPackage'
import { TabMePreferencesStackScreenProps } from '@utils/navigation/navigators' import { TabMePreferencesStackScreenProps } from '@utils/navigation/navigators'
import { queryClient } from '@utils/queryHooks' import { queryClient } from '@utils/queryHooks'
import { QueryKeyFilters } from '@utils/queryHooks/filters' import { QueryKeyFilters } from '@utils/queryHooks/filters'
import { getAccountStorage } from '@utils/storage/actions'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { RefObject, useEffect, useState } from 'react' import * as WebBrowser from 'expo-web-browser'
import React, { RefObject, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { KeyboardAvoidingView, Platform, View } from 'react-native' import { ScrollView, View } from 'react-native'
import FlashMessage from 'react-native-flash-message' import FlashMessage from 'react-native-flash-message'
import { ScrollView } from 'react-native-gesture-handler'
import { SafeAreaView } from 'react-native-safe-area-context'
const TabMePreferencesFilter: React.FC< const TabMePreferencesFilter: React.FC<
TabMePreferencesStackScreenProps<'Tab-Me-Preferences-Filter'> & { TabMePreferencesStackScreenProps<'Tab-Me-Preferences-Filter'> & {
@ -101,7 +103,11 @@ const TabMePreferencesFilter: React.FC<
]) ])
const [keywords, setKeywords] = useState<string[]>( const [keywords, setKeywords] = useState<string[]>(
params.type === 'edit' ? params.filter.keywords.map(({ keyword }) => keyword) : [] params.type === 'edit'
? params.filter.keywords.length
? params.filter.keywords.map(({ keyword }) => keyword)
: ['']
: ['']
) )
useEffect(() => { useEffect(() => {
@ -152,6 +158,48 @@ const TabMePreferencesFilter: React.FC<
}) })
break break
case 'edit': case 'edit':
isLoading = true
await apiInstance({
method: 'put',
version: 'v2',
url: `filters/${params.filter.id}`,
body: {
title: titleState[0],
context: contexts
.filter(context => context.selected)
.map(context => context.type),
filter_action: actions.filter(
action => action.type === 'hide' && action.selected
).length
? 'hide'
: 'warn',
...(parseInt(expiration) && {
expires_in: parseInt(expiration)
}),
...(keywords.filter(keyword => keyword.length).length
? {
keywords_attributes: keywords
.filter(keyword => keyword.length)
.map(keyword => ({ keyword, whole_word: true }))
}
: params.filter.keywords.length && {
keywords_attributes: params.filter.keywords.map(keyword => ({
...keyword,
_destroy: true
}))
})
}
})
.then(() => {
isLoading = false
const queryKey: QueryKeyFilters = ['Filters', { version: 'v2' }]
queryClient.refetchQueries(queryKey)
navigation.navigate('Tab-Me-Preferences-Filters')
})
.catch(() => {
isLoading = false
haptics('Error')
})
break break
} }
}} }}
@ -160,105 +208,132 @@ const TabMePreferencesFilter: React.FC<
}) })
}, [titleState[0], expiration, contexts, actions, keywords]) }, [titleState[0], expiration, contexts, actions, keywords])
const scrollViewRef = useRef<ScrollView>(null)
return ( return (
<KeyboardAvoidingView <ModalScrollView ref={scrollViewRef}>
style={{ flex: 1 }} <ComponentInput title={t('screenTabs:me.preferencesFilter.name')} value={titleState} />
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} <MenuRow
> title={t('screenTabs:me.preferencesFilter.expiration')}
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}> content={t(`screenTabs:me.preferencesFilter.expirationOptions.${expiration}`)}
<ScrollView style={{ padding: StyleConstants.Spacing.Global.PagePadding }}> iconBack='chevron-right'
<ComponentInput title={t('screenTabs:me.preferencesFilter.name')} value={titleState} /> onPress={() =>
showActionSheetWithOptions(
{
title: t('screenTabs:me.preferencesFilter.expiration'),
options: [
...expirations.map(opt =>
t(`screenTabs:me.preferencesFilter.expirationOptions.${opt}`)
),
t('common:buttons.cancel')
],
cancelButtonIndex: expirations.length,
...androidActionSheetStyles(colors)
},
(selectedIndex: number) => {
selectedIndex < expirations.length && setExpiration(expirations[selectedIndex])
}
)
}
/>
<Hr />
<Selections
title={t('screenTabs:me.preferencesFilter.context')}
multiple
invalid={!contexts.filter(context => context.selected).length}
options={contexts}
setOptions={setContexts}
/>
<Selections
title={t('screenTabs:me.preferencesFilter.action')}
options={actions}
setOptions={setActions}
/>
<Hr style={{ marginVertical: StyleConstants.Spacing.M }} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
<CustomText
fontStyle='M'
children={t('screenTabs:me.preferencesFilter.keywords')}
style={{ color: colors.primaryDefault }}
/>
<CustomText
style={{ marginHorizontal: StyleConstants.Spacing.M, color: colors.secondary }}
children={t('screenTabs:me.preferencesFilters.keywords', { count: keywords.length })}
/>
</View>
<View
style={{
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S
}}
>
{[...Array(keywords.length)].map((_, i) => (
<ComponentInput
key={i}
title={t('screenTabs:me.preferencesFilter.keyword')}
value={[
keywords[i],
k => setKeywords(keywords.map((curr, ii) => (i === ii ? k : curr)))
]}
/>
))}
</View>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: StyleConstants.Spacing.M
}}
>
<Button
onPress={() => setKeywords(keywords.slice(0, keywords.length - 1))}
type='icon'
content='minus'
round
disabled={keywords.length < 1}
style={{ marginRight: StyleConstants.Spacing.M }}
/>
<Button
onPress={() => {
setKeywords([...keywords, ''])
setTimeout(() => scrollViewRef.current?.scrollToEnd(), 50)
}}
type='icon'
content='plus'
round
/>
</View>
{params.type === 'edit' && params.filter.statuses?.length ? (
<>
<Hr style={{ marginVertical: StyleConstants.Spacing.M }} />
<MenuRow <MenuRow
title={t('screenTabs:me.preferencesFilter.expiration')} title={t('screenTabs:me.preferencesFilter.statuses')}
content={t(`screenTabs:me.preferencesFilter.expirationOptions.${expiration}`)} content={t('screenTabs:me.preferencesFilters.statuses', {
iconBack='chevron-right' count: params.filter.statuses.length
onPress={() => })}
showActionSheetWithOptions( iconBack='external-link'
onPress={async () =>
WebBrowser.openAuthSessionAsync(
`https://${getAccountStorage.string('auth.domain')}/filters/${
params.filter.id
}/statuses`,
'tooot://tooot',
{ {
title: t('screenTabs:me.preferencesFilter.expiration'), ...(await browserPackage()),
options: [ dismissButtonStyle: 'done',
...expirations.map(opt => readerMode: false
t(`screenTabs:me.preferencesFilter.expirationOptions.${opt}`)
),
t('common:buttons.cancel')
],
cancelButtonIndex: expirations.length,
...androidActionSheetStyles(colors)
},
(selectedIndex: number) => {
selectedIndex < expirations.length && setExpiration(expirations[selectedIndex])
} }
) )
} }
/> />
<Hr /> </>
) : null}
<Selections </ModalScrollView>
title={t('screenTabs:me.preferencesFilter.context')}
multiple
invalid={!contexts.filter(context => context.selected).length}
options={contexts}
setOptions={setContexts}
/>
<Selections
title={t('screenTabs:me.preferencesFilter.action')}
options={actions}
setOptions={setActions}
/>
<Hr style={{ marginVertical: StyleConstants.Spacing.M }} />
<CustomText
fontStyle='M'
children={t('screenTabs:me.preferencesFilter.keywords')}
style={{ color: colors.primaryDefault }}
/>
<View
style={{
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S
}}
>
{[...Array(keywords.length)].map((_, i) => (
<ComponentInput
key={i}
title={t('screenTabs:me.preferencesFilter.keyword')}
value={[
keywords[i],
k => setKeywords(keywords.map((curr, ii) => (i === ii ? k : curr)))
]}
/>
))}
</View>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: StyleConstants.Spacing.M
}}
>
<Button
onPress={() => setKeywords(keywords.slice(0, keywords.length - 1))}
type='icon'
content='minus'
round
disabled={keywords.length < 1}
/>
<CustomText
style={{ marginHorizontal: StyleConstants.Spacing.M, color: colors.secondary }}
children={keywords.length}
/>
<Button
onPress={() => setKeywords([...keywords, ''])}
type='icon'
content='plus'
round
/>
</View>
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
) )
} }

View File

@ -4,7 +4,6 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack'
import { TabMeProfileStackParamList, TabMeStackScreenProps } from '@utils/navigation/navigators' import { TabMeProfileStackParamList, TabMeStackScreenProps } from '@utils/navigation/navigators'
import React, { useRef } from 'react' import React, { useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { KeyboardAvoidingView, Platform } from 'react-native'
import FlashMessage from 'react-native-flash-message' import FlashMessage from 'react-native-flash-message'
import TabMeProfileFields from './Fields' import TabMeProfileFields from './Fields'
import TabMeProfileName from './Name' import TabMeProfileName from './Name'
@ -18,10 +17,7 @@ const TabMeProfile: React.FC<TabMeStackScreenProps<'Tab-Me-Switch'>> = ({ naviga
const messageRef = useRef<FlashMessage>(null) const messageRef = useRef<FlashMessage>(null)
return ( return (
<KeyboardAvoidingView <>
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}> <Stack.Navigator screenOptions={{ headerShadowVisible: false }}>
<Stack.Screen <Stack.Screen
name='Tab-Me-Profile-Root' name='Tab-Me-Profile-Root'
@ -55,7 +51,7 @@ const TabMeProfile: React.FC<TabMeStackScreenProps<'Tab-Me-Switch'>> = ({ naviga
</Stack.Navigator> </Stack.Navigator>
<Message ref={messageRef} /> <Message ref={messageRef} />
</KeyboardAvoidingView> </>
) )
} }

View File

@ -1,12 +1,13 @@
import AccountButton from '@components/AccountButton' import AccountButton from '@components/AccountButton'
import ComponentInstance from '@components/Instance' import ComponentInstance from '@components/Instance'
import { ModalScrollView } from '@components/ModalScrollView'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { getReadableAccounts } from '@utils/storage/actions' import { getReadableAccounts } from '@utils/storage/actions'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useRef } from 'react' import React, { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { KeyboardAvoidingView, Platform, View } from 'react-native' import { View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler' import { ScrollView } from 'react-native-gesture-handler'
const TabMeSwitch: React.FC = () => { const TabMeSwitch: React.FC = () => {
@ -20,63 +21,53 @@ const TabMeSwitch: React.FC = () => {
}, [scrollViewRef.current]) }, [scrollViewRef.current])
return ( return (
<KeyboardAvoidingView <ModalScrollView>
style={{ flex: 1 }} <View>
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} <CustomText
> fontStyle='M'
<ScrollView
ref={scrollViewRef}
style={{ marginBottom: StyleConstants.Spacing.L * 2 }}
keyboardShouldPersistTaps='always'
>
<View>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S,
color: colors.primaryDefault
}}
>
{t('me.switch.new')}
</CustomText>
<ComponentInstance scrollViewRef={scrollViewRef} disableHeaderImage goBack />
</View>
<View
style={{ style={{
marginTop: StyleConstants.Spacing.S, textAlign: 'center',
paddingTop: StyleConstants.Spacing.M, paddingVertical: StyleConstants.Spacing.S,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding, color: colors.primaryDefault
borderTopWidth: 1,
borderTopColor: colors.border
}} }}
> >
<CustomText {t('me.switch.new')}
fontStyle='M' </CustomText>
style={{ <ComponentInstance scrollViewRef={scrollViewRef} disableHeaderImage goBack />
textAlign: 'center', </View>
paddingVertical: StyleConstants.Spacing.S,
color: colors.primaryDefault <View
}} style={{
> marginTop: StyleConstants.Spacing.S,
{t('me.switch.existing')} paddingTop: StyleConstants.Spacing.M,
</CustomText> borderTopWidth: 1,
<View borderTopColor: colors.border
style={{ }}
flex: 1, >
flexDirection: 'row', <CustomText
flexWrap: 'wrap', fontStyle='M'
marginTop: StyleConstants.Spacing.M style={{
}} textAlign: 'center',
> paddingVertical: StyleConstants.Spacing.S,
{accounts.map((account, index) => { color: colors.primaryDefault
return <AccountButton key={index} account={account} /> }}
})} >
</View> {t('me.switch.existing')}
</CustomText>
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M
}}
>
{accounts.map((account, index) => {
return <AccountButton key={index} account={account} />
})}
</View> </View>
</ScrollView> </View>
</KeyboardAvoidingView> </ModalScrollView>
) )
} }

View File

@ -1,5 +1,6 @@
import ComponentAccount from '@components/Account' import ComponentAccount from '@components/Account'
import { HeaderLeft, HeaderRight } from '@components/Header' import { HeaderLeft, HeaderRight } from '@components/Header'
import { ModalScrollView } from '@components/ModalScrollView'
import Selections from '@components/Selections' import Selections from '@components/Selections'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import apiInstance from '@utils/api/instance' import apiInstance from '@utils/api/instance'
@ -11,7 +12,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Platform, ScrollView, TextInput, View } from 'react-native' import { Platform, TextInput, View } from 'react-native'
import { Switch } from 'react-native-gesture-handler' import { Switch } from 'react-native-gesture-handler'
const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>> = ({ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>> = ({
@ -96,7 +97,7 @@ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>>
}, [rulesQuery.data]) }, [rulesQuery.data])
return ( return (
<ScrollView> <ModalScrollView>
<View <View
style={{ style={{
margin: StyleConstants.Spacing.Global.PagePadding, margin: StyleConstants.Spacing.Global.PagePadding,
@ -209,7 +210,7 @@ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>>
/> />
) : null} ) : null}
</View> </View>
</ScrollView> </ModalScrollView>
) )
} }