Skip to content

Instantly share code, notes, and snippets.

@daveham
Created February 13, 2020 20:09
Show Gist options
  • Save daveham/e3860b18fba64d9dbf26b55790d025cb to your computer and use it in GitHub Desktop.
Save daveham/e3860b18fba64d9dbf26b55790d025cb to your computer and use it in GitHub Desktop.
My animation attempt at TextNumbers/index.js
// External Dependencies
import { ActivityIndicator, Divider } from 'react-native-paper';
import { Animated, StyleSheet, View } from 'react-native';
import { DrawerItems } from 'react-navigation-drawer';
import { NavigationContext } from 'react-navigation';
import React, { useContext, useEffect, useRef, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
// Internal Dependencies
import { changeParamsConversations } from '../state/conversations/actions';
import { changeParamsTextNumbers } from '../state/text-numbers/actions';
import {
isGetting as isGettingTextNumbersSelector,
textNumbers as textNumbersSelector,
textNumbersData as textNumbersDataSelector,
} from '../state/text-numbers/selectors';
import ListItem from '../shared/ListItem';
import ListSubheader from '../shared/ListSubheader';
import { theme } from '../shared';
import usePrevious from '../shared/usePreviousHook';
// local variables
const itemHeight = 48.5;
// Component Definition
const TextNumbers = (props) => {
const dispatch = useDispatch();
const navigation = useContext(NavigationContext);
const emptyNumbers = [];
const textNumbers = useSelector(textNumbersSelector) || emptyNumbers;
const textNumbersData = useSelector(textNumbersDataSelector);
const isGettingTextNumbers = useSelector(isGettingTextNumbersSelector);
const [isShowingMore, setIsShowingMore] = useState(false);
const lowerSizeLimit = useRef(0);
const upperSizeLimit = useRef(0);
// Keep a separate copy of the text numbers for when we need to render
// prior batch while animating "out" of view.
const [renderedNumbers, setRenderedNumbers] = useState(textNumbers);
const textNumbersLength = textNumbers.length;
const previousNumbersLength = usePrevious(textNumbersLength);
const animation = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (textNumbersLength === previousNumbersLength) {
return;
}
if (isShowingMore) {
if (textNumbersLength) {
upperSizeLimit.current = textNumbers.length * itemHeight;
} else {
upperSizeLimit.current = lowerSizeLimit.current;
}
setRenderedNumbers([...textNumbers]);
animation.setValue(lowerSizeLimit.current);
// Animated.spring(animation, {
// toValue: upperSizeLimit.current,
// overshootClamping: true,
// bounciness: 6,
// speed: 4,
// }).start();
Animated.timing(animation, {
duration: 350,
toValue: upperSizeLimit.current,
}).start();
} else {
if (textNumbersLength) {
lowerSizeLimit.current = textNumbers.length * itemHeight;
}
if (!renderedNumbers.length) {
setRenderedNumbers([...textNumbers]);
}
animation.setValue(upperSizeLimit.current);
// Animated.spring(animation, {
// toValue: lowerSizeLimit.current,
// overshootClamping: true,
// bounciness: 6,
// speed: 4,
// }).start(() => {
// setRenderedNumbers([...textNumbers]);
// });
Animated.timing(animation, {
duration: 350,
toValue: lowerSizeLimit.current,
}).start(() => {
setRenderedNumbers([...textNumbers]);
});
}
}, [isShowingMore, textNumbers]);
const handleNavigate = (route, params) => () => {
// TODO: Once more routes are create, create a default function that
// calls the 'navigate' function
dispatch(changeParamsConversations(params));
return navigation.closeDrawer();
};
const renderTextNumbers = () => {
if (!textNumbers) return null;
return renderedNumbers.map((textNumber) => (
<ListItem
key={textNumber.TextNumberID}
label={textNumber.Name || textNumber.TextPhoneNumber}
leftIcon={textNumber.FlatRateConversation ? 'infinity' : 'deskphone'}
count={textNumber.UnreadCount > 99 ? '99+' : textNumber.UnreadCount}
onPress={handleNavigate('Home', {
textNumberId: textNumber.TextNumberID,
})}
style={styles.item}
/>
));
};
const toggleShowMore = () => {
if (isShowingMore) {
setIsShowingMore(false);
dispatch(changeParamsTextNumbers({ pagesize: 5 }));
} else {
setIsShowingMore(true);
dispatch(changeParamsTextNumbers({ pagesize: textNumbersData.Size }));
}
};
const renderListItem = () => {
if (!textNumbersData || textNumbersData.Size < 4) return null;
// this is the value as measured from phone number items in the list
return isGettingTextNumbers ? (
<ActivityIndicator
animating
color={theme.colors.primary}
style={styles.item}
/>
) : (
<ListItem
iconSize={24}
label={isShowingMore ? 'Show Less' : 'Show More'}
leftIcon={isShowingMore ? 'chevron-up' : 'chevron-down'}
onPress={() => toggleShowMore()}
style={styles.item}
/>
);
};
// eslint-disable-next-line
const navigationDrawerItems = <DrawerItems {...props} />;
return (
<View>
<Divider />
<ListSubheader text="Text Numbers" />
<Animated.View style={[styles.numbersContainer, { height: animation }]}>
{renderTextNumbers()}
</Animated.View>
{renderListItem()}
<Divider />
</View>
);
};
const styles = StyleSheet.create({
item: {
height: itemHeight,
},
numbersContainer: {
overflow: 'hidden',
backgroundColor: theme.colors.surface,
},
});
export default TextNumbers;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment