import { ActivityIndicator, Alert, Linking, TouchableOpacity, Text, TextInput, View, } from 'react-native'; import { useState } from 'react'; import { Ionicons } from '@expo/vector-icons'; import { useTranslation } from 'react-i18next'; import * as Haptics from 'expo-haptics'; import { useColors } from '../../lib/theme'; import { KeyboardAwareSheet } from '../KeyboardAwareSheet'; import { RiveAvatar } from '../RiveAvatar'; import { useProtectedDevicesStore } from '../../stores/protectedDevices'; import { useRouter } from 'expo-router'; // TODO lyra-persona: review windows_lyra_intro + windows_step_* body strings for coach tone type Step = 1 | 2 | 3; interface StepItem { titleKey: string; bodyKey: string; icon: React.ComponentProps['name']; } const STEPS: StepItem[] = [ { titleKey: 'devices.windows_step_1_title', bodyKey: 'devices.windows_step_1_body', icon: 'download-outline' }, { titleKey: 'devices.windows_step_2_title', bodyKey: 'devices.windows_step_2_body', icon: 'document-outline' }, { titleKey: 'devices.windows_step_3_title', bodyKey: 'devices.windows_step_3_body', icon: 'shield-checkmark-outline' }, { titleKey: 'devices.windows_step_4_title', bodyKey: 'devices.windows_step_4_body', icon: 'wifi-outline' }, { titleKey: 'devices.windows_step_5_title', bodyKey: 'devices.windows_step_5_body', icon: 'checkmark-circle-outline' }, ]; export function AddWindowsSheet({ visible, onClose, }: { visible: boolean; onClose: () => void; }) { const { t } = useTranslation(); const colors = useColors(); const router = useRouter(); const { enroll, confirmInstalled, enrolling } = useProtectedDevicesStore(); const [step, setStep] = useState(1); const [label, setLabel] = useState(t('devices.windows_label_default')); const [labelError, setLabelError] = useState(''); const [enrollResult, setEnrollResult] = useState<{ deviceId: string; downloadUrl: string } | null>(null); const [confirming, setConfirming] = useState(false); function reset() { setStep(1); setLabel(t('devices.windows_label_default')); setLabelError(''); setEnrollResult(null); setConfirming(false); } function handleClose() { reset(); onClose(); } async function handlePrepare() { const trimmed = label.trim(); if (!trimmed) { setLabelError(t('devices.windows_label_question')); return; } if (trimmed.length > 32) { setLabelError(t('devices.windows_label_question')); return; } setLabelError(''); try { const result = await enroll(trimmed, 'windows'); setEnrollResult(result); setStep(2); } catch { Alert.alert(t('common.error'), t('common.unknown_error')); } } async function handleConfirmInstalled() { if (!enrollResult) return; setConfirming(true); try { await confirmInstalled(enrollResult.deviceId); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {}); setStep(3); } catch { Alert.alert(t('common.error'), t('common.unknown_error')); } finally { setConfirming(false); } } function handleDownload() { if (!enrollResult?.downloadUrl) return; Linking.openURL(enrollResult.downloadUrl).catch(() => {}); } function handleNeedHelp() { handleClose(); router.push('/coach'); } const collapsedHeight = step === 1 ? 300 : step === 2 ? 700 : 380; return ( {step === 1 ? t('devices.windows_label_question') : step === 2 ? t('devices.windows_download_button') : t('devices.windows_success_title')} } > {step === 1 && ( )} {step === 2 && ( )} {step === 3 && ( )} ); } function WindowsStep1LabelContent({ label, setLabel, labelError, onPrepare, enrolling, colors, t, }: { label: string; setLabel: (v: string) => void; labelError: string; onPrepare: () => void; enrolling: boolean; colors: ReturnType; t: (k: string) => string; }) { return ( {labelError ? ( {labelError} ) : null} {enrolling ? ( ) : ( {t('devices.prepare_profile')} )} ); } function WindowsStep2OnboardingContent({ onDownload, onConfirmInstalled, onNeedHelp, confirming, colors, t, }: { onDownload: () => void; onConfirmInstalled: () => void; onNeedHelp: () => void; confirming: boolean; colors: ReturnType; t: (k: string) => string; }) { return ( {/* Lyra intro card */} {t('devices.windows_lyra_intro')} {/* 5-step list */} {STEPS.map((item, idx) => ( {t(item.titleKey)} {t(item.bodyKey)} ))} {/* Download button */} {t('devices.windows_download_button')} {/* Confirm installed */} {confirming ? ( ) : ( {t('devices.confirm_installed')} )} {/* Need help */} {t('devices.need_help')} ); } function WindowsStep3SuccessContent({ onClose, colors, t, }: { onClose: () => void; colors: ReturnType; t: (k: string) => string; }) { return ( {t('devices.windows_success_title')} {t('devices.windows_success_body')} {t('common.ok')} ); }