/** * BrowserNotSupported - Error screen for unsupported browsers * * Displayed when Web Bluetooth is not available: * - Safari (no Web Bluetooth support) * - Firefox (no Web Bluetooth support) * - Insecure context (HTTP instead of HTTPS) */ import React from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Linking, Platform, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { WebBluetoothSupport, getUnsupportedBrowserMessage, BROWSER_HELP_URLS, } from '@/services/ble/webBluetooth'; interface BrowserNotSupportedProps { support: WebBluetoothSupport; onDismiss?: () => void; } /** * Get browser-specific icon */ function getBrowserIcon(browserName: string): keyof typeof Ionicons.glyphMap { switch (browserName.toLowerCase()) { case 'safari': return 'logo-apple'; case 'firefox': return 'logo-firefox'; case 'chrome': return 'logo-chrome'; case 'edge': return 'logo-edge'; default: return 'globe-outline'; } } /** * Get suggested browser based on current browser */ function getSuggestedBrowser(currentBrowser: string): { name: string; url: string } { // On desktop, suggest Chrome // On mobile, suggest appropriate browser if (Platform.OS === 'web') { return { name: 'Chrome', url: BROWSER_HELP_URLS.Chrome, }; } return { name: 'Chrome', url: BROWSER_HELP_URLS.Chrome, }; } export function BrowserNotSupported({ support, onDismiss }: BrowserNotSupportedProps) { const errorInfo = getUnsupportedBrowserMessage(support); const browserIcon = getBrowserIcon(support.browserName); const suggestedBrowser = getSuggestedBrowser(support.browserName); const handleOpenChrome = async () => { try { await Linking.openURL(suggestedBrowser.url); } catch { // Ignore errors opening URL } }; return ( {/* Browser Icon with X overlay */} {/* Title */} {errorInfo.title} {/* Browser info */} {support.browserName} {support.browserVersion} {/* Message */} {errorInfo.message} {/* Suggestion */} {errorInfo.suggestion} {/* Supported browsers list */} Supported browsers: Chrome Edge Opera {/* Action buttons */} Get Chrome {onDismiss && ( Continue anyway )} {/* Note for secure context */} {support.reason === 'insecure_context' && ( This page must be served over HTTPS for Bluetooth to work. )} ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fff', padding: 24, }, content: { alignItems: 'center', maxWidth: 360, }, iconContainer: { marginBottom: 24, }, iconWrapper: { width: 96, height: 96, borderRadius: 48, backgroundColor: '#F3F4F6', justifyContent: 'center', alignItems: 'center', position: 'relative', }, xOverlay: { position: 'absolute', bottom: -4, right: -4, backgroundColor: '#fff', borderRadius: 12, }, title: { fontSize: 22, fontWeight: '700', color: '#1F2937', textAlign: 'center', marginBottom: 4, }, browserInfo: { fontSize: 14, color: '#9CA3AF', marginBottom: 12, }, message: { fontSize: 15, color: '#6B7280', textAlign: 'center', lineHeight: 22, marginBottom: 16, }, suggestionBox: { flexDirection: 'row', alignItems: 'flex-start', backgroundColor: '#EFF6FF', paddingVertical: 12, paddingHorizontal: 16, borderRadius: 12, marginBottom: 24, gap: 10, }, suggestionText: { flex: 1, fontSize: 14, color: '#1E40AF', lineHeight: 20, }, supportedBrowsers: { width: '100%', marginBottom: 24, }, supportedTitle: { fontSize: 13, fontWeight: '600', color: '#6B7280', marginBottom: 12, textAlign: 'center', }, browserList: { flexDirection: 'row', justifyContent: 'center', gap: 24, }, browserItem: { alignItems: 'center', gap: 4, }, browserName: { fontSize: 12, color: '#6B7280', }, buttons: { width: '100%', gap: 12, }, downloadButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: '#3B82F6', paddingVertical: 14, paddingHorizontal: 24, borderRadius: 12, }, buttonIcon: { marginRight: 8, }, downloadButtonText: { color: '#fff', fontSize: 16, fontWeight: '600', }, dismissButton: { alignItems: 'center', justifyContent: 'center', paddingVertical: 12, }, dismissButtonText: { color: '#6B7280', fontSize: 15, }, secureNote: { flexDirection: 'row', alignItems: 'center', marginTop: 24, gap: 6, }, secureNoteText: { fontSize: 12, color: '#9CA3AF', }, }); export default BrowserNotSupported;