refactor(rn-com): refactor rn switch component

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-01-21 00:12:22 +08:00
parent 203c253522
commit aa5d5f5679
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
5 changed files with 57 additions and 80 deletions

View File

@ -5,9 +5,11 @@ import { forwardRef } from "react"
export const ThemedBlurView = forwardRef<BlurView, BlurViewProps>(({ tint, ...rest }, ref) => {
const { colorScheme } = useColorScheme()
return (
<BlurView
ref={ref}
intensity={100}
tint={colorScheme === "light" ? "systemChromeMaterialLight" : "systemChromeMaterialDark"}
{...rest}
/>

View File

@ -1,5 +1,5 @@
import { forwardRef } from "react"
import type { StyleProp, Switch as NativeSwitch, ViewStyle } from "react-native"
import type { StyleProp, ViewStyle } from "react-native"
import { Text, View } from "react-native"
import type { SwitchProps, SwitchRef } from "../switch/Switch"

View File

@ -3,9 +3,8 @@ import type { FC, PropsWithChildren } from "react"
import * as React from "react"
import { Fragment } from "react"
import type { ViewProps } from "react-native"
import { Pressable, StyleSheet, Switch, Text, View } from "react-native"
import { Pressable, StyleSheet, Text, View } from "react-native"
import { setGeneralSetting } from "@/src/atoms/settings/general"
import { RightCuteReIcon } from "@/src/icons/right_cute_re"
import { useColor } from "@/src/theme/colors"

View File

@ -1,7 +1,14 @@
import type { useState } from "react"
import { forwardRef, useEffect, useImperativeHandle, useMemo } from "react"
import { forwardRef, useEffect, useImperativeHandle } from "react"
import type { SwitchChangeEvent } from "react-native"
import { Animated, Easing, Pressable, StyleSheet, useAnimatedValue, View } from "react-native"
import { Pressable, StyleSheet, View } from "react-native"
import Animated, {
interpolate,
interpolateColor,
useAnimatedStyle,
useSharedValue,
withSpring,
withTiming,
} from "react-native-reanimated"
import { accentColor, useColor } from "@/src/theme/colors"
@ -27,83 +34,62 @@ export type SwitchRef = {
}
export const Switch = forwardRef<SwitchRef, SwitchProps>(
({ value, onValueChange, onChange, size = "default" }, ref) => {
const animatedValue = useAnimatedValue(0)
const circleWidthAnimatedValue = useAnimatedValue(0)
const translateX = useAnimatedValue(0)
const colorAnimatedValue = useAnimatedValue(0)
useEffect(() => {
Animated.timing(animatedValue, {
toValue: value ? 1 : 0,
duration: 110,
easing: Easing.linear,
useNativeDriver: false,
}).start()
Animated.timing(colorAnimatedValue, {
toValue: value ? 1 : 0,
duration: 300,
easing: Easing.linear,
useNativeDriver: false,
}).start()
}, [value])
const progress = useSharedValue(value ? 1 : 0)
const scale = useSharedValue(1)
const translateX = useSharedValue(0)
const onTouchStart = () => {
Animated.timing(circleWidthAnimatedValue, {
toValue: 1,
duration: 200,
useNativeDriver: false,
}).start()
if (value)
Animated.timing(translateX, {
toValue: size === "sm" ? -4 : -7,
duration: 200,
useNativeDriver: false,
}).start()
scale.value = withSpring(1.1)
if (value) {
translateX.value = withSpring(size === "sm" ? -4 : -7)
}
}
const onTouchEnd = () => {
Animated.timing(circleWidthAnimatedValue, {
toValue: 0,
duration: 100,
useNativeDriver: false,
}).start()
Animated.timing(translateX, {
toValue: 0,
duration: 100,
useNativeDriver: false,
}).start()
scale.value = withSpring(1)
translateX.value = withSpring(0)
}
const moveToggle = useMemo(
() =>
animatedValue.interpolate({
inputRange: [0, 1],
outputRange: size === "sm" ? [2, 20] : [2.3, 22],
}),
[animatedValue, size],
)
const circleWidth = useMemo(
() =>
circleWidthAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: size === "sm" ? [18, 21] : [27.8, 35],
}),
[circleWidthAnimatedValue, size],
)
useImperativeHandle(ref, () => ({
value: !!value,
}))
const activeBgColor = accentColor
const inactiveBgColor = useColor("secondarySystemFill")
const bgColor = colorAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [inactiveBgColor, activeBgColor],
const toggleStyle = useAnimatedStyle(() => {
const backgroundColor = interpolateColor(
progress.value,
[0, 1],
[inactiveBgColor, activeBgColor],
)
return {
backgroundColor,
}
})
const circleStyle = useAnimatedStyle(() => {
const marginLeft = interpolate(progress.value, [0, 1], size === "sm" ? [2, 20] : [2.3, 22])
const width = interpolate(scale.value, [1, 1.1], size === "sm" ? [18, 21] : [27.8, 35])
return {
marginLeft,
width,
transform: [{ translateX: translateX.value }, { translateY: -0.4 }, { scale: scale.value }],
}
})
useEffect(() => {
// Update progress when value changes
if (value && progress.value === 0) {
progress.value = withTiming(1)
} else if (!value && progress.value === 1) {
progress.value = withTiming(0)
}
}, [progress, value])
return (
<View style={styles.container}>
<Pressable
@ -115,21 +101,12 @@ export const Switch = forwardRef<SwitchRef, SwitchProps>(
}}
>
<Animated.View
style={[
size === "sm" ? styles.toggleContainerSm : styles.toggleContainer,
{
backgroundColor: bgColor,
},
]}
style={[size === "sm" ? styles.toggleContainerSm : styles.toggleContainer, toggleStyle]}
>
<Animated.View
style={[
size === "sm" ? styles.toggleWheelStyleSm : styles.toggleWheelStyle,
{
marginLeft: moveToggle,
width: circleWidth,
transform: [{ translateX }, { translateY: -0.4 }],
},
circleStyle,
]}
/>
</Animated.View>

View File

@ -1,5 +1,4 @@
import { FeedViewType } from "@follow/constants"
import { transformUriPath } from "@follow/utils"
import { PlatformPressable } from "@react-navigation/elements/src/PlatformPressable"
import { router, Tabs } from "expo-router"
import { useContext, useEffect, useMemo, useState } from "react"