Visual edit in Lovable
Edited UI in Lovable
This commit is contained in:
@@ -1,17 +1,14 @@
|
|||||||
|
|
||||||
import React, { useCallback, useEffect, useState, useRef } from 'react';
|
import React, { useCallback, useEffect, useState, useRef } from 'react';
|
||||||
import { getAppVersionInfo, isAndroidPlatform } from '@/utils/platform';
|
import { getAppVersionInfo, isAndroidPlatform } from '@/utils/platform';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
|
||||||
interface AppVersionInfoProps {
|
interface AppVersionInfoProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
showDevInfo?: boolean; // 개발자 정보 표시 여부
|
showDevInfo?: boolean; // 개발자 정보 표시 여부
|
||||||
editable?: boolean; // 편집 가능 여부
|
editable?: boolean; // 편집 가능 여부
|
||||||
}
|
}
|
||||||
|
const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
||||||
const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|
||||||
className,
|
className,
|
||||||
showDevInfo = true,
|
showDevInfo = true,
|
||||||
editable = false
|
editable = false
|
||||||
@@ -24,38 +21,34 @@ const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|||||||
versionName: '1.0.0',
|
versionName: '1.0.0',
|
||||||
buildNumber: 1
|
buildNumber: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
const [retries, setRetries] = useState(0);
|
const [retries, setRetries] = useState(0);
|
||||||
|
|
||||||
// 편집 가능한 필드를 위한 상태
|
// 편집 가능한 필드를 위한 상태
|
||||||
const [editableVersionName, setEditableVersionName] = useState('1.0.0');
|
const [editableVersionName, setEditableVersionName] = useState('1.0.0');
|
||||||
const [editableBuildNumber, setEditableBuildNumber] = useState('1');
|
const [editableBuildNumber, setEditableBuildNumber] = useState('1');
|
||||||
|
|
||||||
// 버전 정보 가져오기
|
// 버전 정보 가져오기
|
||||||
const fetchVersionInfo = useCallback(async () => {
|
const fetchVersionInfo = useCallback(async () => {
|
||||||
if (!editable) {
|
if (!editable) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(false);
|
setError(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('앱 버전 정보 요청 시작... (retries:', retries, ')');
|
console.log('앱 버전 정보 요청 시작... (retries:', retries, ')');
|
||||||
console.log('현재 플랫폼은', isAndroidPlatform() ? 'Android' : '기타');
|
console.log('현재 플랫폼은', isAndroidPlatform() ? 'Android' : '기타');
|
||||||
|
|
||||||
// 재시도를 하는 경우 짤은 지연 추가
|
// 재시도를 하는 경우 짤은 지연 추가
|
||||||
if (retries > 0) {
|
if (retries > 0) {
|
||||||
await new Promise(resolve => setTimeout(resolve, 300));
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = await getAppVersionInfo();
|
const info = await getAppVersionInfo();
|
||||||
console.log('받은 앱 버전 정보:', info);
|
console.log('받은 앱 버전 정보:', info);
|
||||||
|
|
||||||
// 데이터 검증 - 유효한 버전 정보인지 확인
|
// 데이터 검증 - 유효한 버전 정보인지 확인
|
||||||
if (!info || typeof info !== 'object') {
|
if (!info || typeof info !== 'object') {
|
||||||
throw new Error('유효하지 않은 응답 형식');
|
throw new Error('유효하지 않은 응답 형식');
|
||||||
}
|
}
|
||||||
|
|
||||||
setVersionInfo({
|
setVersionInfo({
|
||||||
versionName: info.versionName,
|
versionName: info.versionName,
|
||||||
buildNumber: info.buildNumber,
|
buildNumber: info.buildNumber,
|
||||||
@@ -65,7 +58,6 @@ const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|||||||
// 편집 가능한 필드도 업데이트
|
// 편집 가능한 필드도 업데이트
|
||||||
setEditableVersionName(info.versionName);
|
setEditableVersionName(info.versionName);
|
||||||
setEditableBuildNumber(String(info.buildNumber));
|
setEditableBuildNumber(String(info.buildNumber));
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
console.log('앱 버전 정보 표시 준비 완료');
|
console.log('앱 버전 정보 표시 준비 완료');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -75,23 +67,23 @@ const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [retries, editable]);
|
}, [retries, editable]);
|
||||||
|
|
||||||
// 재시도 처리
|
// 재시도 처리
|
||||||
const handleRetry = useCallback(() => {
|
const handleRetry = useCallback(() => {
|
||||||
setRetries(prev => prev + 1);
|
setRetries(prev => prev + 1);
|
||||||
fetchVersionInfo();
|
fetchVersionInfo();
|
||||||
}, [fetchVersionInfo]);
|
}, [fetchVersionInfo]);
|
||||||
|
|
||||||
// 초기화 완료 후 한번 더 시도하도록 설정
|
// 초기화 완료 후 한번 더 시도하도록 설정
|
||||||
const initialLoadAttemptedRef = useRef(false);
|
const initialLoadAttemptedRef = useRef(false);
|
||||||
|
|
||||||
// 컴포넌트 마운트 시 즉시 실행 (IIFE)
|
// 컴포넌트 마운트 시 즉시 실행 (IIFE)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editable) {
|
if (!editable) {
|
||||||
(async () => {
|
(async () => {
|
||||||
// 즉시 버전 정보 가져오기 시도
|
// 즉시 버전 정보 가져오기 시도
|
||||||
await fetchVersionInfo();
|
await fetchVersionInfo();
|
||||||
|
|
||||||
// 300ms 후에 한번 더 시도 (네이티브 플러그인이 완전히 로드되지 않았을 경우 대비)
|
// 300ms 후에 한번 더 시도 (네이티브 플러그인이 완전히 로드되지 않았을 경우 대비)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (error || loading) {
|
if (error || loading) {
|
||||||
@@ -100,21 +92,19 @@ const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// 개발 모드에서는 버전 정보 변경을 쉽게 확인하기 위해 주기적 갱신
|
// 개발 모드에서는 버전 정보 변경을 쉽게 확인하기 위해 주기적 갱신
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
fetchVersionInfo();
|
fetchVersionInfo();
|
||||||
}, 30000); // 30초마다 새로 가져오기
|
}, 30000); // 30초마다 새로 가져오기
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [fetchVersionInfo, error, loading, editable]);
|
}, [fetchVersionInfo, error, loading, editable]);
|
||||||
|
|
||||||
if (editable) {
|
if (editable) {
|
||||||
return (
|
return <div className={className}>
|
||||||
<div className={className}>
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="versionName">앱 버전</Label>
|
<Label htmlFor="versionName">앱 버전</Label>
|
||||||
@@ -131,44 +121,24 @@ const AppVersionInfo: React.FC<AppVersionInfoProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="notes">메모</Label>
|
<Label htmlFor="notes">세부 설명</Label>
|
||||||
<Textarea
|
<Textarea id="notes" placeholder="추가 정보를 입력하세요" className="h-20" />
|
||||||
id="notes"
|
|
||||||
placeholder="추가 정보를 입력하세요"
|
|
||||||
className="h-20"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return <div className={className}>
|
||||||
return (
|
{loading ? <div className="py-1 text-center">
|
||||||
<div className={className}>
|
|
||||||
{loading ? (
|
|
||||||
<div className="py-1 text-center">
|
|
||||||
<p className="text-sm text-gray-400 animate-pulse">버전 정보 로딩 중...</p>
|
<p className="text-sm text-gray-400 animate-pulse">버전 정보 로딩 중...</p>
|
||||||
</div>
|
</div> : error ? <div className="py-1 text-center">
|
||||||
) : error ? (
|
|
||||||
<div className="py-1 text-center">
|
|
||||||
<p className="text-sm text-red-500">빌드 정보 로딩 오류</p>
|
<p className="text-sm text-red-500">빌드 정보 로딩 오류</p>
|
||||||
<button
|
<button onClick={handleRetry} className="text-xs text-blue-500 underline mt-1 px-2 py-0.5 rounded hover:bg-blue-50">
|
||||||
onClick={handleRetry}
|
|
||||||
className="text-xs text-blue-500 underline mt-1 px-2 py-0.5 rounded hover:bg-blue-50"
|
|
||||||
>
|
|
||||||
재시도
|
재시도
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> : <div className="py-1 text-center">
|
||||||
) : (
|
|
||||||
<div className="py-1 text-center">
|
|
||||||
<p className="text-sm">앱 버전 {versionInfo.versionName} <span className="font-mono">(빌드 {versionInfo.buildNumber})</span></p>
|
<p className="text-sm">앱 버전 {versionInfo.versionName} <span className="font-mono">(빌드 {versionInfo.buildNumber})</span></p>
|
||||||
{showDevInfo && versionInfo.versionCode && (
|
{showDevInfo && versionInfo.versionCode && <p className="text-xs text-gray-400 mt-1 font-mono">versionCode: {versionInfo.versionCode}</p>}
|
||||||
<p className="text-xs text-gray-400 mt-1 font-mono">versionCode: {versionInfo.versionCode}</p>
|
</div>}
|
||||||
)}
|
</div>;
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
export default AppVersionInfo;
|
||||||
export default AppVersionInfo;
|
|
||||||
Reference in New Issue
Block a user