Android fixes (#515)

* Fix profile screen performance on android and remove dead code

* Correctly handle android hardware back btn

* Fix EditProfile modal for android

* Fix lint
This commit is contained in:
Paul Frazee 2023-04-22 17:14:20 -05:00 committed by GitHub
parent eb6b36be61
commit d35f7c1f1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 273 additions and 594 deletions

View file

@ -1,12 +1,13 @@
import React, {useEffect, useState} from 'react'
import {View} from 'react-native'
import {Selector} from './Selector'
import {HorzSwipe} from './gestures/HorzSwipe'
import {Pressable, StyleSheet, View} from 'react-native'
import {FlatList} from './Views'
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
import {Text} from './text/Text'
import {usePalette} from 'lib/hooks/usePalette'
import {clamp} from 'lib/numbers'
import {s} from 'lib/styles'
import {s, colors} from 'lib/styles'
import {isAndroid} from 'platform/detection'
const HEADER_ITEM = {_reactKey: '__header__'}
const SELECTOR_ITEM = {_reactKey: '__selector__'}
@ -16,7 +17,6 @@ export function ViewSelector({
sections,
items,
refreshing,
swipeEnabled,
renderHeader,
renderItem,
ListFooterComponent,
@ -42,19 +42,12 @@ export function ViewSelector({
onEndReached?: (info: {distanceFromEnd: number}) => void
}) {
const [selectedIndex, setSelectedIndex] = useState<number>(0)
const panX = useAnimatedValue(0)
// events
// =
const onSwipeEnd = React.useCallback(
(dx: number) => {
if (dx !== 0) {
setSelectedIndex(clamp(selectedIndex + dx, 0, sections.length))
}
},
[setSelectedIndex, selectedIndex, sections],
)
const keyExtractor = React.useCallback(item => item._reactKey, [])
const onPressSelection = React.useCallback(
(index: number) => setSelectedIndex(clamp(index, 0, sections.length)),
[setSelectedIndex, sections],
@ -77,7 +70,6 @@ export function ViewSelector({
return (
<Selector
items={sections}
panX={panX}
selectedIndex={selectedIndex}
onSelect={onPressSelection}
/>
@ -86,7 +78,7 @@ export function ViewSelector({
return renderItem(item)
}
},
[sections, panX, selectedIndex, onPressSelection, renderHeader, renderItem],
[sections, selectedIndex, onPressSelection, renderHeader, renderItem],
)
const data = React.useMemo(
@ -94,28 +86,98 @@ export function ViewSelector({
[items],
)
return (
<HorzSwipe
hasPriority
panX={panX}
swipeEnabled={swipeEnabled || false}
canSwipeLeft={selectedIndex > 0}
canSwipeRight={selectedIndex < sections.length - 1}
onSwipeEnd={onSwipeEnd}>
<FlatList
data={data}
keyExtractor={item => item._reactKey}
renderItem={renderItemInternal}
ListFooterComponent={ListFooterComponent}
stickyHeaderIndices={STICKY_HEADER_INDICES}
refreshing={refreshing}
onScroll={onScroll}
onRefresh={onRefresh}
onEndReached={onEndReached}
onEndReachedThreshold={0.6}
contentContainerStyle={s.contentContainer}
removeClippedSubviews={true}
scrollIndicatorInsets={{right: 1}} // fixes a bug where the scroll indicator is on the middle of the screen https://github.com/bluesky-social/social-app/pull/464
/>
</HorzSwipe>
<FlatList
data={data}
keyExtractor={keyExtractor}
renderItem={renderItemInternal}
ListFooterComponent={ListFooterComponent}
// NOTE sticky header disabled on android due to major performance issues -prf
stickyHeaderIndices={isAndroid ? undefined : STICKY_HEADER_INDICES}
refreshing={refreshing}
onScroll={onScroll}
onRefresh={onRefresh}
onEndReached={onEndReached}
onEndReachedThreshold={0.6}
contentContainerStyle={s.contentContainer}
removeClippedSubviews={true}
scrollIndicatorInsets={{right: 1}} // fixes a bug where the scroll indicator is on the middle of the screen https://github.com/bluesky-social/social-app/pull/464
/>
)
}
export function Selector({
selectedIndex,
items,
onSelect,
}: {
selectedIndex: number
items: string[]
onSelect?: (index: number) => void
}) {
const pal = usePalette('default')
const borderColor = useColorSchemeStyle(
{borderColor: colors.black},
{borderColor: colors.white},
)
const onPressItem = (index: number) => {
onSelect?.(index)
}
return (
<View style={[pal.view, styles.outer]}>
{items.map((item, i) => {
const selected = i === selectedIndex
return (
<Pressable
testID={`selector-${i}`}
key={item}
onPress={() => onPressItem(i)}>
<View
style={[
styles.item,
selected && styles.itemSelected,
borderColor,
]}>
<Text
style={
selected
? [styles.labelSelected, pal.text]
: [styles.label, pal.textLight]
}>
{item}
</Text>
</View>
</Pressable>
)
})}
</View>
)
}
const styles = StyleSheet.create({
outer: {
flexDirection: 'row',
paddingHorizontal: 14,
},
item: {
marginRight: 14,
paddingHorizontal: 10,
paddingTop: 8,
paddingBottom: 12,
},
itemSelected: {
borderBottomWidth: 3,
},
label: {
fontWeight: '600',
},
labelSelected: {
fontWeight: '600',
},
underline: {
position: 'absolute',
height: 4,
bottom: 0,
},
})