Fix Android ViewShot dropping frames and date overlays by temporarily lifting pointerEvents=none during capture
This commit is contained in:
@@ -3,6 +3,7 @@ import { StyleSheet, Image, View } from 'react-native';
|
|||||||
|
|
||||||
interface FrameOverlayProps {
|
interface FrameOverlayProps {
|
||||||
frameAsset: any; // require() asset
|
frameAsset: any; // require() asset
|
||||||
|
isCapturing?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,11 +11,11 @@ interface FrameOverlayProps {
|
|||||||
* The frame PNG must have a transparent center (alpha=0) so the photo shows through.
|
* The frame PNG must have a transparent center (alpha=0) so the photo shows through.
|
||||||
* Positioned absolutely to cover the entire photo canvas.
|
* Positioned absolutely to cover the entire photo canvas.
|
||||||
*/
|
*/
|
||||||
export default function FrameOverlay({ frameAsset }: FrameOverlayProps) {
|
export default function FrameOverlay({ frameAsset, isCapturing = false }: FrameOverlayProps) {
|
||||||
if (!frameAsset) return null;
|
if (!frameAsset) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container} pointerEvents="none" collapsable={false}>
|
<View style={styles.container} pointerEvents={isCapturing ? "auto" : "none"} collapsable={false}>
|
||||||
<Image
|
<Image
|
||||||
source={frameAsset}
|
source={frameAsset}
|
||||||
style={styles.frameImage}
|
style={styles.frameImage}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export default function PreviewScreen({
|
|||||||
}: PreviewScreenProps) {
|
}: PreviewScreenProps) {
|
||||||
const [layout, setLayout] = useState<CollageLayout>('single');
|
const [layout, setLayout] = useState<CollageLayout>('single');
|
||||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||||
|
const [isCapturing, setIsCapturing] = useState<boolean>(false);
|
||||||
const [statusMessage, setStatusMessage] = useState<string>('');
|
const [statusMessage, setStatusMessage] = useState<string>('');
|
||||||
|
|
||||||
|
|
||||||
@@ -204,14 +205,21 @@ export default function PreviewScreen({
|
|||||||
try {
|
try {
|
||||||
logger.log(`captureComposite started. Has ViewShot ref: ${!!viewShotRef.current}`);
|
logger.log(`captureComposite started. Has ViewShot ref: ${!!viewShotRef.current}`);
|
||||||
if (viewShotRef.current) {
|
if (viewShotRef.current) {
|
||||||
|
setIsCapturing(true);
|
||||||
|
// Wait for React to re-render and remove pointerEvents="none" which blocks ViewShot on Android
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
|
||||||
logger.log('Executing viewShotRef.current.capture()...');
|
logger.log('Executing viewShotRef.current.capture()...');
|
||||||
const uri = await viewShotRef.current.capture();
|
const uri = await viewShotRef.current.capture();
|
||||||
|
|
||||||
|
setIsCapturing(false);
|
||||||
logger.log(`ViewShot successfully generated collage URI: ${uri}`);
|
logger.log(`ViewShot successfully generated collage URI: ${uri}`);
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
logger.log('[WARNING] viewShotRef.current was null, falling back to raw photo.');
|
logger.log('[WARNING] viewShotRef.current was null, falling back to raw photo.');
|
||||||
return fallbackPhoto;
|
return fallbackPhoto;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
setIsCapturing(false);
|
||||||
logger.error('Failed to capture composite (ViewShot crashed)', e?.message || e);
|
logger.error('Failed to capture composite (ViewShot crashed)', e?.message || e);
|
||||||
return fallbackPhoto;
|
return fallbackPhoto;
|
||||||
}
|
}
|
||||||
@@ -453,11 +461,11 @@ export default function PreviewScreen({
|
|||||||
{renderCollageView()}
|
{renderCollageView()}
|
||||||
|
|
||||||
{/* Frame Overlay */}
|
{/* Frame Overlay */}
|
||||||
{activeFrame && <FrameOverlay frameAsset={activeFrame.asset} />}
|
{activeFrame && <FrameOverlay frameAsset={activeFrame.asset} isCapturing={isCapturing} />}
|
||||||
|
|
||||||
{/* Date/Time Overlay */}
|
{/* Date/Time Overlay */}
|
||||||
{dateOverlay !== 'off' && (
|
{dateOverlay !== 'off' && (
|
||||||
<View style={[styles.dateOverlay, getDatePositionStyle()]} pointerEvents="none">
|
<View style={[styles.dateOverlay, getDatePositionStyle()]} pointerEvents={isCapturing ? "auto" : "none"}>
|
||||||
<Text style={styles.dateOverlayText}>
|
<Text style={styles.dateOverlayText}>
|
||||||
{formatDate(dateOverlay)}
|
{formatDate(dateOverlay)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
Reference in New Issue
Block a user