import React, { useState, useCallback } from 'react'; import { View, Text, TouchableOpacity, TextInput, ScrollView, StyleSheet, Linking, Alert, } from 'react-native'; import type { PluginComponentProps, DebuggerPlugin } from '../../core/types'; const DeepLinkTesterPanel: React.FC = ({ theme }) => { const [url, setUrl] = useState(''); const [history, setHistory] = useState<{ url: string; timestamp: number; success: boolean }[]>( [], ); const [presets, setPresets] = useState([]); const handleOpen = useCallback(async () => { if (!url.trim()) return; try { const canOpen = await Linking.canOpenURL(url); if (canOpen) { await Linking.openURL(url); setHistory((prev) => [{ url, timestamp: Date.now(), success: true }, ...prev].slice(0, 20)); } else { Alert.alert('Error', `Cannot open URL: ${url}`); setHistory((prev) => [{ url, timestamp: Date.now(), success: false }, ...prev].slice(0, 20), ); } } catch (err) { Alert.alert('Error', err instanceof Error ? err.message : 'Failed'); setHistory((prev) => [{ url, timestamp: Date.now(), success: false }, ...prev].slice(0, 20)); } }, [url]); const handleSavePreset = useCallback(() => { if (!url.trim() || presets.includes(url)) return; setPresets((prev) => [url, ...prev]); }, [url, presets]); return ( {/* URL Input */} DEEP LINK URL 🔗 Open Link Save {/* Common Schemes */} COMMON SCHEMES {[ 'tel:+1234567890', 'mailto:test@example.com', 'sms:+1234567890', 'https://example.com', 'geo:37.7749,-122.4194', ].map((scheme) => ( setUrl(scheme)} activeOpacity={0.7} > {scheme.length > 25 ? scheme.slice(0, 25) + '…' : scheme} ))} {/* Saved Presets */} {presets.length > 0 && ( SAVED PRESETS {presets.map((preset, i) => ( setUrl(preset)} activeOpacity={0.7} > {preset} ))} )} {/* History */} {history.length > 0 && ( HISTORY {history.map((entry, i) => ( setUrl(entry.url)} activeOpacity={0.7} > {entry.success ? '✅' : '❌'} {entry.url} ))} )} ); }; const styles = StyleSheet.create({ container: { flex: 1 }, inputSection: { margin: 12, padding: 12, borderRadius: 12 }, section: { margin: 12, marginTop: 0, padding: 12, borderRadius: 12 }, sectionTitle: { fontSize: 11, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 8, }, urlInput: { height: 44, borderRadius: 8, paddingHorizontal: 12, fontSize: 14, borderWidth: 1, fontFamily: 'monospace', }, buttonRow: { flexDirection: 'row', gap: 8, marginTop: 12 }, primaryBtn: { flex: 1, height: 42, borderRadius: 8, alignItems: 'center', justifyContent: 'center', }, primaryBtnText: { color: '#FFF', fontSize: 14, fontWeight: '700' }, secondaryBtn: { paddingHorizontal: 16, height: 42, borderRadius: 8, alignItems: 'center', justifyContent: 'center', borderWidth: 1, }, secondaryBtnText: { fontSize: 13, fontWeight: '600' }, schemeGrid: { flexDirection: 'row', flexWrap: 'wrap', gap: 6 }, schemeChip: { paddingHorizontal: 10, paddingVertical: 6, borderRadius: 8, borderWidth: 1 }, schemeText: { fontSize: 11, fontFamily: 'monospace' }, presetRow: { paddingVertical: 10, borderBottomWidth: StyleSheet.hairlineWidth }, presetText: { fontSize: 13, fontFamily: 'monospace' }, historyRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 8, borderBottomWidth: StyleSheet.hairlineWidth, gap: 8, }, historyStatus: { fontSize: 12 }, historyUrl: { fontSize: 12, fontFamily: 'monospace', flex: 1 }, }); export function createDeepLinkTesterPlugin(): DebuggerPlugin { return { id: 'deep-link-tester', name: 'Links', icon: '🔗', component: DeepLinkTesterPanel, order: 120, }; }