import { useEffect, useRef, useState } from "react"; import { Modal, Platform, Share, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions, } from "react-native"; import { BlurView } from "expo-blur"; import Animated, { FadeIn, FadeOut, SlideInDown, SlideOutDown } from "react-native-reanimated"; import { Ionicons } from "@expo/vector-icons"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import ViewShot, { type ViewShotRef } from "react-native-view-shot"; import * as Sharing from "expo-sharing"; import { colors, spacing, typography, blur } from "../../../theme"; import { shareToInstagramStories } from "../../../lib/instagramShare"; import { Events } from "../../../lib/analytics"; import { QuizResultsShareCard } from "./QuizResultsShareCard"; const MAX_CARD_WIDTH = 340; interface QuizShareModalProps { visible: boolean; onClose: () => void; scorePercent: number; } export function QuizShareModal({ visible, onClose, scorePercent }: QuizShareModalProps) { const insets = useSafeAreaInsets(); const { width: screenWidth } = useWindowDimensions(); const cardWidth = Math.min(screenWidth - 64, MAX_CARD_WIDTH); const shareViewRef = useRef(null); const [capturedUri, setCapturedUri] = useState(null); const [isCapturing, setIsCapturing] = useState(false); const shareMessage = `We matched on ${scorePercent}% on our couple quiz! Discover more on sauci.app`; useEffect(() => { if (visible && shareViewRef.current) { setIsCapturing(true); const timer = setTimeout(async () => { try { const uri = await shareViewRef.current?.capture?.(); if (uri) setCapturedUri(uri); } catch (error) { console.error("Error capturing quiz share image:", error); } finally { setIsCapturing(false); } }, 100); return () => clearTimeout(timer); } }, [visible]); useEffect(() => { if (!visible) setCapturedUri(null); }, [visible]); const handleInstagramShare = async () => { if (!capturedUri) return; const shared = await shareToInstagramStories(capturedUri); if (shared) { Events.quizShared(); } else { // Instagram Stories sharing unavailable - fall back to the share sheet await handleMoreShare(); } }; const handleMessagesShare = async () => { if (!capturedUri) { await Share.share({ message: shareMessage }); Events.quizShared(); return; } try { if (Platform.OS === "ios") { await Sharing.shareAsync(capturedUri, { mimeType: "image/png", UTI: "public.png" }); Events.quizShared(); } else { await handleMoreShare(); } } catch (error) { console.error("Messages share error:", error); await Share.share({ message: shareMessage }); Events.quizShared(); } }; const handleMoreShare = async () => { if (!capturedUri) { await Share.share({ message: shareMessage }); Events.quizShared(); return; } try { const isAvailable = await Sharing.isAvailableAsync(); if (isAvailable) { await Sharing.shareAsync(capturedUri, { mimeType: "image/png", dialogTitle: "Share your quiz score" }); } else { await Share.share({ message: shareMessage }); } Events.quizShared(); } catch (error) { console.error("Share error:", error); } }; const useBlur = Platform.OS === "ios"; return ( {useBlur ? ( ) : ( )} Share your score ); } function ShareActionButton({ icon, label, onPress, disabled, }: { icon: string; label: string; onPress: () => void; disabled?: boolean; }) { return ( {label} ); } const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: "rgba(0, 0, 0, 0.5)", }, backdropFallback: { flex: 1, backgroundColor: "rgba(14, 14, 17, 0.95)", }, content: { flex: 1, }, header: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: spacing.lg, paddingVertical: spacing.md, }, closeButton: { width: 44, height: 44, justifyContent: "center", alignItems: "center", }, title: { ...typography.headline, color: colors.text, fontWeight: "600", }, headerSpacer: { width: 44, }, previewContainer: { flex: 1, justifyContent: "center", alignItems: "center", paddingHorizontal: spacing.lg, }, actionsContainer: { flexDirection: "row", justifyContent: "center", gap: spacing.xl, paddingTop: spacing.xl, paddingHorizontal: spacing.lg, }, actionButton: { alignItems: "center", gap: spacing.sm, }, actionIconContainer: { width: 64, height: 64, borderRadius: 32, justifyContent: "center", alignItems: "center", backgroundColor: colors.backgroundLight, borderWidth: 1, borderColor: colors.border, }, actionLabel: { ...typography.caption1, color: colors.text, fontWeight: "500", }, });