feat: Phase 1 mobile tablet — Jenkins APK, PC tab, in-app update

Capacitor 확장으로 git push 시 Mobile Jenkins 빌드, PC 탭 Android/iPad 다운로드,
앱 내 APK 업데이트, iOS TestFlight API 및 Capacitor ios 프로젝트를 추가한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Macbook
2026-06-14 16:31:55 +09:00
parent 36c06b55ea
commit f34104b721
38 changed files with 1468 additions and 15 deletions
@@ -1,4 +1,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import { App } from '@capacitor/app';
import { Capacitor } from '@capacitor/core';
import {
resetPaperAccount,
sendFcmTest,
@@ -20,11 +22,21 @@ export default function SettingsScreen() {
const [fcmAvailable, setFcmAvailable] = useState(false);
const [pushPerm, setPushPerm] = useState<string>('—');
const [fcmBusy, setFcmBusy] = useState(false);
const [updateBusy, setUpdateBusy] = useState(false);
const [appVersion, setAppVersion] = useState('—');
useEffect(() => {
void loadFcmStatus().then(s => setFcmAvailable(!!s?.available));
}, []);
useEffect(() => {
if (Capacitor.isNativePlatform()) {
void App.getInfo().then(i => setAppVersion(i.version ?? '—'));
} else {
setAppVersion('web');
}
}, []);
const patch = useCallback((p: AppSettingsDto) => save(p as unknown as Parameters<typeof save>[0]), [save]);
const onLogout = () => {
@@ -205,6 +217,30 @@ export default function SettingsScreen() {
</SettingRow>
</SettingGroup>
<SettingGroup title="앱">
<SettingRow label="앱 버전">
<span className="text-muted">{appVersion}</span>
</SettingRow>
{Capacitor.getPlatform() === 'android' && (
<SettingRow label="업데이트" description="서버 APK 버전 확인">
<button
type="button"
className="btn-secondary"
style={{ padding: '8px 12px', minHeight: 36 }}
disabled={updateBusy}
onClick={() => {
setUpdateBusy(true);
void import('../../services/appUpdate')
.then(m => m.checkAndPromptAppUpdate())
.finally(() => setUpdateBusy(false));
}}
>
</button>
</SettingRow>
)}
</SettingGroup>
<SettingGroup title="네트워크">
<SettingRow label="API URL">
<input