Add animations to post controls
parent
64d095a96b
commit
dcf6a49715
|
@ -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,8 +26,51 @@ 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}>
|
||||||
|
<View style={s.flex1}>
|
||||||
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressReply}>
|
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressReply}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
style={styles.ctrlIcon}
|
style={styles.ctrlIcon}
|
||||||
|
@ -29,39 +79,71 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
/>
|
/>
|
||||||
<Text style={s.f13}>{opts.replyCount}</Text>
|
<Text style={s.f13}>{opts.replyCount}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleRepost}>
|
</View>
|
||||||
|
<View style={s.flex1}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={onPressToggleRepostWrapper}
|
||||||
|
style={styles.ctrl}>
|
||||||
|
<Animated.View style={anim1Style}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
style={opts.isReposted ? styles.ctrlIconReposted : styles.ctrlIcon}
|
style={
|
||||||
|
opts.isReposted ? styles.ctrlIconReposted : styles.ctrlIcon
|
||||||
|
}
|
||||||
icon="retweet"
|
icon="retweet"
|
||||||
size={18}
|
size={18}
|
||||||
/>
|
/>
|
||||||
<Text style={opts.isReposted ? [s.bold, s.green3, s.f13] : s.f13}>
|
</Animated.View>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
opts.isReposted
|
||||||
|
? [s.bold, s.green3, s.f13, s.ml5]
|
||||||
|
: [s.f13, s.ml5]
|
||||||
|
}>
|
||||||
{opts.repostCount}
|
{opts.repostCount}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleUpvote}>
|
</View>
|
||||||
|
<View style={s.flex1}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.ctrl}
|
||||||
|
onPress={onPressToggleUpvoteWrapper}>
|
||||||
|
<Animated.View style={anim2Style}>
|
||||||
{opts.isUpvoted ? (
|
{opts.isUpvoted ? (
|
||||||
<UpIconSolid style={styles.ctrlIconUpvoted} size={18} />
|
<UpIconSolid style={styles.ctrlIconUpvoted} size={18} />
|
||||||
) : (
|
) : (
|
||||||
<UpIcon style={styles.ctrlIcon} size={18} />
|
<UpIcon style={styles.ctrlIcon} size={18} />
|
||||||
)}
|
)}
|
||||||
<Text style={opts.isUpvoted ? [s.bold, s.red3, s.f13] : s.f13}>
|
</Animated.View>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
opts.isUpvoted ? [s.bold, s.red3, s.f13, s.ml5] : [s.f13, s.ml5]
|
||||||
|
}>
|
||||||
{opts.upvoteCount}
|
{opts.upvoteCount}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<View style={s.flex1}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.ctrl}
|
style={styles.ctrl}
|
||||||
onPress={opts.onPressToggleDownvote}>
|
onPress={onPressToggleDownvoteWrapper}>
|
||||||
|
<Animated.View style={anim3Style}>
|
||||||
{opts.isDownvoted ? (
|
{opts.isDownvoted ? (
|
||||||
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} />
|
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} />
|
||||||
) : (
|
) : (
|
||||||
<DownIcon style={styles.ctrlIcon} size={18} />
|
<DownIcon style={styles.ctrlIcon} size={18} />
|
||||||
)}
|
)}
|
||||||
<Text style={opts.isDownvoted ? [s.bold, s.blue3, s.f13] : s.f13}>
|
</Animated.View>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
opts.isDownvoted
|
||||||
|
? [s.bold, s.blue3, s.f13, s.ml5]
|
||||||
|
: [s.f13, s.ml5]
|
||||||
|
}>
|
||||||
{opts.downvoteCount}
|
{opts.downvoteCount}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</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,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue