Add animations to post controls

zio/stable
Paul Frazee 2022-11-16 10:58:39 -06:00
parent 64d095a96b
commit dcf6a49715
1 changed files with 122 additions and 45 deletions

View File

@ -1,5 +1,12 @@
import React from 'react' import React from 'react'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import Animated, {
useSharedValue,
useAnimatedStyle,
withDelay,
withTiming,
interpolate,
} from 'react-native-reanimated'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {UpIcon, UpIconSolid, DownIcon, DownIconSolid} from '../../lib/icons' import {UpIcon, UpIconSolid, DownIcon, DownIconSolid} from '../../lib/icons'
import {s, colors} from '../../lib/styles' import {s, colors} from '../../lib/styles'
@ -19,48 +26,123 @@ interface PostCtrlsOpts {
} }
export function PostCtrls(opts: PostCtrlsOpts) { export function PostCtrls(opts: PostCtrlsOpts) {
const interp1 = useSharedValue<number>(0)
const interp2 = useSharedValue<number>(0)
const interp3 = useSharedValue<number>(0)
const anim1Style = useAnimatedStyle(() => ({
transform: [{scale: interpolate(interp1.value, [0, 1.0], [1.0, 3.0])}],
opacity: interpolate(interp1.value, [0, 1.0], [1.0, 0.0]),
}))
const anim2Style = useAnimatedStyle(() => ({
transform: [{scale: interpolate(interp2.value, [0, 1.0], [1.0, 3.0])}],
opacity: interpolate(interp2.value, [0, 1.0], [1.0, 0.0]),
}))
const anim3Style = useAnimatedStyle(() => ({
transform: [{scale: interpolate(interp3.value, [0, 1.0], [1.0, 3.0])}],
opacity: interpolate(interp3.value, [0, 1.0], [1.0, 0.0]),
}))
const onPressToggleRepostWrapper = () => {
if (!opts.isReposted) {
interp1.value = withTiming(1, {duration: 300}, () => {
interp1.value = withDelay(100, withTiming(0, {duration: 20}))
})
}
opts.onPressToggleRepost()
}
const onPressToggleUpvoteWrapper = () => {
if (!opts.isUpvoted) {
interp2.value = withTiming(1, {duration: 300}, () => {
interp2.value = withDelay(100, withTiming(0, {duration: 20}))
})
}
opts.onPressToggleUpvote()
}
const onPressToggleDownvoteWrapper = () => {
if (!opts.isDownvoted) {
interp3.value = withTiming(1, {duration: 300}, () => {
interp3.value = withDelay(100, withTiming(0, {duration: 20}))
})
}
opts.onPressToggleDownvote()
}
return ( return (
<View style={styles.ctrls}> <View style={styles.ctrls}>
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressReply}> <View style={s.flex1}>
<FontAwesomeIcon <TouchableOpacity style={styles.ctrl} onPress={opts.onPressReply}>
style={styles.ctrlIcon} <FontAwesomeIcon
icon={['far', 'comment']} style={styles.ctrlIcon}
size={14} icon={['far', 'comment']}
/> size={14}
<Text style={s.f13}>{opts.replyCount}</Text> />
</TouchableOpacity> <Text style={s.f13}>{opts.replyCount}</Text>
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleRepost}> </TouchableOpacity>
<FontAwesomeIcon </View>
style={opts.isReposted ? styles.ctrlIconReposted : styles.ctrlIcon} <View style={s.flex1}>
icon="retweet" <TouchableOpacity
size={18} onPress={onPressToggleRepostWrapper}
/> style={styles.ctrl}>
<Text style={opts.isReposted ? [s.bold, s.green3, s.f13] : s.f13}> <Animated.View style={anim1Style}>
{opts.repostCount} <FontAwesomeIcon
</Text> style={
</TouchableOpacity> opts.isReposted ? styles.ctrlIconReposted : styles.ctrlIcon
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleUpvote}> }
{opts.isUpvoted ? ( icon="retweet"
<UpIconSolid style={styles.ctrlIconUpvoted} size={18} /> size={18}
) : ( />
<UpIcon style={styles.ctrlIcon} size={18} /> </Animated.View>
)} <Text
<Text style={opts.isUpvoted ? [s.bold, s.red3, s.f13] : s.f13}> style={
{opts.upvoteCount} opts.isReposted
</Text> ? [s.bold, s.green3, s.f13, s.ml5]
</TouchableOpacity> : [s.f13, s.ml5]
<TouchableOpacity }>
style={styles.ctrl} {opts.repostCount}
onPress={opts.onPressToggleDownvote}> </Text>
{opts.isDownvoted ? ( </TouchableOpacity>
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} /> </View>
) : ( <View style={s.flex1}>
<DownIcon style={styles.ctrlIcon} size={18} /> <TouchableOpacity
)} style={styles.ctrl}
<Text style={opts.isDownvoted ? [s.bold, s.blue3, s.f13] : s.f13}> onPress={onPressToggleUpvoteWrapper}>
{opts.downvoteCount} <Animated.View style={anim2Style}>
</Text> {opts.isUpvoted ? (
</TouchableOpacity> <UpIconSolid style={styles.ctrlIconUpvoted} size={18} />
) : (
<UpIcon style={styles.ctrlIcon} size={18} />
)}
</Animated.View>
<Text
style={
opts.isUpvoted ? [s.bold, s.red3, s.f13, s.ml5] : [s.f13, s.ml5]
}>
{opts.upvoteCount}
</Text>
</TouchableOpacity>
</View>
<View style={s.flex1}>
<TouchableOpacity
style={styles.ctrl}
onPress={onPressToggleDownvoteWrapper}>
<Animated.View style={anim3Style}>
{opts.isDownvoted ? (
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} />
) : (
<DownIcon style={styles.ctrlIcon} size={18} />
)}
</Animated.View>
<Text
style={
opts.isDownvoted
? [s.bold, s.blue3, s.f13, s.ml5]
: [s.f13, s.ml5]
}>
{opts.downvoteCount}
</Text>
</TouchableOpacity>
</View>
</View> </View>
) )
} }
@ -72,24 +154,19 @@ const styles = StyleSheet.create({
ctrl: { ctrl: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
flex: 1,
paddingLeft: 4, paddingLeft: 4,
paddingRight: 4, paddingRight: 4,
}, },
ctrlIcon: { ctrlIcon: {
marginRight: 5,
color: colors.gray5, color: colors.gray5,
}, },
ctrlIconReposted: { ctrlIconReposted: {
marginRight: 5,
color: colors.green3, color: colors.green3,
}, },
ctrlIconUpvoted: { ctrlIconUpvoted: {
marginRight: 5,
color: colors.red3, color: colors.red3,
}, },
ctrlIconDownvoted: { ctrlIconDownvoted: {
marginRight: 5,
color: colors.blue3, color: colors.blue3,
}, },
}) })