share modal

This commit is contained in:
2025-10-20 13:58:16 +02:00
parent 8e281e8f78
commit 2cb3af13e2
3 changed files with 169 additions and 86 deletions
+14 -4
View File
@@ -18,16 +18,18 @@ const AppActionSheet = ({
if (isWeb && webModal) { if (isWeb && webModal) {
return ( return (
<Portal> <Portal>
<View style={styles.webOverlay} pointerEvents="box-none"> <View style={styles.webOverlay}>
<Pressable <Pressable
onPress={onClose} onPress={onClose}
style={StyleSheet.absoluteFill} accessibilityRole="button"
pointerEvents="auto" style={styles.webBackdrop}
/> />
<View style={styles.webModalWrapper} pointerEvents="box-none">
<BlurView intensity={40} tint="dark" style={styles.webModalCard}> <BlurView intensity={40} tint="dark" style={styles.webModalCard}>
{children} {children}
</BlurView> </BlurView>
</View> </View>
</View>
</Portal> </Portal>
); );
} }
@@ -70,10 +72,18 @@ export default AppActionSheet;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
webOverlay: { webOverlay: {
...StyleSheet.absoluteFillObject, ...StyleSheet.absoluteFillObject,
position: "fixed",
zIndex: 100,
},
webBackdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: "rgba(0, 0, 0, 0.55)",
},
webModalWrapper: {
flex: 1,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
padding: 24, padding: 24,
backgroundColor: "rgba(0, 0, 0, 0.55)",
}, },
webModalCard: { webModalCard: {
width: 480, width: 480,
+75 -8
View File
@@ -18,6 +18,7 @@ import {
StyleSheet, StyleSheet,
Text, Text,
View, View,
findNodeHandle,
} from "react-native"; } from "react-native";
import { SheetManager } from "react-native-actions-sheet"; import { SheetManager } from "react-native-actions-sheet";
@@ -45,15 +46,33 @@ const ShareModal = ({ payload }) => {
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
const copyTimeout = useRef(null); const copyTimeout = useRef(null);
const modalRef = useRef(null);
const [webVisible, setWebVisible] = useState(true);
const blurProps = const blurProps =
Platform.OS === "android" Platform.OS === "android"
? { experimentalBlurMethod: "dimezisBlurView" } ? { experimentalBlurMethod: "dimezisBlurView" }
: {}; : {};
const closeSheet = useCallback(() => { const closeSheet = useCallback(() => {
return SheetManager.hide("Share"); if (isWeb) {
setWebVisible(false);
}
try {
const maybePromise = SheetManager.hide("Share");
return Promise.resolve(maybePromise);
} catch (error) {
console.error("share.sheet.close", error);
return Promise.resolve();
}
}, []); }, []);
useEffect(() => {
if (isWeb) {
setWebVisible(true);
}
}, [payload]);
const shareText = useMemo(() => { const shareText = useMemo(() => {
return [shareMessage, url].filter(Boolean).join(" "); return [shareMessage, url].filter(Boolean).join(" ");
}, [shareMessage, url]); }, [shareMessage, url]);
@@ -72,6 +91,46 @@ const ShareModal = ({ payload }) => {
}; };
}, []); }, []);
useEffect(() => {
if (!isWeb || typeof document === "undefined" || !webVisible) {
return;
}
const handlePointerDown = (event) => {
const node = modalRef.current;
if (!node) {
return;
}
const domNode = findNodeHandle(node);
if (domNode && typeof domNode.contains === "function") {
if (domNode.contains(event.target)) {
return;
}
}
if (domNode === event.target) {
return;
}
closeSheet();
};
const handleKeyDown = (event) => {
if (event.key === "Escape") {
closeSheet();
}
};
document.addEventListener("pointerdown", handlePointerDown);
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("pointerdown", handlePointerDown);
document.removeEventListener("keydown", handleKeyDown);
};
}, [closeSheet, webVisible]);
const handleCopy = useCallback(async () => { const handleCopy = useCallback(async () => {
try { try {
if (copyTimeout.current) { if (copyTimeout.current) {
@@ -288,8 +347,18 @@ const ShareModal = ({ payload }) => {
</View> </View>
); );
const webContent = ( if (isWeb && !webVisible) {
<View style={styles.webContainer}> return null;
}
return (
<AppActionSheet id="Share" webModal={isWeb} onClose={closeSheet}>
{isWeb ? (
<View
ref={modalRef}
collapsable={false}
style={styles.webContainer}
>
<View style={styles.webHeader}> <View style={styles.webHeader}>
<Text style={styles.webHeading}>{heading}</Text> <Text style={styles.webHeading}>{heading}</Text>
<Pressable <Pressable
@@ -362,11 +431,9 @@ const ShareModal = ({ payload }) => {
</View> </View>
</View> </View>
</View> </View>
); ) : (
mobileContent
return ( )}
<AppActionSheet id="Share" webModal={isWeb} onClose={closeSheet}>
{isWeb ? webContent : mobileContent}
</AppActionSheet> </AppActionSheet>
); );
}; };
+8 -2
View File
@@ -23,10 +23,11 @@ const ShareQrModal = ({
return ( return (
<Portal> <Portal>
<View style={StyleSheet.absoluteFill} pointerEvents="box-none"> <View style={styles.overlay}>
<Pressable <Pressable
onPress={onClose} onPress={onClose}
style={[StyleSheet.absoluteFill, styles.backdrop]} accessibilityRole="button"
style={styles.backdrop}
/> />
<View style={styles.centerWrapper} pointerEvents="box-none"> <View style={styles.centerWrapper} pointerEvents="box-none">
@@ -71,7 +72,12 @@ const ShareQrModal = ({
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
overlay: {
...StyleSheet.absoluteFillObject,
zIndex: 200,
},
backdrop: { backdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: "rgba(0, 0, 0, 0.65)", backgroundColor: "rgba(0, 0, 0, 0.65)",
}, },
centerWrapper: { centerWrapper: {