Skip to content

Commit

Permalink
feat(mobile): optimize bottom sheet to prevent re-trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
bkdev98 committed Aug 21, 2024
1 parent 31422e8 commit 325a44b
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 236 deletions.
30 changes: 4 additions & 26 deletions apps/mobile/components/category/select-category-icon-field.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { BottomSheetBackdrop, BottomSheetModal } from '@gorhom/bottom-sheet'
import type { BottomSheetModal } from '@gorhom/bottom-sheet'
import { useMemo, useRef } from 'react'

import { useColorScheme } from '@/hooks/useColorScheme'
import {
CATEGORY_EXPENSE_ICONS,
CATEGORY_INCOME_ICONS,
} from '@/lib/icons/category-icons'
import { theme } from '@/lib/theme'
import { sleep } from '@/lib/utils'
import type { CategoryTypeType } from '@6pm/validation'
import { useController } from 'react-hook-form'
import { Keyboard } from 'react-native'
import { FullWindowOverlay } from 'react-native-screens'
import { BottomSheet } from '../common/bottom-sheet'
import GenericIcon from '../common/generic-icon'
import { IconGridSheet } from '../common/icon-grid-sheet'
import { Button } from '../ui/button'
Expand All @@ -26,7 +24,6 @@ export function SelectCategoryIconField({
type: CategoryTypeType
}) {
const sheetRef = useRef<BottomSheetModal>(null)
const { colorScheme } = useColorScheme()

const {
field: { onChange, onBlur, value },
Expand All @@ -51,26 +48,7 @@ export function SelectCategoryIconField({
>
<GenericIcon name={value} className="size-6 text-primary" />
</Button>
<BottomSheetModal
ref={sheetRef}
index={0}
enableDynamicSizing
enablePanDownToClose
enableDismissOnClose
keyboardBehavior="extend"
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<BottomSheet ref={sheetRef} index={0} enableDynamicSizing>
<IconGridSheet
icons={icons}
value={value}
Expand All @@ -82,7 +60,7 @@ export function SelectCategoryIconField({
onSelect?.(icon)
}}
/>
</BottomSheetModal>
</BottomSheet>
</>
)
}
50 changes: 50 additions & 0 deletions apps/mobile/components/common/bottom-sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useColorScheme } from '@/hooks/useColorScheme'
import { theme } from '@/lib/theme'
import {
BottomSheetBackdrop,
type BottomSheetBackdropProps,
BottomSheetModal,
type BottomSheetModalProps,
} from '@gorhom/bottom-sheet'
import type { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types'
import { forwardRef, useCallback } from 'react'
import { FullWindowOverlay } from 'react-native-screens'

export const BottomSheet = forwardRef<
BottomSheetModalMethods,
BottomSheetModalProps
>((props, ref) => {
const { colorScheme } = useColorScheme()

const backdropComponent = useCallback(
(props: BottomSheetBackdropProps) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
),
[],
)

const containerComponent = useCallback(
(props: { children?: React.ReactNode }) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
),
[],
)

return (
<BottomSheetModal
ref={ref}
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
backdropComponent={backdropComponent}
containerComponent={containerComponent}
keyboardBehavior="extend"
enablePanDownToClose
enableDismissOnClose
{...props}
/>
)
})
33 changes: 4 additions & 29 deletions apps/mobile/components/common/date-picker.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { useColorScheme } from '@/hooks/useColorScheme'
import { formatDateShort } from '@/lib/date'
import { theme } from '@/lib/theme'
import { sleep } from '@/lib/utils'
import {
BottomSheetBackdrop,
BottomSheetModal,
BottomSheetView,
} from '@gorhom/bottom-sheet'
import { type BottomSheetModal, BottomSheetView } from '@gorhom/bottom-sheet'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import DateTimePicker from '@react-native-community/datetimepicker'
Expand All @@ -15,9 +9,9 @@ import { Calendar } from 'lucide-react-native'
import { useRef, useState } from 'react'
import { Keyboard, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { FullWindowOverlay } from 'react-native-screens'
import { Button } from '../ui/button'
import { Text } from '../ui/text'
import { BottomSheet } from './bottom-sheet'

function SpinnerDatePicker({
value,
Expand Down Expand Up @@ -70,7 +64,6 @@ export function DatePicker({
minimumDate?: Date
}) {
const { bottom } = useSafeAreaInsets()
const { colorScheme } = useColorScheme()
const sheetRef = useRef<BottomSheetModal>(null)

return (
Expand All @@ -87,25 +80,7 @@ export function DatePicker({
<Calendar className="h-5 w-5 text-primary" />
<Text>{formatDateShort(value)}</Text>
</Button>
<BottomSheetModal
ref={sheetRef}
index={0}
enableDynamicSizing
enablePanDownToClose
keyboardBehavior="extend"
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<BottomSheet ref={sheetRef} index={0} enableDynamicSizing>
<BottomSheetView
style={{
paddingBottom: bottom,
Expand All @@ -122,7 +97,7 @@ export function DatePicker({
minimumDate={minimumDate}
/>
</BottomSheetView>
</BottomSheetModal>
</BottomSheet>
</>
)
}
55 changes: 6 additions & 49 deletions apps/mobile/components/common/date-range-picker.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { useColorScheme } from '@/hooks/useColorScheme'
import { formatDateShort } from '@/lib/date'
import { theme } from '@/lib/theme'
import { cn, sleep } from '@/lib/utils'
import {
BottomSheetBackdrop,
BottomSheetModal,
BottomSheetView,
} from '@gorhom/bottom-sheet'
import { type BottomSheetModal, BottomSheetView } from '@gorhom/bottom-sheet'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import DateTimePicker from '@react-native-community/datetimepicker'
Expand All @@ -17,9 +11,9 @@ import { ArrowRightIcon } from 'lucide-react-native'
import { useRef, useState } from 'react'
import { Keyboard, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { FullWindowOverlay } from 'react-native-screens'
import { Button } from '../ui/button'
import { Text } from '../ui/text'
import { BottomSheet } from './bottom-sheet'

function SpinnerDatePicker({
value,
Expand Down Expand Up @@ -78,7 +72,6 @@ export function DateRangePicker({
}) {
const { i18n } = useLingui()
const { bottom } = useSafeAreaInsets()
const { colorScheme } = useColorScheme()
const sheetFromRef = useRef<BottomSheetModal>(null)
const sheetToRef = useRef<BottomSheetModal>(null)
const [fromDate, toDate] = value ?? []
Expand Down Expand Up @@ -118,25 +111,7 @@ export function DateRangePicker({
</Text>
</Button>
</View>
<BottomSheetModal
ref={sheetFromRef}
index={0}
enableDynamicSizing
enablePanDownToClose
keyboardBehavior="extend"
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<BottomSheet ref={sheetFromRef} index={0} enableDynamicSizing>
<BottomSheetView
style={{
paddingBottom: bottom,
Expand All @@ -160,26 +135,8 @@ export function DateRangePicker({
minimumDate={minimumDate}
/>
</BottomSheetView>
</BottomSheetModal>
<BottomSheetModal
ref={sheetToRef}
index={0}
enableDynamicSizing
enablePanDownToClose
keyboardBehavior="extend"
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
</BottomSheet>
<BottomSheet ref={sheetToRef} index={0} enableDynamicSizing>
<BottomSheetView
style={{
paddingBottom: bottom,
Expand All @@ -197,7 +154,7 @@ export function DateRangePicker({
minimumDate={fromDate ? addDays(fromDate, 1) : minimumDate}
/>
</BottomSheetView>
</BottomSheetModal>
</BottomSheet>
</>
)
}
32 changes: 5 additions & 27 deletions apps/mobile/components/form-fields/currency-field.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { BottomSheetBackdrop, BottomSheetModal } from '@gorhom/bottom-sheet'
import { useRef } from 'react'

import { useColorScheme } from '@/hooks/useColorScheme'
import { theme } from '@/lib/theme'
import { cn } from '@/lib/utils'
import type { BottomSheetModal } from '@gorhom/bottom-sheet'
import { useRef } from 'react'
import { Keyboard } from 'react-native'
import { FullWindowOverlay } from 'react-native-screens'
import { BottomSheet } from '../common/bottom-sheet'
import { CurrencySheetList } from '../common/currency-sheet'
import { Button } from '../ui/button'
import { Text } from '../ui/text'
Expand All @@ -20,7 +17,6 @@ export function CurrencyField({
className?: string
}) {
const sheetRef = useRef<BottomSheetModal>(null)
const { colorScheme } = useColorScheme()
return (
<>
<Button
Expand All @@ -36,33 +32,15 @@ export function CurrencyField({
>
<Text className="font-normal text-primary text-sm">{value}</Text>
</Button>
<BottomSheetModal
ref={sheetRef}
index={0}
snapPoints={['50%', '87%']}
enablePanDownToClose
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
keyboardBehavior="extend"
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<BottomSheet ref={sheetRef} index={0} snapPoints={['50%', '87%']}>
<CurrencySheetList
value={value}
onSelect={(currency) => {
onChange?.(currency.code)
setTimeout(() => sheetRef.current?.close(), 200)
}}
/>
</BottomSheetModal>
</BottomSheet>
</>
)
}
Loading

0 comments on commit 325a44b

Please sign in to comment.