Add "performant" recent album view

This commit is contained in:
Lei Nelissen
2020-06-25 18:07:44 +02:00
parent 623e267b52
commit 80ff88c3b2
11 changed files with 321 additions and 38 deletions

View File

@@ -0,0 +1,87 @@
import React, { useCallback, useRef, useState } from 'react';
import styled from 'styled-components/native';
import { ALPHABET_LETTERS } from 'CONSTANTS';
import { View, LayoutChangeEvent } from 'react-native';
import { TouchableWithoutFeedback, PanGestureHandler, PanGestureHandlerGestureEvent, TapGestureHandler, TapGestureHandlerGestureEvent } from 'react-native-gesture-handler';
interface LetterContainerProps {
onPress: (letter: string) => void;
letter: string;
}
const LetterContainer: React.FC<LetterContainerProps> = ({ children, letter, onPress }) => {
const handlePress = useCallback(() => {
onPress(letter);
}, [letter, onPress]);
return (
<TouchableWithoutFeedback onPress={handlePress}>
{children}
</TouchableWithoutFeedback>
);
};
const Container = styled.View`
position: absolute;
right: 5px;
top: 0;
height: 100%;
z-index: 10;
padding: 5px;
margin: auto 0;
justify-content: space-around;
`;
const Letter = styled.Text`
text-align: center;
padding: 1px 0;
`;
interface Props {
onSelect: (index: number) => void;
}
/**
* A generic component that introduces a scrolling bar on the right side of the
* screen with all letters of the Alphabet.
*/
const AlphabetScroller: React.FC<Props> = ({ onSelect }) => {
const [ height, setHeight ] = useState(0);
const [ index, setIndex ] = useState<number>();
// Handler for setting the correct height for a single alphabet item
const handleLayout = useCallback((event: LayoutChangeEvent) => {
setHeight(event.nativeEvent.layout.height);
}, []);
// Handler for passing on a new index when it is tapped or swiped
const handleGestureEvent = useCallback((event: PanGestureHandlerGestureEvent | TapGestureHandlerGestureEvent) => {
const newIndex = Math.floor(event.nativeEvent.y / height);
if (newIndex !== index) {
setIndex(newIndex);
onSelect(newIndex);
}
}, [height, index]);
return (
<Container>
<TapGestureHandler onHandlerStateChange={handleGestureEvent}>
<PanGestureHandler onGestureEvent={handleGestureEvent}>
<View>
{ALPHABET_LETTERS.split('').map((l, i) => (
<View
key={l}
onLayout={i === 0 ? handleLayout : undefined}
>
<Letter>{l}</Letter>
</View>
))}
</View>
</PanGestureHandler>
</TapGestureHandler>
</Container>
);
};
export default AlphabetScroller;