Share funktion
This commit is contained in:
@@ -4,7 +4,7 @@ import { useRouter } from 'expo-router';
|
||||
import { parseShareIntent, ShareIntentModule } from 'expo-share-intent';
|
||||
import * as ExpoLinking from 'expo-linking';
|
||||
import { SHARE_INTENT_KEY, storeSharedImageUri } from '../utils/shareHandoff';
|
||||
import { resolveSharedImageUri, summarizeShareIntent } from '../utils/shareIntent';
|
||||
import { isSharedImageResolutionFailure, resolveSharedImageUri, summarizeShareIntent } from '../utils/shareIntent';
|
||||
|
||||
const SHARE_INTENT_SCHEME = 'greenlens';
|
||||
const SHARE_INTENT_OPTIONS = {
|
||||
@@ -16,6 +16,8 @@ export default function ShareIntentCallbackScreen() {
|
||||
const router = useRouter();
|
||||
const [isWaiting, setIsWaiting] = React.useState(true);
|
||||
const [failureDetails, setFailureDetails] = React.useState<string | null>(null);
|
||||
const [failureTitle, setFailureTitle] = React.useState<string | null>(null);
|
||||
const [failureBody, setFailureBody] = React.useState<string | null>(null);
|
||||
const [previewUri, setPreviewUri] = React.useState<string | null>(null);
|
||||
const pendingKeyRef = React.useRef<string | null>(null);
|
||||
const getIntentCalledRef = React.useRef(false);
|
||||
@@ -33,11 +35,13 @@ export default function ShareIntentCallbackScreen() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const showFailure = (message: string) => {
|
||||
const showFailure = (message: string, title?: string, body?: string) => {
|
||||
settledRef.current = true;
|
||||
ShareIntentModule?.clearShareIntent(SHARE_INTENT_KEY);
|
||||
setPreviewUri(null);
|
||||
setIsWaiting(false);
|
||||
setFailureTitle(title ?? null);
|
||||
setFailureBody(body ?? null);
|
||||
setFailureDetails(message);
|
||||
};
|
||||
|
||||
@@ -45,13 +49,23 @@ export default function ShareIntentCallbackScreen() {
|
||||
try {
|
||||
setIsWaiting(true);
|
||||
setFailureDetails(null);
|
||||
setFailureTitle(null);
|
||||
setFailureBody(null);
|
||||
const shareIntent = parseShareIntent(event.value, SHARE_INTENT_OPTIONS);
|
||||
if (__DEV__) {
|
||||
console.debug('[ShareIntentCallback]', summarizeShareIntent(shareIntent));
|
||||
}
|
||||
const resolved = await resolveSharedImageUri(shareIntent);
|
||||
if (!resolved) {
|
||||
showFailure('Die Quelle hat keinen nutzbaren Bildanhang oder Bild-Link geliefert.');
|
||||
if (isSharedImageResolutionFailure(resolved)) {
|
||||
if (resolved.failureReason === 'login_wall') {
|
||||
showFailure(
|
||||
'Die geteilte Seite verlangt einen Login und hat das Bild nicht ausgeliefert.',
|
||||
'Instagram hat den Post nicht freigegeben',
|
||||
'Mach einen Screenshot vom Post und teile den Screenshot mit GreenLens — das funktioniert immer.',
|
||||
);
|
||||
} else {
|
||||
showFailure('Die Quelle hat keinen nutzbaren Bildanhang oder Bild-Link geliefert.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
settledRef.current = true;
|
||||
@@ -118,9 +132,10 @@ export default function ShareIntentCallbackScreen() {
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.messageBox}>
|
||||
<Text style={styles.title}>Bild konnte nicht geladen werden.</Text>
|
||||
<Text style={styles.title}>{failureTitle ?? 'Bild konnte nicht geladen werden.'}</Text>
|
||||
<Text style={styles.body}>
|
||||
Tippe und halte das Bild in Safari oder Instagram, wähle „Bild teilen" und teile es direkt mit GreenLens.
|
||||
{failureBody
|
||||
?? 'Tippe und halte das Bild in Safari oder Instagram, wähle „Bild teilen" und teile es direkt mit GreenLens.'}
|
||||
</Text>
|
||||
{failureDetails ? (
|
||||
<Text style={styles.detail}>{failureDetails}</Text>
|
||||
|
||||
@@ -42,6 +42,7 @@ const getBillingCopy = (language: 'de' | 'en' | 'es') => {
|
||||
retryLabel: 'Erneut versuchen',
|
||||
notAPlantTitle: 'Keine Pflanze erkannt',
|
||||
notAPlantMessage: 'Das Bild zeigt keine erkennbare Pflanze. Bitte fotografiere eine Pflanze und versuche es erneut.',
|
||||
notAPlantSharedMessage: 'Das geteilte Bild zeigt keine erkennbare Pflanze. Möglicherweise wurde nicht der Original-Post geladen. Mach einen Screenshot vom Post und teile den Screenshot — das funktioniert immer.',
|
||||
providerErrorMessage: 'KI-Scan gerade nicht verfügbar. Bitte versuche es erneut.',
|
||||
healthProviderErrorMessage: 'KI-Health-Check gerade nicht verfügbar. Bitte versuche es erneut.',
|
||||
healthTitle: 'Health Check',
|
||||
@@ -74,6 +75,7 @@ const getBillingCopy = (language: 'de' | 'en' | 'es') => {
|
||||
retryLabel: 'Reintentar',
|
||||
notAPlantTitle: 'No es una planta',
|
||||
notAPlantMessage: 'La imagen no muestra una planta reconocible. Por favor fotografía una planta e inténtalo de nuevo.',
|
||||
notAPlantSharedMessage: 'La imagen compartida no muestra una planta reconocible. Es posible que no se haya cargado la publicación original. Haz una captura de pantalla de la publicación y compártela — eso siempre funciona.',
|
||||
providerErrorMessage: 'Escaneo IA no disponible ahora. Inténtalo de nuevo.',
|
||||
healthProviderErrorMessage: 'Health-check IA no disponible ahora. Inténtalo de nuevo.',
|
||||
healthTitle: 'Health Check',
|
||||
@@ -105,6 +107,7 @@ const getBillingCopy = (language: 'de' | 'en' | 'es') => {
|
||||
retryLabel: 'Try again',
|
||||
notAPlantTitle: 'No plant detected',
|
||||
notAPlantMessage: 'The image does not show a recognizable plant. Please photograph a plant and try again.',
|
||||
notAPlantSharedMessage: 'The shared image does not show a recognizable plant. The original post may not have loaded. Take a screenshot of the post and share the screenshot — that always works.',
|
||||
providerErrorMessage: 'AI scan is currently unavailable. Please try again.',
|
||||
healthProviderErrorMessage: 'AI health check is currently unavailable. Please try again.',
|
||||
healthTitle: 'Health Check',
|
||||
@@ -199,6 +202,7 @@ export default function ScannerScreen() {
|
||||
|
||||
const lastProcessedShareToken = useRef<string | null>(null);
|
||||
const sharedAnalysisInFlightToken = useRef<string | null>(null);
|
||||
const analysisFromShareRef = useRef(false);
|
||||
const resizeForAnalysisRef = useRef<(uri: string) => Promise<string>>(async (uri) => uri);
|
||||
const analyzeImageRef = useRef<(imageUri: string, galleryImageUri?: string) => Promise<void>>(async () => {});
|
||||
|
||||
@@ -417,7 +421,7 @@ export default function ScannerScreen() {
|
||||
} else if (isBackendApiError(error) && error.code === 'NOT_A_PLANT') {
|
||||
Alert.alert(
|
||||
billingCopy.notAPlantTitle,
|
||||
billingCopy.notAPlantMessage,
|
||||
analysisFromShareRef.current ? billingCopy.notAPlantSharedMessage : billingCopy.notAPlantMessage,
|
||||
[{ text: billingCopy.dismiss, style: 'cancel' }],
|
||||
);
|
||||
} else if (isBackendApiError(error) && error.code === 'PROVIDER_ERROR') {
|
||||
@@ -469,6 +473,7 @@ export default function ScannerScreen() {
|
||||
if (cancelled || sharedAnalysisInFlightToken.current !== shareToken) return;
|
||||
setDemoResultVisible(false);
|
||||
setSelectedImage(analysisUri);
|
||||
analysisFromShareRef.current = true;
|
||||
await analyzeImageRef.current(analysisUri, nextSharedImageUri);
|
||||
} finally {
|
||||
if (sharedAnalysisInFlightToken.current === shareToken) {
|
||||
@@ -490,6 +495,7 @@ export default function ScannerScreen() {
|
||||
const analysisUri = await resizeForAnalysis(photo.uri);
|
||||
setDemoResultVisible(false);
|
||||
setSelectedImage(analysisUri);
|
||||
analysisFromShareRef.current = false;
|
||||
analyzeImage(analysisUri, photo.uri);
|
||||
}
|
||||
};
|
||||
@@ -507,6 +513,7 @@ export default function ScannerScreen() {
|
||||
const analysisUri = await resizeForAnalysis(asset.uri);
|
||||
setDemoResultVisible(false);
|
||||
setSelectedImage(asset.uri);
|
||||
analysisFromShareRef.current = false;
|
||||
analyzeImage(analysisUri, asset.uri);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user