[251217] fix: MediaPanel.v3.jsx 비디오복원 방어로직 추가
🕐 커밋 시간: 2025. 12. 17. 19:51:27 📊 변경 통계: • 총 파일: 2개 • 추가: +117줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx 🔧 주요 변경 내용: • 중간 규모 기능 개선
This commit is contained in:
@@ -183,6 +183,57 @@ const ButtonStackContainer = SpotlightContainerDecorator(
|
||||
|
||||
const SpottableComponent = Spottable('div');
|
||||
|
||||
// 🔽 [251217] ProductAllSection 스크롤 컨테이너 위치 저장/검증 함수
|
||||
// PlayerPanel의 배너 위치 검증 패턴을 ProductAllSection에 적용
|
||||
|
||||
/**
|
||||
* ProductAllSection의 스크롤 컨테이너 위치 수집 함수
|
||||
* @returns {Object|null} 스크롤 컨테이너의 위치 정보 (top, left) 또는 null
|
||||
*/
|
||||
const collectProductScrollPosition = () => {
|
||||
const scrollContainer = document.querySelector('[data-spotlight-id="main-content-scroller"]');
|
||||
|
||||
if (scrollContainer) {
|
||||
const { top, left } = scrollContainer.getBoundingClientRect();
|
||||
const position = {
|
||||
top: Math.round(top),
|
||||
left: Math.round(left)
|
||||
};
|
||||
console.log('[ProductAllSection] 스크롤 컨테이너 위치 수집:', position);
|
||||
return position;
|
||||
}
|
||||
|
||||
console.warn('[ProductAllSection] 스크롤 컨테이너를 찾을 수 없음');
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* ProductAllSection 스크롤 컨테이너 위치 검증 함수
|
||||
* @param {Object} savedPosition - 저장된 초기 위치
|
||||
* @param {Object} currentPosition - 현재 위치
|
||||
* @returns {boolean} 위치가 일치하는지 여부
|
||||
*/
|
||||
const isProductScrollPositionValid = (savedPosition, currentPosition) => {
|
||||
if (!savedPosition || !currentPosition) {
|
||||
console.warn('[ProductAllSection] 저장된 위치 또는 현재 위치가 없음');
|
||||
return false;
|
||||
}
|
||||
|
||||
const tolerance = 1; // 1px 오차 범위
|
||||
const isMatching =
|
||||
Math.abs(currentPosition.top - savedPosition.top) <= tolerance &&
|
||||
Math.abs(currentPosition.left - savedPosition.left) <= tolerance;
|
||||
|
||||
console.log('[ProductAllSection] 스크롤 위치 검증:', {
|
||||
expected: savedPosition,
|
||||
current: currentPosition,
|
||||
matching: isMatching,
|
||||
tolerance
|
||||
});
|
||||
|
||||
return isMatching;
|
||||
};
|
||||
|
||||
const getProductData = curry(
|
||||
(productType, themeProductInfo, themeProducts, selectedIndex, productInfo) =>
|
||||
pipe(
|
||||
@@ -304,6 +355,9 @@ export default function ProductAllSection({
|
||||
// handleScrollToImages의 timeout을 추적하기 위한 ref
|
||||
const scrollToImagesTimeoutRef = useRef(null);
|
||||
|
||||
// 🔽 [251217] 스크롤 컨테이너 초기 위치 저장 ref (VideoPlayer modal 전환 시 위치 검증용)
|
||||
const scrollPositionOnMountRef = useRef(null);
|
||||
|
||||
// ProductAllSection 초기 로딩 시 Skeleton 표시를 위한 상태
|
||||
const [isInitialLoading, setIsInitialLoading] = useState(true);
|
||||
|
||||
@@ -344,6 +398,19 @@ export default function ProductAllSection({
|
||||
);
|
||||
}, [selectedPatnrId, selectedPrdtId, userNumber, dispatch]);
|
||||
|
||||
// 🔽 [251217] ProductAllSection 마운트 시 스크롤 컨테이너 위치 저장
|
||||
useEffect(() => {
|
||||
// 초기 렌더링 후 스크롤 컨테이너의 위치를 저장 (1회만 실행)
|
||||
// 이 위치는 나중에 VideoPlayer의 modal 전환 시 유효성 검증에 사용됨
|
||||
const savedPosition = collectProductScrollPosition();
|
||||
if (savedPosition) {
|
||||
scrollPositionOnMountRef.current = savedPosition;
|
||||
// 🔽 window 객체에도 저장하여 MediaPanel.v3.jsx에서 접근 가능하게 함
|
||||
window.productScrollPositionOnMount = savedPosition;
|
||||
console.log('[ProductAllSection] ✅ 초기 스크롤 위치 저장 완료:', savedPosition);
|
||||
}
|
||||
}, []); // 마운트 시 1회만 실행
|
||||
|
||||
useEffect(() => {
|
||||
// 필수 값이 모두 있을 때만 호출
|
||||
if (selectedPatnrId && selectedPrdtId) {
|
||||
|
||||
@@ -93,6 +93,36 @@ const findSelector = (selector, maxAttempts = 5, currentAttempts = 0) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 🔽 [251217] ProductAllSection 스크롤 컨테이너 위치 수집 함수
|
||||
const collectProductScrollPosition = () => {
|
||||
const scrollContainer = document.querySelector('[data-spotlight-id="main-content-scroller"]');
|
||||
|
||||
if (scrollContainer) {
|
||||
const { top, left } = scrollContainer.getBoundingClientRect();
|
||||
const position = {
|
||||
top: Math.round(top),
|
||||
left: Math.round(left)
|
||||
};
|
||||
return position;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// 🔽 [251217] ProductAllSection 스크롤 컨테이너 위치 검증 함수
|
||||
const isProductScrollPositionValid = (savedPosition, currentPosition) => {
|
||||
if (!savedPosition || !currentPosition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tolerance = 1; // 1px 오차 범위
|
||||
const isMatching =
|
||||
Math.abs(currentPosition.top - savedPosition.top) <= tolerance &&
|
||||
Math.abs(currentPosition.left - savedPosition.left) <= tolerance;
|
||||
|
||||
return isMatching;
|
||||
};
|
||||
|
||||
const getLogTpNo = (type, nowMenu) => {
|
||||
if (type === 'LIVE') {
|
||||
switch (nowMenu) {
|
||||
@@ -1107,6 +1137,26 @@ const MediaPanel = React.forwardRef(
|
||||
}, [dispatch]);
|
||||
|
||||
const enterFullscreen = useCallback(() => {
|
||||
// 🔽 [251217] ProductAllSection 스크롤 위치 검증
|
||||
// DetailPanel에서 ProductAllSection의 초기 위치와 현재 위치를 비교하여 검증
|
||||
const savedPosition = window.productScrollPositionOnMount;
|
||||
const currentPosition = collectProductScrollPosition();
|
||||
|
||||
if (savedPosition && currentPosition) {
|
||||
const isValid = isProductScrollPositionValid(savedPosition, currentPosition);
|
||||
if (!isValid) {
|
||||
console.warn('[MediaPanel] ⚠️ ProductAllSection 스크롤 위치 검증 실패 - 전체화면 재생 가능하지만 경고 표시', {
|
||||
savedPosition,
|
||||
currentPosition,
|
||||
});
|
||||
// 사용자 피드백: 위치가 일치하지 않음을 콘솔에 기록 (비디오는 계속 재생)
|
||||
} else {
|
||||
console.log('[MediaPanel] ✅ ProductAllSection 스크롤 위치 검증 성공');
|
||||
}
|
||||
} else {
|
||||
console.warn('[MediaPanel] ⚠️ ProductAllSection 위치 정보 없음 - 검증 스킵');
|
||||
}
|
||||
|
||||
isTransitioningToFullscreen.current = true;
|
||||
dispatch(switchMediaToFullscreen());
|
||||
}, [dispatch]);
|
||||
|
||||
Reference in New Issue
Block a user