import { Feather, FontAwesome, MaterialCommunityIcons, } from "@expo/vector-icons"; import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react"; import { Linking, Platform, Pressable, Share, StyleSheet, Text, View, } from "react-native"; import { SheetManager } from "react-native-actions-sheet"; import { BlurView } from "expo-blur"; import { setGlobal } from "reactn"; import { musiclandShareHeading, musiclandShareMessage, musiclandShareUrl, } from "../../data"; import { isWeb } from "../../hooks/useLayoutType"; import { Palette } from "../../styles"; import { FONT_FAMILY } from "../../styles/Fonts"; import AppActionSheet from "../AppActionSheet"; const ShareModal = ({ payload }) => { const heading = payload?.heading ?? musiclandShareHeading; const url = payload?.url ?? musiclandShareUrl; const shareTitle = payload?.shareTitle ?? heading; const shareMessage = payload?.shareMessage ?? musiclandShareMessage; const linkLabel = payload?.linkLabel ?? url; const sectionTitle = payload?.sectionTitle ?? "Partager sur..."; const qrTitle = payload?.qrTitle ?? "Scannez le QR-code"; const qrUrl = payload?.qrUrl ?? musiclandShareUrl; const [copied, setCopied] = useState(false); const copyTimeout = useRef(null); const blurProps = Platform.OS === "android" ? { experimentalBlurMethod: "dimezisBlurView" } : {}; const closeSheet = useCallback(() => { return SheetManager.hide("Share"); }, []); const shareText = useMemo(() => { return [shareMessage, url].filter(Boolean).join(" "); }, [shareMessage, url]); const encodedUrl = useMemo(() => encodeURIComponent(url), [url]); const encodedShareText = useMemo( () => encodeURIComponent(shareText), [shareText] ); useEffect(() => { return () => { if (copyTimeout.current) { clearTimeout(copyTimeout.current); } }; }, []); const handleCopy = useCallback(async () => { try { if (copyTimeout.current) { clearTimeout(copyTimeout.current); } if (isWeb && typeof navigator !== "undefined" && navigator.clipboard) { await navigator.clipboard.writeText(url); } else { const Clipboard = await import("expo-clipboard"); if (typeof Clipboard?.setStringAsync === "function") { await Clipboard.setStringAsync(url); } else if (typeof Clipboard?.default?.setStringAsync === "function") { await Clipboard.default.setStringAsync(url); } } setCopied(true); copyTimeout.current = setTimeout(() => { setCopied(false); }, 2000); } catch (error) { console.error("share.copy.failed", error); } }, [url]); const handleSystemShare = useCallback(async () => { if (Platform.OS === "web" && typeof navigator !== "undefined") { try { if (typeof navigator.share === "function") { await navigator.share({ url, text: shareText, title: shareTitle, }); return; } } catch (error) { console.error("share.system.web", error); } } try { await Share.share( Platform.select({ ios: url ? { url, message: shareText, title: shareTitle } : { message: shareText, title: shareTitle }, android: { message: shareText, title: shareTitle }, default: { message: shareText, title: shareTitle }, }) ); } catch (error) { console.error("share.system.native", error); } }, [shareText, shareTitle, url]); const handleShareOption = useCallback( async (option) => { if (option?.type === "qr") { await closeSheet(); setGlobal({ shareQrModal: { visible: true, url: qrUrl, title: qrTitle, }, }); return; } const target = option?.target; if (!target) { await handleSystemShare(); await closeSheet(); return; } try { if (Platform.OS === "web") { window.open(target, "_blank", "noopener,noreferrer"); await closeSheet(); return; } const supported = await Linking.canOpenURL(target); if (supported) { await Linking.openURL(target); await closeSheet(); return; } } catch (error) { console.error(`share.option.error.${option?.key || "unknown"}`, error); } await handleSystemShare(); await closeSheet(); }, [closeSheet, handleSystemShare, qrTitle, qrUrl] ); const onSystemShare = useCallback(async () => { await handleSystemShare(); await closeSheet(); }, [closeSheet, handleSystemShare]); const shareOptions = useMemo(() => { if (Array.isArray(payload?.options) && payload.options.length) { return payload.options; } return [ { key: "facebook", label: "Partager sur Facebook", Icon: (props) => , target: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`, }, { key: "instagram", label: "Partager sur Instagram", Icon: (props) => , target: `https://www.instagram.com/?url=${encodedUrl}`, }, { key: "x", label: "Partager sur X", Icon: (props) => , target: `https://twitter.com/intent/tweet?url=${encodedUrl}&text=${encodedShareText}`, }, { key: "email", label: "Partager par e-mail", Icon: (props) => , target: `mailto:?subject=${encodeURIComponent( shareTitle )}&body=${encodedShareText}`, }, { key: "qr", type: "qr", label: "Partager par QR-code", Icon: (props) => ( ), }, ]; }, [encodedShareText, encodedUrl, payload?.options, shareTitle]); return ( {heading} {linkLabel} {copied ? Lien copiƩ : null} {sectionTitle} {shareOptions.map((option, index) => { const Icon = option?.Icon ?? Feather; return ( handleShareOption(option)} style={styles.optionRow} > {option?.label} ); })} ); }; const styles = StyleSheet.create({ container: { gap: 24, }, card: { backgroundColor: Palette.glass, overflow: "hidden", borderRadius: 24, borderWidth: 1, borderColor: "rgba(255, 255, 255, 0.08)", paddingHorizontal: 20, paddingVertical: 18, gap: 16, }, blurCard: { overflow: "hidden", position: "relative", }, closeButton: { position: "absolute", top: 16, right: 16, width: 32, height: 32, borderRadius: 16, alignItems: "center", justifyContent: "center", backgroundColor: "rgba(255, 255, 255, 0.12)", zIndex: 2, }, heading: { fontSize: 20, color: Palette.white, textAlign: "center", fontFamily: FONT_FAMILY.HelveticaNeueMedium, }, linkRow: { flexDirection: "row", alignItems: "center", backgroundColor: "rgba(255, 255, 255, 0.06)", borderRadius: 16, paddingHorizontal: 14, paddingVertical: 10, gap: 12, }, linkText: { flex: 1, color: Palette.white, fontSize: 15, fontFamily: FONT_FAMILY.InterMedium, }, linkActions: { flexDirection: "row", alignItems: "center", gap: 8, }, iconButton: { width: 32, height: 32, borderRadius: 16, backgroundColor: "rgba(255, 255, 255, 0.08)", alignItems: "center", justifyContent: "center", }, copiedText: { fontSize: 12, textAlign: "center", color: Palette.white, opacity: 0.8, fontFamily: FONT_FAMILY.InterMedium, }, sectionHeading: { fontSize: 18, color: Palette.white, fontFamily: FONT_FAMILY.HelveticaNeueMedium, textAlign: "center", }, optionsList: { gap: 12, }, optionBlur: { borderRadius: 18, overflow: "hidden", }, optionRow: { flexDirection: "row", alignItems: "center", backgroundColor: "rgba(255, 255, 255, 0.04)", // borderRadius: 18, paddingHorizontal: 14, paddingVertical: 14, gap: 14, }, optionIconWrapper: { width: 36, height: 36, borderRadius: 18, backgroundColor: "rgba(255, 255, 255, 0.08)", alignItems: "center", justifyContent: "center", }, optionLabel: { flex: 1, fontSize: 15, color: Palette.white, fontFamily: FONT_FAMILY.InterMedium, }, }); export default ShareModal;