Switch to react-native default animation tools for composer and post controls
parent
ae522c86fe
commit
79d5708b69
|
@ -1,16 +1,12 @@
|
||||||
import React, {useEffect} from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import {
|
import {
|
||||||
useWindowDimensions,
|
Animated,
|
||||||
Text,
|
Text,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
|
useWindowDimensions,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import Animated, {
|
import {useAnimatedValue} from '../../lib/useAnimatedValue'
|
||||||
useSharedValue,
|
|
||||||
useAnimatedStyle,
|
|
||||||
withTiming,
|
|
||||||
interpolate,
|
|
||||||
} from 'react-native-reanimated'
|
|
||||||
import {colors} from '../../lib/styles'
|
import {colors} from '../../lib/styles'
|
||||||
|
|
||||||
interface AutocompleteItem {
|
interface AutocompleteItem {
|
||||||
|
@ -28,23 +24,22 @@ export function Autocomplete({
|
||||||
onSelect: (item: string) => void
|
onSelect: (item: string) => void
|
||||||
}) {
|
}) {
|
||||||
const winDim = useWindowDimensions()
|
const winDim = useWindowDimensions()
|
||||||
const positionInterp = useSharedValue<number>(0)
|
const positionInterp = useAnimatedValue(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (active) {
|
Animated.timing(positionInterp, {
|
||||||
positionInterp.value = withTiming(1, {duration: 250})
|
toValue: active ? 1 : 0,
|
||||||
} else {
|
duration: 200,
|
||||||
positionInterp.value = withTiming(0, {duration: 250})
|
useNativeDriver: false,
|
||||||
}
|
}).start()
|
||||||
}, [positionInterp, active])
|
}, [positionInterp, active])
|
||||||
|
|
||||||
const topAnimStyle = useAnimatedStyle(() => ({
|
const topAnimStyle = {
|
||||||
top: interpolate(
|
top: positionInterp.interpolate({
|
||||||
positionInterp.value,
|
inputRange: [0, 1],
|
||||||
[0, 1.0],
|
outputRange: [winDim.height, winDim.height / 4],
|
||||||
[winDim.height, winDim.height / 4],
|
}),
|
||||||
),
|
}
|
||||||
}))
|
|
||||||
return (
|
return (
|
||||||
<Animated.View style={[styles.outer, topAnimStyle]}>
|
<Animated.View style={[styles.outer, topAnimStyle]}>
|
||||||
{items.map((item, i) => (
|
{items.map((item, i) => (
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
import {Animated, 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} from '../../lib/icons'
|
import {UpIcon, UpIconSolid} from '../../lib/icons'
|
||||||
import {s, colors} from '../../lib/styles'
|
import {s, colors} from '../../lib/styles'
|
||||||
|
import {useAnimatedValue} from '../../lib/useAnimatedValue'
|
||||||
|
|
||||||
interface PostCtrlsOpts {
|
interface PostCtrlsOpts {
|
||||||
big?: boolean
|
big?: boolean
|
||||||
|
@ -28,31 +22,71 @@ const sRedgray = {color: redgray}
|
||||||
const HITSLOP = {top: 10, left: 10, bottom: 10, right: 10}
|
const HITSLOP = {top: 10, left: 10, bottom: 10, right: 10}
|
||||||
|
|
||||||
export function PostCtrls(opts: PostCtrlsOpts) {
|
export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
const interp1 = useSharedValue<number>(0)
|
const interp1 = useAnimatedValue(0)
|
||||||
const interp2 = useSharedValue<number>(0)
|
const interp2 = useAnimatedValue(0)
|
||||||
|
|
||||||
const anim1Style = useAnimatedStyle(() => ({
|
const anim1Style = {
|
||||||
transform: [{scale: interpolate(interp1.value, [0, 1.0], [1.0, 4.0])}],
|
transform: [
|
||||||
opacity: interpolate(interp1.value, [0, 1.0], [1.0, 0.0]),
|
{
|
||||||
}))
|
scale: interp1.interpolate({
|
||||||
const anim2Style = useAnimatedStyle(() => ({
|
inputRange: [0, 1.0],
|
||||||
transform: [{scale: interpolate(interp2.value, [0, 1.0], [1.0, 4.0])}],
|
outputRange: [1.0, 4.0],
|
||||||
opacity: interpolate(interp2.value, [0, 1.0], [1.0, 0.0]),
|
}),
|
||||||
}))
|
},
|
||||||
|
],
|
||||||
|
opacity: interp1.interpolate({
|
||||||
|
inputRange: [0, 1.0],
|
||||||
|
outputRange: [1.0, 0.0],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
const anim2Style = {
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
scale: interp2.interpolate({
|
||||||
|
inputRange: [0, 1.0],
|
||||||
|
outputRange: [1.0, 4.0],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
opacity: interp2.interpolate({
|
||||||
|
inputRange: [0, 1.0],
|
||||||
|
outputRange: [1.0, 0.0],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
const onPressToggleRepostWrapper = () => {
|
const onPressToggleRepostWrapper = () => {
|
||||||
if (!opts.isReposted) {
|
if (!opts.isReposted) {
|
||||||
interp1.value = withTiming(1, {duration: 400}, () => {
|
Animated.sequence([
|
||||||
interp1.value = withDelay(100, withTiming(0, {duration: 20}))
|
Animated.timing(interp1, {
|
||||||
})
|
toValue: 1,
|
||||||
|
duration: 400,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
Animated.delay(100),
|
||||||
|
Animated.timing(interp1, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 20,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
]).start()
|
||||||
}
|
}
|
||||||
opts.onPressToggleRepost()
|
opts.onPressToggleRepost()
|
||||||
}
|
}
|
||||||
const onPressToggleUpvoteWrapper = () => {
|
const onPressToggleUpvoteWrapper = () => {
|
||||||
if (!opts.isUpvoted) {
|
if (!opts.isUpvoted) {
|
||||||
interp2.value = withTiming(1, {duration: 400}, () => {
|
Animated.sequence([
|
||||||
interp2.value = withDelay(100, withTiming(0, {duration: 20}))
|
Animated.timing(interp2, {
|
||||||
})
|
toValue: 1,
|
||||||
|
duration: 400,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
Animated.delay(100),
|
||||||
|
Animated.timing(interp2, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 20,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
]).start()
|
||||||
}
|
}
|
||||||
opts.onPressToggleUpvote()
|
opts.onPressToggleUpvote()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
import {Animated} from 'react-native'
|
||||||
|
|
||||||
|
export function useAnimatedValue(initialValue: number) {
|
||||||
|
const lazyRef = React.useRef<Animated.Value>()
|
||||||
|
|
||||||
|
if (lazyRef.current === undefined) {
|
||||||
|
lazyRef.current = new Animated.Value(initialValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lazyRef.current as Animated.Value
|
||||||
|
}
|
|
@ -1,15 +1,9 @@
|
||||||
import React, {useEffect} from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {Animated, Easing, StyleSheet, View} from 'react-native'
|
||||||
import Animated, {
|
|
||||||
useSharedValue,
|
|
||||||
useAnimatedStyle,
|
|
||||||
withTiming,
|
|
||||||
interpolate,
|
|
||||||
Easing,
|
|
||||||
} from 'react-native-reanimated'
|
|
||||||
import {ComposePost} from '../../com/composer/ComposePost'
|
import {ComposePost} from '../../com/composer/ComposePost'
|
||||||
import {ComposerOpts} from '../../../state/models/shell-ui'
|
import {ComposerOpts} from '../../../state/models/shell-ui'
|
||||||
|
import {useAnimatedValue} from '../../lib/useAnimatedValue'
|
||||||
|
|
||||||
export const Composer = observer(
|
export const Composer = observer(
|
||||||
({
|
({
|
||||||
|
@ -25,21 +19,30 @@ export const Composer = observer(
|
||||||
onPost?: ComposerOpts['onPost']
|
onPost?: ComposerOpts['onPost']
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}) => {
|
}) => {
|
||||||
const initInterp = useSharedValue<number>(0)
|
const initInterp = useAnimatedValue(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (active) {
|
if (active) {
|
||||||
initInterp.value = withTiming(1, {
|
Animated.timing(initInterp, {
|
||||||
|
toValue: 1,
|
||||||
duration: 300,
|
duration: 300,
|
||||||
easing: Easing.out(Easing.exp),
|
easing: Easing.out(Easing.exp),
|
||||||
})
|
useNativeDriver: true,
|
||||||
|
}).start()
|
||||||
} else {
|
} else {
|
||||||
initInterp.value = 0
|
initInterp.setValue(0)
|
||||||
}
|
}
|
||||||
}, [initInterp, active])
|
}, [initInterp, active])
|
||||||
const wrapperAnimStyle = useAnimatedStyle(() => ({
|
const wrapperAnimStyle = {
|
||||||
top: interpolate(initInterp.value, [0, 1.0], [winHeight, 0]),
|
transform: [
|
||||||
}))
|
{
|
||||||
|
translateY: initInterp.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [winHeight, 0],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
// events
|
// events
|
||||||
// =
|
// =
|
||||||
|
|
Loading…
Reference in New Issue