/** * 모바일 앱 설치 — APK 다운로드 URL·QR 코드 */ import React, { useEffect, useMemo, useState } from 'react'; import QRCode from 'qrcode'; import DraggableModalFrame from './DraggableModalFrame'; import { loadMobileAppReleaseInfo, type MobileAppReleaseInfoDto } from '../utils/backendApi'; interface Props { onClose: () => void; } function formatBytes(n?: number): string { if (n == null || !Number.isFinite(n)) return '—'; if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`; return `${(n / (1024 * 1024)).toFixed(1)} MB`; } /** APK·QR은 항상 서버가 내려준 절대 URL 사용 (exdev.co.kr, localhost 아님) */ function resolveDownloadUrl(info: MobileAppReleaseInfoDto | null): string { if (!info?.available) return ''; return info.downloadUrl?.trim() ?? ''; } const AppDownloadModal: React.FC = ({ onClose }) => { const [info, setInfo] = useState(null); const [loading, setLoading] = useState(true); const [qrDataUrl, setQrDataUrl] = useState(null); const [error, setError] = useState(null); const downloadUrl = useMemo(() => resolveDownloadUrl(info), [info]); useEffect(() => { let cancelled = false; void loadMobileAppReleaseInfo() .then(data => { if (!cancelled) setInfo(data); }) .catch(() => { if (!cancelled) setError('앱 정보를 불러오지 못했습니다.'); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); useEffect(() => { if (!downloadUrl) { setQrDataUrl(null); return; } let cancelled = false; void QRCode.toDataURL(downloadUrl, { width: 220, margin: 2, color: { dark: '#111827', light: '#ffffff' }, }).then(url => { if (!cancelled) setQrDataUrl(url); }).catch(() => { if (!cancelled) setQrDataUrl(null); }); return () => { cancelled = true; }; }, [downloadUrl]); const handleDownload = () => { if (!downloadUrl) return; const a = document.createElement('a'); a.href = downloadUrl; a.download = info?.fileName ?? 'goldenchart-android.apk'; a.rel = 'noopener'; document.body.appendChild(a); a.click(); a.remove(); }; return (
{loading &&

앱 정보 불러오는 중…

} {!loading && error &&

{error}

} {!loading && !error && !info?.available && (
📱

설치 파일 준비 중

Android APK가 아직 서버에 업로드되지 않았습니다.
data/mobile-releases/goldenchart-android.apk 경로에 빌드 파일을 배치하세요.

)} {!loading && info?.available && ( <>
GC

GoldenChart

{info.version && v{info.version}} {info.sizeBytes != null && {formatBytes(info.sizeBytes)}} {info.updatedAt && {info.updatedAt}}

{qrDataUrl ? ( 앱 설치 QR 코드 ) : (
QR 생성 중…
)}
휴대폰 카메라로 QR 스캔

Android에서 APK 다운로드 페이지가 열립니다. 다운로드 후 설치하세요.

{downloadUrl}

설치 방법 (Android)
  1. QR 코드를 스캔하거나 위 버튼으로 APK를 다운로드합니다.
  2. 「출처를 알 수 없는 앱」 설치 허용이 필요할 수 있습니다.
  3. 다운로드 완료 후 APK 파일을 탭하여 설치합니다.
  4. 설치 후 앱에서 API 서버 URL을 설정하세요 (설정 › 네트워크).

iOS는 App Store / TestFlight 배포가 필요합니다. 현재 QR·APK 설치는 Android 전용입니다.

)}
); }; export default AppDownloadModal;