import { useEffect, useMemo } from "react"; import { StyleSheet, useWindowDimensions, View, type ViewProps } from "react-native"; import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from "react-native-reanimated"; import Svg, { Circle, Defs, Line, RadialGradient, Stop } from "react-native-svg"; import { useAppTheme } from "@/contexts/ThemeContext"; import { blobAnimation, blobDiameter } from "@/lib/beenvoice-theme"; import { getBackgroundTokens } from "@/lib/theme-palette"; export function BrandBackground({ style, ...props }: ViewProps) { const { colorScheme } = useAppTheme(); const tokens = useMemo(() => getBackgroundTokens(colorScheme), [colorScheme]); const { width, height } = useWindowDimensions(); const cx = width / 2; const cy = height / 2; const gridLines = useMemo(() => { const vertical: Array<{ key: string; x: number }> = []; const horizontal: Array<{ key: string; y: number }> = []; for (let x = 0; x <= width; x += tokens.gridSize) { vertical.push({ key: `v-${x}`, x }); } for (let y = 0; y <= height; y += tokens.gridSize) { horizontal.push({ key: `h-${y}`, y }); } return { vertical, horizontal }; }, [width, height, tokens.gridSize]); return ( {gridLines.vertical.map((line) => ( ))} {gridLines.horizontal.map((line) => ( ))} ); } function AmbientBlob({ cx, cy, blobCore }: { cx: number; cy: number; blobCore: string }) { const progress = useSharedValue(0); const r = blobDiameter / 2; useEffect(() => { progress.value = withRepeat( withTiming(1, { duration: blobAnimation.durationMs, easing: Easing.inOut(Easing.ease), }), -1, false, ); }, [progress]); const animatedStyle = useAnimatedStyle(() => { const k = blobAnimation.keyframes; const t = progress.value; const seg = t < 0.33 ? 0 : t < 0.66 ? 1 : 2; const local = seg === 0 ? t / 0.33 : seg === 1 ? (t - 0.33) / 0.33 : (t - 0.66) / 0.34; const from = k[seg]!; const to = k[seg + 1] ?? k[0]!; const lerp = (a: number, b: number) => a + (b - a) * local; return { transform: [ { translateX: lerp(from.translateX, to.translateX) }, { translateY: lerp(from.translateY, to.translateY) }, { scale: lerp(from.scale, to.scale) }, ], }; }); return ( ); } const styles = StyleSheet.create({ root: { ...StyleSheet.absoluteFill, }, blobLayer: { position: "absolute", left: "50%", top: "50%", width: blobDiameter * 1.6, height: blobDiameter * 1.6, marginLeft: -(blobDiameter * 0.8), marginTop: -(blobDiameter * 0.8), }, });