Skip to content

Commit

Permalink
Merge pull request #3082 from digitalfabrik/1258-bottom-sheet-scrolling
Browse files Browse the repository at this point in the history
2189: Refactor and upgrade pois and bottom sheet
  • Loading branch information
steffenkleinle authored Feb 18, 2025
2 parents 88903c9 + 9f2c916 commit 9b3507b
Show file tree
Hide file tree
Showing 15 changed files with 271 additions and 237 deletions.
2 changes: 1 addition & 1 deletion native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"dependencies": {
"@dr.pogodin/react-native-static-server": "^0.5.5",
"@dr.pogodin/react-native-webview": "^13.13.0",
"@gorhom/bottom-sheet": "^4.6.4",
"@gorhom/bottom-sheet": "^5.0.6",
"@maplibre/maplibre-react-native": "^9.1.0",
"@notifee/react-native": "^9.1.8",
"@react-native-async-storage/async-storage": "^2.0.0",
Expand Down
70 changes: 0 additions & 70 deletions native/src/components/BottomActionsSheet.tsx

This file was deleted.

15 changes: 15 additions & 0 deletions native/src/components/BottomSheetHandle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { ReactElement } from 'react'
import styled from 'styled-components/native'

const Handle = styled.View`
width: 34px;
border: 1px solid ${props => props.theme.colors.textSecondaryColor};
background-color: ${props => props.theme.colors.textSecondaryColor};
border-radius: 10px;
align-self: center;
margin: 20px 0;
`

const BottomSheetHandle = (): ReactElement => <Handle />

export default BottomSheetHandle
39 changes: 0 additions & 39 deletions native/src/components/BottomSheetHandler.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion native/src/components/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import { FlatList, RefreshControl, ViewStyle } from 'react-native'
import styled from 'styled-components/native'

const NoItemsMessage = styled.Text`
export const NoItemsMessage = styled.Text`
color: ${props => props.theme.colors.textColor};
font-family: ${props => props.theme.fonts.native.contentFontRegular};
align-self: center;
Expand Down
9 changes: 3 additions & 6 deletions native/src/components/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ type MapViewProps = {
selectedFeature: MapFeature | null
userLocation: LocationType | null
setUserLocation: (userLocation: LocationType | null) => void
iconPosition: string | number
selectFeature: (feature: MapFeature | null) => void
setSheetSnapPointIndex: (index: number) => void
bottomSheetHeight: number
bottomSheetFullscreen: boolean
zoom: number | undefined
Overlay?: ReactElement
}
Expand All @@ -78,13 +77,12 @@ const MapView = ({
boundingBox,
features,
selectedFeature,
iconPosition,
userLocation,
setUserLocation,
selectFeature,
setSheetSnapPointIndex,
Overlay,
bottomSheetHeight,
bottomSheetFullscreen,
zoom,
}: MapViewProps): ReactElement => {
const cameraRef = useRef<MapLibreGL.Camera>(null)
Expand Down Expand Up @@ -158,7 +156,6 @@ const MapView = ({

const feature = featureCollection?.features.find((it): it is MapFeature => it.geometry.type === 'Point')
selectFeature(feature ?? null)
setSheetSnapPointIndex(1)

zoomOnClusterPress(pressedCoordinates)
}
Expand Down Expand Up @@ -202,7 +199,7 @@ const MapView = ({
<StyledIcon
icon={<Icon Icon={locationPermissionIcon} />}
onPress={onRequestLocation}
position={iconPosition}
position={bottomSheetFullscreen ? 0 : bottomSheetHeight}
accessibilityLabel={t('showOwnLocation')}
/>
</MapContainer>
Expand Down
2 changes: 1 addition & 1 deletion native/src/components/PoiListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const StyledPressable = styled(Pressable)<{ language: string }>`
border-bottom-width: 1px;
border-bottom-color: ${props => props.theme.colors.textDisabledColor};
flex-direction: ${props => contentDirection(props.language)};
padding: 24px 0;
padding: 16px 0;
`

const Description = styled.View`
Expand Down
117 changes: 117 additions & 0 deletions native/src/components/PoisBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import BottomSheet, {
BottomSheetFlatList,
BottomSheetFlatListMethods,
BottomSheetScrollView,
} from '@gorhom/bottom-sheet'
import React, { memo, ReactElement, Ref } from 'react'
import { useTranslation } from 'react-i18next'
import { Platform } from 'react-native'
import styled from 'styled-components/native'

import { LocationType } from 'shared'
import { ErrorCode, PoiModel } from 'shared/api'

import useCityAppContext from '../hooks/useCityAppContext'
import BottomSheetHandle from './BottomSheetHandle'
import Failure from './Failure'
import { NoItemsMessage } from './List'
import PoiDetails from './PoiDetails'
import PoiListItem from './PoiListItem'

const StyledBottomSheet = styled(BottomSheet)<{ isFullscreen: boolean }>`
${props => props.isFullscreen && `background-color: ${props.theme.colors.backgroundColor};`}
`

const BottomSheetContent = styled.View`
flex: 1;
margin: 0 24px;
`

const Title = styled.Text`
color: ${props => props.theme.colors.textColor};
font-family: ${props => props.theme.fonts.native.decorativeFontBold};
font-size: 18px;
font-weight: bold;
`

type PoiBottomSheetProps = {
poiListRef: Ref<BottomSheetFlatListMethods>
pois: PoiModel[]
poi: PoiModel | undefined
userLocation: LocationType | null
slug: string | undefined
selectPoi: (poi: PoiModel) => void
deselectAll: () => void
snapPoints: number[]
snapPointIndex: number
setSnapPointIndex: (index: number) => void
setScrollPosition: (position: number) => void
isFullscreen: boolean
}

const PoisBottomSheet = ({
poiListRef,
pois,
poi,
userLocation,
slug,
selectPoi,
deselectAll,
snapPoints,
snapPointIndex,
setSnapPointIndex,
setScrollPosition,
isFullscreen,
}: PoiBottomSheetProps): ReactElement | null => {
const { languageCode } = useCityAppContext()
const { t } = useTranslation('pois')
// ios has scrolling issues if content panning gesture is not enabled
const enableContentPanningGesture = Platform.OS === 'ios' || !isFullscreen

const PoiDetail = poi ? (
<PoiDetails language={languageCode} poi={poi} distance={userLocation && poi.distance(userLocation)} />
) : (
<Failure code={ErrorCode.PageNotFound} buttonAction={deselectAll} buttonLabel={t('detailsHeader')} />
)

const renderPoiListItem = ({ item: poi }: { item: PoiModel }): ReactElement => (
<PoiListItem
key={poi.path}
poi={poi}
language={languageCode}
navigateToPoi={() => selectPoi(poi)}
distance={userLocation && poi.distance(userLocation)}
/>
)

return (
<StyledBottomSheet
index={snapPointIndex}
isFullscreen={isFullscreen}
snapPoints={snapPoints}
enableContentPanningGesture={enableContentPanningGesture}
enableDynamicSizing={false}
animateOnMount
handleComponent={BottomSheetHandle}
onChange={setSnapPointIndex}>
<BottomSheetContent>
{slug ? (
<BottomSheetScrollView showsVerticalScrollIndicator={false}>{PoiDetail}</BottomSheetScrollView>
) : (
<BottomSheetFlatList
ref={poiListRef}
data={pois}
role='list'
renderItem={renderPoiListItem}
onMomentumScrollBegin={event => setScrollPosition(event.nativeEvent.contentOffset.y)}
showsVerticalScrollIndicator={false}
ListHeaderComponent={<Title>{t('listTitle')}</Title>}
ListEmptyComponent={<NoItemsMessage>{t('noPois')}</NoItemsMessage>}
/>
)}
</BottomSheetContent>
</StyledBottomSheet>
)
}

export default memo(PoisBottomSheet)
5 changes: 0 additions & 5 deletions native/src/components/__mocks__/BottomActionsSheet.tsx

This file was deleted.

Loading

0 comments on commit 9b3507b

Please sign in to comment.