diff options
author | Paul Frazee <pfrazee@gmail.com> | 2024-07-03 19:05:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-04 03:05:19 +0100 |
commit | 0ed99b840d8de13465f010a6434dea50c72b3f62 (patch) | |
tree | 75ebec28653a081793ca0cbca0c428a816980c6a /src/components/anim | |
parent | aa7117edb60711a67464f7559118334185f01680 (diff) | |
download | voidsky-0ed99b840d8de13465f010a6434dea50c72b3f62.tar.zst |
New user progress guides (#4716)
* Add the animated checkmark svg * Add progress guide list and task components * Add ProgressGuide Toast component * Implement progress-guide controller * Add 7 follows to the progress guide * Wire up action captures * Wire up progress-guide persistence * Trigger progress guide on account creation * Clear the progress guide from storage on complete * Add progress guide interstitial, put behind gate * Fix: read progress guide state from prefs * Some defensive type checks * Create separate toast for completion * List tweaks * Only show on Discover * Spacing and progress tweaks * Completely hide when complete * Capture the progress guide in local state, and only render toasts while guide is active * Fix: ensure persisted hydrates into local state * Gate --------- Co-authored-by: Eric Bailey <git@esb.lol> Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'src/components/anim')
-rw-r--r-- | src/components/anim/AnimatedCheck.tsx | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/components/anim/AnimatedCheck.tsx b/src/components/anim/AnimatedCheck.tsx new file mode 100644 index 000000000..7fdfc14cf --- /dev/null +++ b/src/components/anim/AnimatedCheck.tsx @@ -0,0 +1,92 @@ +import React from 'react' +import Animated, { + Easing, + useAnimatedProps, + useSharedValue, + withDelay, + withTiming, +} from 'react-native-reanimated' +import Svg, {Circle, Path} from 'react-native-svg' + +import {Props, useCommonSVGProps} from '#/components/icons/common' + +const AnimatedPath = Animated.createAnimatedComponent(Path) +const AnimatedCircle = Animated.createAnimatedComponent(Circle) + +const PATH = 'M14.1 27.2l7.1 7.2 16.7-16.8' + +export interface AnimatedCheckRef { + play(cb?: () => void): void +} + +export interface AnimatedCheckProps extends Props { + playOnMount?: boolean +} + +export const AnimatedCheck = React.forwardRef< + AnimatedCheckRef, + AnimatedCheckProps +>(function AnimatedCheck({playOnMount, ...props}, ref) { + const {fill, size, style, ...rest} = useCommonSVGProps(props) + const circleAnim = useSharedValue(0) + const checkAnim = useSharedValue(0) + + const circleAnimatedProps = useAnimatedProps(() => ({ + strokeDashoffset: 166 - circleAnim.value * 166, + })) + const checkAnimatedProps = useAnimatedProps(() => ({ + strokeDashoffset: 48 - 48 * checkAnim.value, + })) + + const play = React.useCallback( + (cb?: () => void) => { + circleAnim.value = 0 + checkAnim.value = 0 + + circleAnim.value = withTiming(1, {duration: 500, easing: Easing.linear}) + checkAnim.value = withDelay( + 500, + withTiming(1, {duration: 300, easing: Easing.linear}, cb), + ) + }, + [circleAnim, checkAnim], + ) + + React.useImperativeHandle(ref, () => ({ + play, + })) + + React.useEffect(() => { + if (playOnMount) { + play() + } + }, [play, playOnMount]) + + return ( + <Svg + fill="none" + {...rest} + viewBox="0 0 52 52" + width={size} + height={size} + style={style}> + <AnimatedCircle + animatedProps={circleAnimatedProps} + cx="26" + cy="26" + r="24" + fill="none" + stroke={fill} + strokeWidth={4} + strokeDasharray={166} + /> + <AnimatedPath + animatedProps={checkAnimatedProps} + stroke={fill} + d={PATH} + strokeWidth={4} + strokeDasharray={48} + /> + </Svg> + ) +}) |