import { useSnapshot } from 'valtio'; import { useEffect, useRef, useState } from 'react'; import { Animated, Pressable, SafeAreaView, StyleSheet } from 'react-native'; import { WebView } from 'react-native-webview'; import { ConnectionController, ConnectorController, EventsController, RouterController, WebviewController } from '@reown/appkit-core-react-native'; import { useTheme, BorderRadius, IconLink, Spacing } from '@reown/appkit-ui-react-native'; import type { AppKitFrameProvider } from './AppKitFrameProvider'; import { AppKitFrameConstants } from './AppKitFrameConstants'; const AnimatedSafeAreaView = Animated.createAnimatedComponent(SafeAreaView); const AnimatedPressable = Animated.createAnimatedComponent(Pressable); export function AppKitWebview() { const webviewRef = useRef(null); const Theme = useTheme(); const authConnector = ConnectorController.getAuthConnector(); const { webviewVisible, webviewUrl } = useSnapshot(WebviewController.state); const [isBackdropVisible, setIsBackdropVisible] = useState(false); const backdropOpacity = useRef(new Animated.Value(0)); const webviewOpacity = useRef(new Animated.Value(0)); const provider = authConnector?.provider as AppKitFrameProvider; const display = webviewVisible ? 'flex' : 'none'; const onClose = () => { EventsController.sendEvent({ type: 'track', event: 'SOCIAL_LOGIN_CANCELED', properties: { provider: ConnectionController.state.selectedSocialProvider! } }); WebviewController.setWebviewVisible(false); WebviewController.setConnecting(false); WebviewController.setConnectingProvider(undefined); RouterController.goBack(); }; useEffect(() => { Animated.timing(webviewOpacity.current, { toValue: webviewVisible ? 1 : 0, duration: 300, useNativeDriver: true }).start(({ finished }) => { if (finished && !webviewVisible) { WebviewController.setWebviewUrl(''); } }); if (webviewVisible) { setIsBackdropVisible(true); } Animated.timing(backdropOpacity.current, { toValue: webviewVisible ? 0.7 : 0, duration: 300, useNativeDriver: true }).start(() => setIsBackdropVisible(webviewVisible)); }, [backdropOpacity, webviewVisible, setIsBackdropVisible]); if (!webviewUrl) return null; return provider ? ( <> { if ( !navState.loading && navState.url.includes(`${AppKitFrameConstants.SECURE_SITE_ORIGIN}/sdk/oauth`) ) { provider.events.emit('social', navState.url); } }} /> ) : null; } const styles = StyleSheet.create({ backdrop: { position: 'absolute', width: '100%', height: '100%', top: 0, zIndex: 999 }, container: { bottom: 0, position: 'absolute', height: '80%', width: '100%', borderTopLeftRadius: BorderRadius.l, borderTopRightRadius: BorderRadius.l, zIndex: 999 }, hidden: { display: 'none' }, webview: { borderTopLeftRadius: BorderRadius.l, borderTopRightRadius: BorderRadius.l }, closeButton: { top: -60, right: 0, zIndex: 999, position: 'absolute', margin: Spacing.l } });