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]);
const mobileContent = (
{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 webContent = (
{heading}
{shareMessage}
{linkLabel}
{copied ? "Lien copiƩ" : "Copier le lien"}
Partager
{sectionTitle}
{shareOptions.map((option, index) => {
const Icon = option?.Icon ?? Feather;
return (
handleShareOption(option)}
style={styles.webOptionRow}
>
{option?.label}
);
})}
);
return (
{isWeb ? webContent : mobileContent}
);
};
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,
},
webContainer: {
gap: 24,
},
webHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
gap: 12,
},
webHeading: {
flex: 1,
fontSize: 24,
color: Palette.white,
fontFamily: FONT_FAMILY.HelveticaNeueMedium,
},
webCloseButton: {
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: "rgba(255, 255, 255, 0.08)",
alignItems: "center",
justifyContent: "center",
},
webSubheading: {
fontSize: 14,
color: "rgba(255, 255, 255, 0.65)",
fontFamily: FONT_FAMILY.InterMedium,
},
webContent: {
gap: 20,
},
webLinkCard: {
backgroundColor: "rgba(255, 255, 255, 0.06)",
borderRadius: 20,
paddingHorizontal: 20,
paddingVertical: 18,
gap: 16,
},
webLinkLabel: {
color: Palette.white,
fontSize: 15,
fontFamily: FONT_FAMILY.InterMedium,
overflow: "hidden",
},
webLinkActions: {
flexDirection: "row",
alignItems: "center",
gap: 12,
flexWrap: "wrap",
},
webActionButton: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
gap: 10,
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 16,
},
webPrimaryButton: {
backgroundColor: Palette.primary,
},
webSecondaryButton: {
backgroundColor: "rgba(255, 255, 255, 0.08)",
},
webActionButtonActive: {
backgroundColor: Palette.darkRadioactivGreen,
},
webActionLabel: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
webOptionsCard: {
backgroundColor: "rgba(255, 255, 255, 0.06)",
borderRadius: 20,
paddingHorizontal: 20,
paddingVertical: 22,
gap: 16,
},
webSectionHeading: {
fontSize: 18,
color: Palette.white,
fontFamily: FONT_FAMILY.HelveticaNeueMedium,
},
webOptionsGrid: {
gap: 12,
},
webOptionRow: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: 12,
backgroundColor: "rgba(255, 255, 255, 0.04)",
borderRadius: 16,
paddingHorizontal: 18,
paddingVertical: 14,
},
webOptionIcon: {
width: 36,
height: 36,
borderRadius: 18,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(255, 255, 255, 0.08)",
marginRight: 4,
},
webOptionLabel: {
flex: 1,
fontSize: 15,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
});
export default ShareModal;