[251111] feat: views - MediaPlayer.jsx, ProductAllSection.jsx, Product...
🕐 커밋 시간: 2025. 11. 11. 14:07:12 📊 변경 통계: • 총 파일: 3개 • 추가: +211줄 • 삭제: -37줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.v2.jsx 🔧 주요 변경 내용: • UI 컴포넌트 아키텍처 개선 • 대규모 기능 개발
This commit is contained in:
@@ -65,7 +65,7 @@ const isEnter = is('enter');
|
|||||||
const isLeft = is('left');
|
const isLeft = is('left');
|
||||||
const isRight = is('right');
|
const isRight = is('right');
|
||||||
|
|
||||||
const jumpBackKeyCode = 37;
|
const jumpBackKeyCode = 3
|
||||||
const jumpForwardKeyCode = 39;
|
const jumpForwardKeyCode = 39;
|
||||||
const controlsHandleAboveSelectionKeys = [13, 16777221, jumpBackKeyCode, jumpForwardKeyCode];
|
const controlsHandleAboveSelectionKeys = [13, 16777221, jumpBackKeyCode, jumpForwardKeyCode];
|
||||||
const getControlsHandleAboveHoldConfig = ({ frequency, time }) => ({
|
const getControlsHandleAboveHoldConfig = ({ frequency, time }) => ({
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ import ProductDescription
|
|||||||
from '../ProductContentSection/ProductDescription/ProductDescription';
|
from '../ProductContentSection/ProductDescription/ProductDescription';
|
||||||
import ProductDetail
|
import ProductDetail
|
||||||
from '../ProductContentSection/ProductDetail/ProductDetail.new';
|
from '../ProductContentSection/ProductDetail/ProductDetail.new';
|
||||||
import { ProductVideoV2 } from '../ProductContentSection/ProductVideo';
|
import { ProductVideoV2 } from '../ProductContentSection/ProductVideo/ProductVideo.v2.jsx';
|
||||||
import ProductVideo from '../ProductContentSection/ProductVideo/ProductVideo';
|
import ProductVideo from '../ProductContentSection/ProductVideo/ProductVideo';
|
||||||
import UserReviews from '../ProductContentSection/UserReviews/UserReviews';
|
import UserReviews from '../ProductContentSection/UserReviews/UserReviews';
|
||||||
// import ViewAllReviewsButton from '../ProductContentSection/UserReviews/ViewAllReviewsButton';
|
// import ViewAllReviewsButton from '../ProductContentSection/UserReviews/ViewAllReviewsButton';
|
||||||
@@ -405,6 +405,39 @@ export default function ProductAllSection({
|
|||||||
dispatch(clearAllToasts())
|
dispatch(clearAllToasts())
|
||||||
},[dispatch])
|
},[dispatch])
|
||||||
|
|
||||||
|
// 스크롤 컨테이너의 클릭 이벤트 추적용 로깅
|
||||||
|
const handleScrollContainerClick = useCallback((e) => {
|
||||||
|
console.log('📱 [ProductAllSection] TScrollerDetail onClick 감지됨', {
|
||||||
|
eventType: e.type,
|
||||||
|
target: e.target?.className,
|
||||||
|
currentTarget: e.currentTarget?.className,
|
||||||
|
bubbles: e.bubbles,
|
||||||
|
defaultPrevented: e.defaultPrevented,
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
|
eventPath: e.composedPath?.().slice(0, 5).map(el => ({
|
||||||
|
tag: el.tagName,
|
||||||
|
className: el.className,
|
||||||
|
id: el.id
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ContentContainer 레벨 클릭 이벤트 추적
|
||||||
|
const handleContentContainerClick = useCallback((e) => {
|
||||||
|
console.log('🎯 [ProductAllSection] ContentContainer onClick 감지됨', {
|
||||||
|
eventType: e.type,
|
||||||
|
target: e.target?.className,
|
||||||
|
currentTarget: e.currentTarget?.className,
|
||||||
|
bubbles: e.bubbles,
|
||||||
|
defaultPrevented: e.defaultPrevented,
|
||||||
|
eventPath: e.composedPath?.().slice(0, 8).map(el => ({
|
||||||
|
tag: el.tagName,
|
||||||
|
className: el.className,
|
||||||
|
id: el.id
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
// ADD TO CART 버튼 클릭 핸들러
|
// ADD TO CART 버튼 클릭 핸들러
|
||||||
const handleAddToCartClick = useCallback(() => {
|
const handleAddToCartClick = useCallback(() => {
|
||||||
// console.log('[AddToCart] Add To Cart button clicked');
|
// console.log('[AddToCart] Add To Cart button clicked');
|
||||||
@@ -966,6 +999,7 @@ export default function ProductAllSection({
|
|||||||
<ContentContainer
|
<ContentContainer
|
||||||
className={css.rightContentContainer}
|
className={css.rightContentContainer}
|
||||||
spotlightId="content-scroller-container"
|
spotlightId="content-scroller-container"
|
||||||
|
onClick={handleContentContainerClick}
|
||||||
>
|
>
|
||||||
<div className={css.scrollerWrapper}>
|
<div className={css.scrollerWrapper}>
|
||||||
<TScrollerDetail
|
<TScrollerDetail
|
||||||
@@ -978,6 +1012,7 @@ export default function ProductAllSection({
|
|||||||
spotlightDisabled={false}
|
spotlightDisabled={false}
|
||||||
spotlightRestrict="none"
|
spotlightRestrict="none"
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
|
onClick={handleScrollContainerClick}
|
||||||
>
|
>
|
||||||
<div className={css.productDetail}>
|
<div className={css.productDetail}>
|
||||||
{/* <LayoutSample onClick={handleLayoutSampleClick} /> */}
|
{/* <LayoutSample onClick={handleLayoutSampleClick} /> */}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const YOUTUBECONFIG = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProductVideoV2({
|
export function ProductVideoV2({
|
||||||
productInfo,
|
productInfo,
|
||||||
videoUrl,
|
videoUrl,
|
||||||
thumbnailUrl,
|
thumbnailUrl,
|
||||||
@@ -141,10 +141,14 @@ export default function ProductVideoV2({
|
|||||||
}, [canPlayVideo, isPlaying]);
|
}, [canPlayVideo, isPlaying]);
|
||||||
|
|
||||||
// 썸네일 클릭 핸들러 - 비디오 재생 시작 + Redux dispatch + MediaPlayer 메서드 호출
|
// 썸네일 클릭 핸들러 - 비디오 재생 시작 + Redux dispatch + MediaPlayer 메서드 호출
|
||||||
const handleThumbnailClick = useCallback(() => {
|
const handleThumbnailClick = useCallback((e) => {
|
||||||
console.log('🎬 [handleThumbnailClick] 썸네일 클릭됨', {
|
console.log('🎬 [handleThumbnailClick] 썸네일 클릭됨', {
|
||||||
canPlayVideo,
|
canPlayVideo,
|
||||||
isPlaying,
|
isPlaying,
|
||||||
|
eventType: e?.type,
|
||||||
|
target: e?.target?.className,
|
||||||
|
bubbles: e?.bubbles,
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
});
|
});
|
||||||
if (canPlayVideo && !isPlaying) {
|
if (canPlayVideo && !isPlaying) {
|
||||||
// console.log('[BgVideo] ProductVideoV2 - Starting video playback');
|
// console.log('[BgVideo] ProductVideoV2 - Starting video playback');
|
||||||
@@ -276,6 +280,9 @@ export default function ProductVideoV2({
|
|||||||
eventType: e.type,
|
eventType: e.type,
|
||||||
target: e.target?.className,
|
target: e.target?.className,
|
||||||
currentTarget: e.currentTarget?.className,
|
currentTarget: e.currentTarget?.className,
|
||||||
|
bubbles: e.bubbles,
|
||||||
|
cancelable: e.cancelable,
|
||||||
|
composed: e.composed,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 비디오 재생 중이고 전체화면이 아닐 때만 작동
|
// 비디오 재생 중이고 전체화면이 아닐 때만 작동
|
||||||
@@ -300,24 +307,14 @@ export default function ProductVideoV2({
|
|||||||
// 마우스 다운 (클릭) 이벤트 - capture phase에서 처리
|
// 마우스 다운 (클릭) 이벤트 - capture phase에서 처리
|
||||||
const handleVideoPlayerMouseDown = useCallback(
|
const handleVideoPlayerMouseDown = useCallback(
|
||||||
(e) => {
|
(e) => {
|
||||||
|
// ⚠️ 이 함수는 사용되지 않으므로 제거 예정
|
||||||
|
// videoPlayerWrapper의 onMouseDownCapture에서 처리됨
|
||||||
console.log('🎬 [ProductVideoV2] handleVideoPlayerMouseDown 실행됨', {
|
console.log('🎬 [ProductVideoV2] handleVideoPlayerMouseDown 실행됨', {
|
||||||
isPlaying,
|
isPlaying,
|
||||||
isFullscreen,
|
isFullscreen,
|
||||||
eventType: e.type,
|
eventType: e.type,
|
||||||
target: e.target?.className,
|
target: e.target?.className,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 비디오 재생 중이고 전체화면이 아닐 때만 작동
|
|
||||||
if (!isPlaying || isFullscreen) {
|
|
||||||
console.log('🎬 [ProductVideoV2] MouseDown 조건 불만족');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// capture phase에서 이벤트 처리
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
console.log('🎬 [ProductVideoV2] ✅ MouseDown detected at capture phase');
|
|
||||||
},
|
},
|
||||||
[isPlaying, isFullscreen]
|
[isPlaying, isFullscreen]
|
||||||
);
|
);
|
||||||
@@ -349,6 +346,34 @@ export default function ProductVideoV2({
|
|||||||
}
|
}
|
||||||
}, [isPlaying, isFullscreen, handleFullscreenKeyDown]);
|
}, [isPlaying, isFullscreen, handleFullscreenKeyDown]);
|
||||||
|
|
||||||
|
// 전역 클릭 이벤트 감시 (debugging용 - 모든 클릭이 document에 도달하는지 확인)
|
||||||
|
useEffect(() => {
|
||||||
|
const handleDocumentClick = (e) => {
|
||||||
|
// ProductVideoV2 관련 요소인 경우만 로깅
|
||||||
|
const isVideoElement = e.target?.closest('[class*="videoContainer"]') ||
|
||||||
|
e.target?.closest('[class*="videoPlayer"]') ||
|
||||||
|
e.target?.closest('[class*="videoThumbnail"]');
|
||||||
|
|
||||||
|
if (isVideoElement) {
|
||||||
|
console.log('📄 [Document Level] 전역 클릭 감지됨', {
|
||||||
|
eventPhase: e.eventPhase,
|
||||||
|
bubbles: e.bubbles,
|
||||||
|
target: e.target?.className,
|
||||||
|
eventPath: e.composedPath?.().slice(0, 6).map(el => ({
|
||||||
|
tag: el.tagName,
|
||||||
|
className: el.className,
|
||||||
|
id: el.id
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('click', handleDocumentClick, true);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('click', handleDocumentClick, true);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
// autoPlay 기능: 컴포넌트 마운트 후 500ms 후 자동 재생
|
// autoPlay 기능: 컴포넌트 마운트 후 500ms 후 자동 재생
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (autoPlay && canPlayVideo && !isPlaying) {
|
if (autoPlay && canPlayVideo && !isPlaying) {
|
||||||
@@ -397,6 +422,101 @@ export default function ProductVideoV2({
|
|||||||
};
|
};
|
||||||
}, [dispatch, isPlaying]);
|
}, [dispatch, isPlaying]);
|
||||||
|
|
||||||
|
// VideoContainer의 모든 클릭 감시 (Hooks는 early return 전에 정의되어야 함)
|
||||||
|
const handleVideoContainerClick = useCallback(
|
||||||
|
(e) => {
|
||||||
|
console.log('🎥 [ProductVideoV2] videoContainer onClick 감지됨', {
|
||||||
|
isPlaying,
|
||||||
|
isFullscreen,
|
||||||
|
eventType: e.type,
|
||||||
|
target: e.target?.className,
|
||||||
|
currentTarget: e.currentTarget?.className,
|
||||||
|
bubbles: e.bubbles,
|
||||||
|
defaultPrevented: e.defaultPrevented,
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isPlaying && !isFullscreen) {
|
||||||
|
console.log('🎥 [ProductVideoV2] videoContainer 클릭 → 직접 전체화면 토글 실행', {
|
||||||
|
direct: true,
|
||||||
|
});
|
||||||
|
e.preventDefault?.();
|
||||||
|
e.stopPropagation?.();
|
||||||
|
toggleFullscreen();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[isPlaying, isFullscreen, toggleFullscreen]
|
||||||
|
);
|
||||||
|
|
||||||
|
const containerProps = useMemo(() => {
|
||||||
|
const baseProps = {
|
||||||
|
onClick: handleVideoContainerClick, // 모든 상태에서 동일하게 적용
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isFullscreen) {
|
||||||
|
return {
|
||||||
|
...baseProps,
|
||||||
|
spotlightRestrict: 'self-only', // 포커스가 밖으로 나가지 않도록
|
||||||
|
spotlightId: 'product-video-v2-fullscreen',
|
||||||
|
onSpotlightDown: handleSpotlightDown, // 전체화면에서도 Down 키 동작
|
||||||
|
};
|
||||||
|
} else if (isPlaying) {
|
||||||
|
return {
|
||||||
|
...baseProps,
|
||||||
|
spotlightId: 'product-video-v2-playing',
|
||||||
|
onKeyDown: handleContainerKeyDown, // 일반 모드: 컨테이너에서 직접 처리
|
||||||
|
onSpotlightDown: handleSpotlightDown, // 일반 재생에서도 Down 키 동작
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return baseProps;
|
||||||
|
}
|
||||||
|
}, [isFullscreen, isPlaying, handleVideoContainerClick, handleSpotlightDown, handleContainerKeyDown]);
|
||||||
|
|
||||||
|
// ⚠️ 간단한 해결책: 비디오 영역 클릭 시 직접 동작 실행
|
||||||
|
const handleContainerClickFallback = useCallback((e) => {
|
||||||
|
const isThumbnailArea = e.target?.closest('[class*="videoThumbnail"]') ||
|
||||||
|
e.target?.closest('[class*="playButton"]');
|
||||||
|
|
||||||
|
const isVideoPlayerArea = e.target?.closest('[class*="videoPlayer"]') ||
|
||||||
|
e.target?.closest('[class*="VideoPlayer"]');
|
||||||
|
|
||||||
|
// 썸네일 클릭: 비디오 재생 시작
|
||||||
|
if (isThumbnailArea && !isPlaying) {
|
||||||
|
console.log('🎬 [handleContainerClickFallback] 썸네일 클릭 → 비디오 재생 시작');
|
||||||
|
handleThumbnailClick(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 비디오 재생 중 클릭: 전체화면 토글
|
||||||
|
if (isVideoPlayerArea && isPlaying && !isFullscreen) {
|
||||||
|
console.log('🎬 [handleContainerClickFallback] 비디오 클릭 → 전체화면 토글');
|
||||||
|
toggleFullscreen();
|
||||||
|
}
|
||||||
|
}, [isPlaying, isFullscreen, handleThumbnailClick, toggleFullscreen]);
|
||||||
|
|
||||||
|
// ⚠️ 핵심: TScrollerDetail이 capture phase에서 이벤트를 막으므로,
|
||||||
|
// ProductVideoV2 컨테이너 전체에서 capture phase를 다시 열어줌 (Hooks는 early return 전에)
|
||||||
|
const handleContainerMouseDownCapture = useCallback((e) => {
|
||||||
|
// 비디오 영역인지 확인
|
||||||
|
const isVideoArea = e.currentTarget === containerRef.current;
|
||||||
|
|
||||||
|
console.log('🔓 [ProductVideoV2 Container] onMouseDownCapture - TScrollerDetail 차단 우회', {
|
||||||
|
isVideoArea,
|
||||||
|
target: e.target?.className,
|
||||||
|
isPlaying,
|
||||||
|
isFullscreen,
|
||||||
|
});
|
||||||
|
|
||||||
|
toggleFullscreen();
|
||||||
|
|
||||||
|
// TScrollerDetail의 onClick 실행을 막기 위해 preventDefault 호출
|
||||||
|
if (isPlaying && !isFullscreen) {
|
||||||
|
console.log('🔓 [ProductVideoV2] TScrollerDetail onClick 실행 차단');
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}, [isPlaying, isFullscreen]);
|
||||||
|
|
||||||
|
// Early return: 비디오 재생 불가능한 경우
|
||||||
if (!canPlayVideo) return null;
|
if (!canPlayVideo) return null;
|
||||||
|
|
||||||
// 컨테이너 컴포넌트 결정
|
// 컨테이너 컴포넌트 결정
|
||||||
@@ -409,22 +529,6 @@ export default function ProductVideoV2({
|
|||||||
? SpottableComponent
|
? SpottableComponent
|
||||||
: 'div';
|
: 'div';
|
||||||
|
|
||||||
const containerProps = isFullscreen
|
|
||||||
? {
|
|
||||||
spotlightRestrict: 'self-only', // 포커스가 밖으로 나가지 않도록
|
|
||||||
spotlightId: 'product-video-v2-fullscreen',
|
|
||||||
onSpotlightDown: handleSpotlightDown, // 전체화면에서도 Down 키 동작
|
|
||||||
// 전체화면 모드: window 레벨에서 이벤트 처리
|
|
||||||
}
|
|
||||||
: isPlaying
|
|
||||||
? {
|
|
||||||
spotlightId: 'product-video-v2-playing',
|
|
||||||
onKeyDown: handleContainerKeyDown, // 일반 모드: 컨테이너에서 직접 처리
|
|
||||||
onSpotlightDown: handleSpotlightDown, // 일반 재생에서도 Down 키 동작
|
|
||||||
// 일반 재생 모드: 컨테이너가 포커스 받음
|
|
||||||
}
|
|
||||||
: {};
|
|
||||||
|
|
||||||
// VideoPlayer 컴포넌트 생성 함수
|
// VideoPlayer 컴포넌트 생성 함수
|
||||||
const renderVideoPlayer = () => {
|
const renderVideoPlayer = () => {
|
||||||
if (!isPlaying) return null;
|
if (!isPlaying) return null;
|
||||||
@@ -447,14 +551,26 @@ export default function ProductVideoV2({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseDownCapture={(e) => {
|
onMouseDownCapture={(e) => {
|
||||||
|
// ⚠️ 핵심: VideoPlayer 내부(실제 비디오 영역)에서만 이벤트를 살리고,
|
||||||
|
// 그 외 wrapper 영역에서만 preventDefault
|
||||||
|
const isVideoElement = e.target?.closest('[class*="videoPlayer"]') ||
|
||||||
|
e.target?.closest('video') ||
|
||||||
|
e.target?.closest('[class*="react-player"]');
|
||||||
|
|
||||||
console.log('🎬 [videoPlayerWrapper] onMouseDownCapture 실행됨', {
|
console.log('🎬 [videoPlayerWrapper] onMouseDownCapture 실행됨', {
|
||||||
isFullscreen,
|
isFullscreen,
|
||||||
isPlaying,
|
isPlaying,
|
||||||
|
isVideoElement,
|
||||||
|
target: e.target?.className,
|
||||||
});
|
});
|
||||||
if (!isFullscreen && isPlaying) {
|
|
||||||
|
// VideoPlayer가 아닌 wrapper 영역에서만 preventDefault
|
||||||
|
if (!isFullscreen && isPlaying && !isVideoElement) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
console.log('🛑 [videoPlayerWrapper] preventDefault - wrapper 배경 영역');
|
||||||
console.log('🎬 [videoPlayerWrapper] MouseDown at wrapper - capturing');
|
} else if (!isFullscreen && isPlaying && isVideoElement) {
|
||||||
|
// 실제 비디오 영역이면 이벤트를 전파시켜 click이 정상 발생하도록
|
||||||
|
console.log('✅ [videoPlayerWrapper] 이벤트 전파 허용 - 비디오 요소');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -508,12 +624,20 @@ export default function ProductVideoV2({
|
|||||||
{...containerProps}
|
{...containerProps}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={`${css.videoContainer} ${isFullscreen ? css.fullscreen : ''}`}
|
className={`${css.videoContainer} ${isFullscreen ? css.fullscreen : ''}`}
|
||||||
|
onMouseDownCapture={handleContainerMouseDownCapture}
|
||||||
|
onClick={handleContainerClickFallback}
|
||||||
>
|
>
|
||||||
{!isPlaying ? (
|
{!isPlaying ? (
|
||||||
// 썸네일 + 재생 버튼 표시
|
// 썸네일 + 재생 버튼 표시
|
||||||
<SpottableComponent
|
<SpottableComponent
|
||||||
className={css.videoThumbnailContainer}
|
className={css.videoThumbnailContainer}
|
||||||
onClick={handleThumbnailClick}
|
onClick={(e) => {
|
||||||
|
console.log('🎬 [SpottableComponent] onClick 실행됨', {
|
||||||
|
eventType: e.type,
|
||||||
|
target: e.target?.className,
|
||||||
|
});
|
||||||
|
handleThumbnailClick(e);
|
||||||
|
}}
|
||||||
onFocus={videoContainerOnFocus}
|
onFocus={videoContainerOnFocus}
|
||||||
onBlur={videoContainerOnBlur}
|
onBlur={videoContainerOnBlur}
|
||||||
spotlightId="product-video-v2-thumbnail"
|
spotlightId="product-video-v2-thumbnail"
|
||||||
@@ -545,11 +669,26 @@ export default function ProductVideoV2({
|
|||||||
handleVideoPlayerClick(e);
|
handleVideoPlayerClick(e);
|
||||||
}}
|
}}
|
||||||
onMouseDownCapture={(e) => {
|
onMouseDownCapture={(e) => {
|
||||||
|
// ⚠️ 핵심: VideoPlayer 영역 내에서만 이벤트를 살리고,
|
||||||
|
// 그 외 영역(스크롤 영역)에서만 preventDefault
|
||||||
|
const isVideoPlayerArea = e.target?.closest('[class*="videoPlayer"]') ||
|
||||||
|
e.target?.closest('[class*="VideoPlayer"]');
|
||||||
|
|
||||||
console.log('🎬 [normalContainerRef] onMouseDownCapture 실행됨', {
|
console.log('🎬 [normalContainerRef] onMouseDownCapture 실행됨', {
|
||||||
isPlaying,
|
isPlaying,
|
||||||
isFullscreen,
|
isFullscreen,
|
||||||
|
isVideoPlayerArea,
|
||||||
|
target: e.target?.className,
|
||||||
});
|
});
|
||||||
handleVideoPlayerMouseDown(e);
|
|
||||||
|
// VideoPlayer가 아닌 영역(스크롤 영역)에서만 preventDefault
|
||||||
|
if (!isVideoPlayerArea) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log('🛑 [normalContainerRef] preventDefault - 스크롤 영역에서의 클릭');
|
||||||
|
} else {
|
||||||
|
// VideoPlayer 영역이면 이벤트를 전파시켜 click이 정상 발생하도록
|
||||||
|
console.log('✅ [normalContainerRef] 이벤트 전파 허용 - VideoPlayer 영역');
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{renderVideoPlayer()}
|
{renderVideoPlayer()}
|
||||||
|
|||||||
Reference in New Issue
Block a user