feat: Android 폰·태블릿 다운로드·앱 내 업데이트 완료

CI에서 APK 버전 자동 bump, 앱 복귀 시 업데이트 확인·시스템 다운로드,
프론트 Android 전용 UI 정리(iPad는 향후).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Macbook
2026-06-14 17:03:10 +09:00
parent be45247dc9
commit c840e09885
8 changed files with 193 additions and 130 deletions
+11 -52
View File
@@ -107,12 +107,15 @@ const MobileTab: React.FC = () => {
<div className="app-download-hero">
<div className="app-download-app-icon" aria-hidden>GC</div>
<div>
<h3 className="app-download-app-name">GoldenChart Mobile</h3>
<h3 className="app-download-app-name">GoldenChart Android</h3>
<p className="app-download-meta">
{info.version && <span>v{info.version}</span>}
{info.sizeBytes != null && <span>{formatBytes(info.sizeBytes)}</span>}
{info.updatedAt && <span>{info.updatedAt}</span>}
</p>
<p className="app-download-muted" style={{ marginTop: 4, fontSize: 12 }}>
·릿() APK
</p>
</div>
</div>
@@ -123,7 +126,7 @@ const MobileTab: React.FC = () => {
<div className="app-download-qr app-download-qr--placeholder">QR </div>
)}
<div className="app-download-qr-help">
<strong> QR </strong>
<strong>·릿 QR </strong>
<p>Android에서 APK . .</p>
<p className="app-download-muted app-download-url" title={downloadUrl}>{downloadUrl}</p>
</div>
@@ -138,23 +141,20 @@ const MobileTab: React.FC = () => {
</button>
<details className="app-download-steps">
<summary> (Android)</summary>
<summary> (Android · ·)</summary>
<ol>
<li>QR APK를 .</li>
<li> .</li>
<li> APK .</li>
<li> .</li>
</ol>
</details>
<p className="app-download-ios-note">
iPad는 PC TestFlight . QR·APK는 Android .
</p>
</>
);
};
const PlatformCard: React.FC<{
platform: 'mac' | 'windows' | 'android' | 'ipad';
platform: 'mac' | 'windows' | 'android';
release?: DesktopAppPlatformReleaseDto;
mobile?: MobileAppReleaseInfoDto | null;
}> = ({ platform, release, mobile }) => {
@@ -162,7 +162,6 @@ const PlatformCard: React.FC<{
mac: { label: 'macOS (Apple Silicon · Intel)', icon: '🍎', ext: '.dmg', isLink: false },
windows: { label: 'Windows (64-bit)', icon: '🪟', ext: '.exe', isLink: false },
android: { label: 'Android (패드 · 폰)', icon: '🤖', ext: '.apk', isLink: false },
ipad: { label: 'iPad (TestFlight)', icon: '📱', ext: '', isLink: true },
} as const;
const { label, icon, ext } = configs[platform];
@@ -203,43 +202,6 @@ const PlatformCard: React.FC<{
);
}
if (platform === 'ipad') {
const testFlightUrl = mobile?.iosTestFlightUrl?.trim();
if (!mobile?.iosAvailable || !testFlightUrl) {
return (
<div className="app-download-pc-card app-download-pc-card--empty">
<div className="app-download-pc-icon" aria-hidden>{icon}</div>
<div>
<strong>{label}</strong>
<p className="app-download-muted">TestFlight </p>
</div>
</div>
);
}
return (
<div className="app-download-pc-card">
<div className="app-download-pc-icon" aria-hidden>{icon}</div>
<div className="app-download-pc-body">
<strong>{label}</strong>
<p className="app-download-meta">
<span>TestFlight </span>
</p>
<p className="app-download-muted app-download-url" title={testFlightUrl}>
Apple TestFlight
</p>
</div>
<a
href={testFlightUrl}
target="_blank"
rel="noopener noreferrer"
className="app-download-pc-btn app-download-pc-btn--link"
>
TestFlight
</a>
</div>
);
}
if (!release?.available || !release.downloadUrl) {
return (
<div className="app-download-pc-card app-download-pc-card--empty">
@@ -471,8 +433,7 @@ const DesktopTab: React.FC<{ canBuildDesktop: boolean }> = ({ canBuildDesktop })
}
}, [canBuildDesktop, buildBusy, isBuilding, reloadBuildStatus]);
const hasAny = info?.mac?.available || info?.windows?.available
|| mobileInfo?.available || mobileInfo?.iosAvailable;
const hasAny = info?.mac?.available || info?.windows?.available || mobileInfo?.available;
if (loading) return <p className="app-download-muted">PC </p>;
if (error) return <p className="app-download-error">{error}</p>;
@@ -534,7 +495,7 @@ const DesktopTab: React.FC<{ canBuildDesktop: boolean }> = ({ canBuildDesktop })
<div className="app-download-empty-icon" aria-hidden>💻</div>
<h3> </h3>
<p>
macOS(.dmg), Windows(.exe), Android(.apk) iPad TestFlight .
macOS(.dmg), Windows(.exe) Android(.apk) .
<br />
{canBuildDesktop
? '우측 상단 「앱 빌드」 버튼으로 Jenkins 빌드를 시작하세요.'
@@ -554,7 +515,6 @@ const DesktopTab: React.FC<{ canBuildDesktop: boolean }> = ({ canBuildDesktop })
<PlatformCard platform="mac" release={info?.mac} />
<PlatformCard platform="windows" release={info?.windows} />
<PlatformCard platform="android" mobile={mobileInfo} />
<PlatformCard platform="ipad" mobile={mobileInfo} />
</div>
)}
@@ -573,9 +533,8 @@ const DesktopTab: React.FC<{ canBuildDesktop: boolean }> = ({ canBuildDesktop })
</li>
<li><strong>Windows</strong>: setup.exe를 .</li>
<li><strong>Android (·)</strong>: APK를 . APK입니다.</li>
<li><strong>iPad</strong>: TestFlight (App Store ipa ).</li>
<li> PC <strong></strong> .</li>
<li>Android APK .</li>
<li>Android · <strong> </strong> APK를 .</li>
<li> Git <code>main</code> , .</li>
</ol>
</details>