/* * File: DicomViewer.tsx * Description: DICOM viewer component using WebView for medical imaging * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React, { useRef, useEffect, useState } from 'react'; import { WebView, WebViewMessageEvent } from 'react-native-webview'; import { Platform, View, Text, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native'; // Interface for component props interface DicomViewerProps { dicomUrl: string; onError?: (error: string) => void; onLoad?: () => void; } // Interface for WebView reference interface WebViewRef { postMessage: (message: string) => void; reload: () => void; } export default function DicomViewer({ dicomUrl, onError, onLoad }: DicomViewerProps): React.ReactElement { const webViewRef = useRef(null); const [hasError, setHasError] = useState(false); const [webViewReady, setWebViewReady] = useState(false); // Handle WebView load events const handleLoadStart = () => { setHasError(false); }; const handleLoadEnd = () => { setWebViewReady(true); onLoad?.(); }; const handleError = (error: any) => { setHasError(true); onError?.(error?.nativeEvent?.description || 'Failed to load DICOM viewer'); }; const handleMessage = (event: WebViewMessageEvent) => { try { const message = event.nativeEvent.data; // Try to parse JSON message if (typeof message === 'string') { try { const parsedMessage = JSON.parse(message); if (parsedMessage.type === 'error') { setHasError(true); onError?.(parsedMessage.message); } else if (parsedMessage.type === 'success') { setHasError(false); } } catch (parseError) { // Failed to parse message as JSON } } } catch (error) { // Error handling WebView message } }; // Send DICOM URL to WebView when component mounts or URL changes useEffect(() => { if (webViewRef.current && dicomUrl && webViewReady) { // Wait a bit for WebView to be ready const timer = setTimeout(() => { if (webViewRef.current) { try { // Send the URL directly as a string message webViewRef.current.postMessage(dicomUrl); // Also try sending as a structured message setTimeout(() => { if (webViewRef.current) { const structuredMessage = JSON.stringify({ type: 'loadDicom', data: dicomUrl }); webViewRef.current.postMessage(structuredMessage); } }, 500); } catch (error) { // Failed to send DICOM URL } } }, 1000); return () => clearTimeout(timer); } }, [dicomUrl, webViewReady]); // Reload WebView if there's an error const handleRetry = () => { if (webViewRef.current) { setHasError(false); setWebViewReady(false); webViewRef.current.reload(); } }; return ( {hasError && ( Failed to load DICOM viewer URL: {dicomUrl} Tap to retry )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#000', }, webview: { flex: 1, backgroundColor: '#000', }, errorContainer: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'center', alignItems: 'center', backgroundColor: '#000', padding: 20, }, errorText: { color: '#F44336', fontSize: 18, textAlign: 'center', marginBottom: 16, fontWeight: '600', }, errorDetails: { color: '#FF9800', fontSize: 14, textAlign: 'center', marginBottom: 20, fontFamily: 'monospace', }, retryButton: { backgroundColor: '#2196F3', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 8, }, retryButtonText: { color: '#FFFFFF', fontSize: 16, fontWeight: '600', }, }); /* * End of File: DicomViewer.tsx * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */