Fix: SafeArea for iOS dynamic island
Fixes iOS safe area issues caused by the dynamic island.
This commit is contained in:
@@ -21,7 +21,17 @@ const Header: React.FC = () => {
|
||||
|
||||
// 플랫폼 감지
|
||||
useEffect(() => {
|
||||
setIsIOS(isIOSPlatform());
|
||||
const checkPlatform = async () => {
|
||||
try {
|
||||
const isiOS = isIOSPlatform();
|
||||
console.log('Header: iOS 플랫폼 감지 결과:', isiOS);
|
||||
setIsIOS(isiOS);
|
||||
} catch (error) {
|
||||
console.error('플랫폼 감지 중 오류:', error);
|
||||
}
|
||||
};
|
||||
|
||||
checkPlatform();
|
||||
}, []);
|
||||
|
||||
// 이미지 프리로딩 처리
|
||||
@@ -37,7 +47,8 @@ const Header: React.FC = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const headerClass = isIOS ? 'has-safe-area-top' : 'py-4';
|
||||
// iOS 전용 헤더 클래스 - 안전 영역 적용
|
||||
const headerClass = isIOS ? 'ios-notch-padding' : 'py-4';
|
||||
|
||||
return (
|
||||
<header className={headerClass}>
|
||||
|
||||
@@ -25,15 +25,22 @@ const SafeAreaContainer: React.FC<SafeAreaContainerProps> = ({
|
||||
|
||||
// 마운트 시 플랫폼 확인
|
||||
useEffect(() => {
|
||||
setIsIOS(isIOSPlatform());
|
||||
const checkPlatform = async () => {
|
||||
const isiOS = isIOSPlatform();
|
||||
console.log('SafeAreaContainer: 플랫폼 확인 - iOS:', isiOS);
|
||||
setIsIOS(isiOS);
|
||||
};
|
||||
|
||||
checkPlatform();
|
||||
}, []);
|
||||
|
||||
// 플랫폼에 따른 클래스 결정
|
||||
let safeAreaClass = '';
|
||||
let safeAreaClass = 'safe-area-container';
|
||||
|
||||
if (isIOS) {
|
||||
if (!bottomOnly) safeAreaClass += ' has-safe-area-top'; // iOS 상단 안전 영역
|
||||
if (!topOnly) safeAreaClass += ' has-safe-area-bottom'; // iOS 하단 안전 영역
|
||||
safeAreaClass += ' ios-safe-area'; // iOS 전용 클래스 추가
|
||||
} else {
|
||||
if (!bottomOnly) safeAreaClass += ' pt-4'; // 안드로이드 상단 여백
|
||||
if (!topOnly) safeAreaClass += ' pb-4'; // 안드로이드 하단 여백
|
||||
@@ -42,6 +49,30 @@ const SafeAreaContainer: React.FC<SafeAreaContainerProps> = ({
|
||||
// 추가 하단 여백 적용
|
||||
const extraBottomClass = extraBottomPadding ? 'pb-[80px]' : '';
|
||||
|
||||
// 디버그용 로그 추가
|
||||
useEffect(() => {
|
||||
if (isIOS) {
|
||||
console.log('SafeAreaContainer: iOS 안전 영역 적용됨', {
|
||||
topOnly,
|
||||
bottomOnly,
|
||||
extraBottomPadding
|
||||
});
|
||||
|
||||
// 안전 영역 값 확인 (CSS 변수)
|
||||
try {
|
||||
const computedStyle = getComputedStyle(document.documentElement);
|
||||
console.log('Safe area 변수 값:', {
|
||||
top: computedStyle.getPropertyValue('--safe-area-top'),
|
||||
bottom: computedStyle.getPropertyValue('--safe-area-bottom'),
|
||||
left: computedStyle.getPropertyValue('--safe-area-left'),
|
||||
right: computedStyle.getPropertyValue('--safe-area-right')
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('CSS 변수 확인 중 오류:', error);
|
||||
}
|
||||
}
|
||||
}, [isIOS, topOnly, bottomOnly]);
|
||||
|
||||
return (
|
||||
<div className={`${safeAreaClass} ${extraBottomClass} ${className}`}>
|
||||
{children}
|
||||
|
||||
@@ -52,11 +52,11 @@
|
||||
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
|
||||
/* Safe area 값 */
|
||||
--safe-area-top: env(safe-area-inset-top, 0px);
|
||||
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
|
||||
--safe-area-left: env(safe-area-inset-left, 0px);
|
||||
--safe-area-right: env(safe-area-inset-right, 0px);
|
||||
/* Safe area 값 - !important 추가하여 우선 적용 */
|
||||
--safe-area-top: env(safe-area-inset-top, 0px) !important;
|
||||
--safe-area-bottom: env(safe-area-inset-bottom, 0px) !important;
|
||||
--safe-area-left: env(safe-area-inset-left, 0px) !important;
|
||||
--safe-area-right: env(safe-area-inset-right, 0px) !important;
|
||||
}
|
||||
|
||||
.dark {
|
||||
@@ -150,17 +150,29 @@
|
||||
@apply neuro-pressed px-4 py-3 w-full focus:outline-none focus:ring-2 focus:ring-neuro-accent/30;
|
||||
}
|
||||
|
||||
/* 안전 영역 관련 클래스 */
|
||||
/* 안전 영역 관련 클래스 - 강화된 버전 */
|
||||
.safe-area-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ios-safe-area {
|
||||
/* iOS 전용 안전 영역 처리 */
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.has-safe-area-top {
|
||||
padding-top: max(1rem, var(--safe-area-top));
|
||||
padding-top: max(1rem, var(--safe-area-top)) !important;
|
||||
}
|
||||
|
||||
.has-safe-area-bottom {
|
||||
padding-bottom: max(1rem, var(--safe-area-bottom));
|
||||
padding-bottom: max(1rem, var(--safe-area-bottom)) !important;
|
||||
}
|
||||
|
||||
.ios-header {
|
||||
padding-top: max(1rem, var(--safe-area-top));
|
||||
padding-top: max(1rem, var(--safe-area-top)) !important;
|
||||
}
|
||||
|
||||
/* 모바일 화면에서의 추가 스타일 */
|
||||
@@ -186,6 +198,11 @@
|
||||
.SheetContent {
|
||||
@apply rounded-xl overflow-hidden;
|
||||
}
|
||||
|
||||
/* iOS 고유 노치/다이나믹 아일랜드 영역 고려한 추가 스타일 */
|
||||
.ios-safe-area-screen {
|
||||
padding: var(--safe-area-top) var(--safe-area-right) var(--safe-area-bottom) var(--safe-area-left) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 데스크탑 화면에서의 추가 스타일 */
|
||||
@@ -260,11 +277,21 @@
|
||||
/* iOS 전용 스타일 */
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.ios-safe-area-top {
|
||||
padding-top: var(--safe-area-top);
|
||||
padding-top: var(--safe-area-top) !important;
|
||||
}
|
||||
|
||||
.ios-safe-area-bottom {
|
||||
padding-bottom: var(--safe-area-bottom);
|
||||
padding-bottom: var(--safe-area-bottom) !important;
|
||||
}
|
||||
|
||||
/* iOS에서 노치/다이나믹 아일랜드 영역 처리를 위한 추가 클래스 */
|
||||
.ios-notch-padding {
|
||||
padding-top: max(1.5rem, var(--safe-area-top)) !important;
|
||||
}
|
||||
|
||||
/* iOS에서 하단 홈 인디케이터 영역을 위한 추가 클래스 */
|
||||
.ios-bottom-padding {
|
||||
padding-bottom: max(1.5rem, var(--safe-area-bottom)) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,26 @@ import { useDataInitialization } from '@/hooks/useDataInitialization';
|
||||
import { useIsMobile } from '@/hooks/use-mobile';
|
||||
import useNotifications from '@/hooks/useNotifications';
|
||||
import SafeAreaContainer from '@/components/SafeAreaContainer';
|
||||
import { BudgetData } from '@/contexts/budget/types';
|
||||
|
||||
// 기본 예산 데이터 (빈 객체 대신 사용할 더미 데이터)
|
||||
const defaultBudgetData: BudgetData = {
|
||||
daily: {
|
||||
targetAmount: 0,
|
||||
spentAmount: 0,
|
||||
remainingAmount: 0
|
||||
},
|
||||
weekly: {
|
||||
targetAmount: 0,
|
||||
spentAmount: 0,
|
||||
remainingAmount: 0
|
||||
},
|
||||
monthly: {
|
||||
targetAmount: 0,
|
||||
spentAmount: 0,
|
||||
remainingAmount: 0
|
||||
}
|
||||
};
|
||||
|
||||
// 메인 컴포넌트
|
||||
const Index = () => {
|
||||
@@ -69,7 +89,7 @@ const Index = () => {
|
||||
try {
|
||||
console.log('Index 페이지 마운트, 현재 데이터 상태:');
|
||||
console.log('트랜잭션:', transactions?.length || 0);
|
||||
console.log('예산 데이터:', budgetData);
|
||||
console.log('예산 데이터:', budgetData || defaultBudgetData);
|
||||
|
||||
// 페이지 첫 마운트 시에만 실행되는 로직으로 수정
|
||||
const isFirstMount = sessionStorage.getItem('initialDataLoaded') !== 'true';
|
||||
@@ -194,7 +214,7 @@ const Index = () => {
|
||||
|
||||
<HomeContent
|
||||
transactions={transactions || []}
|
||||
budgetData={budgetData || {}}
|
||||
budgetData={budgetData || defaultBudgetData}
|
||||
selectedTab={selectedTab}
|
||||
setSelectedTab={setSelectedTab}
|
||||
handleBudgetGoalUpdate={handleBudgetGoalUpdate}
|
||||
|
||||
Reference in New Issue
Block a user