[251014] refactor(views): [251014] ProductAllSection 동영상 포커스 처리
🕐 커밋 시간: 2025. 10. 14. 09:44:35 📊 변경 통계: • 총 파일: 2개 • 추가: +77줄 • 삭제: -80줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx (javascript): 🔄 Modified: extractProductMeta() Performance: 코드 최적화로 성능 개선 기대
This commit is contained in:
@@ -14,7 +14,7 @@ import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDeco
|
||||
//image
|
||||
import arrowDown from '../../../../assets/images/icons/ic_arrow_down_3x_new.png';
|
||||
import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png';
|
||||
import { pushPanel } from '../../../actions/panelActions';
|
||||
// import { pushPanel } from '../../../actions/panelActions';
|
||||
import { resetShowAllReviews } from '../../../actions/productActions';
|
||||
import { showToast } from '../../../actions/toastActions';
|
||||
// ProductInfoSection imports
|
||||
@@ -143,7 +143,7 @@ export default function ProductAllSection({
|
||||
const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
|
||||
|
||||
// ProductVideo 버전 관리 (1: 기존 modal 방식, 2: 내장 방식)
|
||||
const [productVideoVersion, setProductVideoVersion] = useState(2);
|
||||
const [productVideoVersion, setProductVideoVersion] = useState(1);
|
||||
|
||||
// const [currentHeight, setCurrentHeight] = useState(0);
|
||||
//하단부분까지 갔을때 체크용
|
||||
@@ -157,6 +157,9 @@ export default function ProductAllSection({
|
||||
// 모든 timeout/timer를 추적하기 위한 ref
|
||||
const timersRef = useRef([]);
|
||||
|
||||
// handleScrollToImages의 timeout을 추적하기 위한 ref
|
||||
const scrollToImagesTimeoutRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const toggleQRCode = () => {
|
||||
if (isShowQRCode) {
|
||||
@@ -251,34 +254,6 @@ export default function ProductAllSection({
|
||||
dispatch(resetShowAllReviews());
|
||||
}, []); // 빈 dependency array = 마운트 시에만 실행
|
||||
|
||||
// [임시 테스트] LayoutSample 클릭 핸들러 - ShowUserReviews와 동일하게 UserReviewPanel 열기
|
||||
// const handleLayoutSampleClick = useCallback(() => {
|
||||
// console.log(`[ProductId] LayoutSample clicked - opening UserReviewPanel`, {
|
||||
// productDataPrdtId: productData && productData.prdtId,
|
||||
// hasProductData: !!productData,
|
||||
// reviewTotalCount: stats.totalReviews,
|
||||
// averageRating: stats.averageRating,
|
||||
// productData: productData,
|
||||
// });
|
||||
// dispatch(
|
||||
// pushPanel({
|
||||
// name: panel_names.USER_REVIEW_PANEL,
|
||||
// panelInfo: {
|
||||
// prdtId: productData.prdtId,
|
||||
// productImage:
|
||||
// (productData.imgUrls600 && productData.imgUrls600[0]) ||
|
||||
// (productData.imgUrls && productData.imgUrls[0]) ||
|
||||
// productData.thumbnailUrl ||
|
||||
// "https://placehold.co/150x150",
|
||||
// brandLogo: productData.patncLogoPath || "https://placehold.co/50x50",
|
||||
// productName: productData.prdtNm || "상품명 정보가 없습니다",
|
||||
// avgRating: stats.averageRating || 5,
|
||||
// reviewCount: stats.totalReviews || 0,
|
||||
// },
|
||||
// })
|
||||
// );
|
||||
// }, [dispatch, productData, stats]);
|
||||
|
||||
// BUY NOW 버튼 클릭 핸들러 - Toast로 BuyOption 표시
|
||||
const handleBuyNowClick = useCallback(() => {
|
||||
// console.log('[BuyNow] Buy Now button clicked');
|
||||
@@ -298,26 +273,6 @@ export default function ProductAllSection({
|
||||
// TODO: 장바구니 추가 로직 구현
|
||||
}, []);
|
||||
|
||||
// 디버깅: 실제 이미지 및 동영상 데이터 확인
|
||||
// useEffect(() => {
|
||||
// console.log('[ProductId] ProductAllSection productData check:', {
|
||||
// hasProductData: !!productData,
|
||||
// productDataPrdtId: productData && productData.prdtId,
|
||||
// imgUrls600: productData && productData.imgUrls600,
|
||||
// imgUrls600Length: productData && productData.imgUrls600 && productData.imgUrls600.length,
|
||||
// imgUrls600Type: Array.isArray(productData && productData.imgUrls600)
|
||||
// ? 'array'
|
||||
// : typeof (productData && productData.imgUrls600),
|
||||
// // 동영상 관련 정보 추가
|
||||
// prdtMediaUrl: productData && productData.prdtMediaUrl,
|
||||
// thumbnailUrl960: productData && productData.thumbnailUrl960,
|
||||
// hasVideo: !!(productData && productData.prdtMediaUrl),
|
||||
// renderItemsLength: renderItems.length,
|
||||
// renderItems: renderItems,
|
||||
// productData: productData,
|
||||
// });
|
||||
// }, [productData, renderItems]);
|
||||
|
||||
const { revwGrd, orderPhnNo } = useMemo(() => extractProductMeta(productInfo), [productInfo]);
|
||||
|
||||
const [favoriteOverride, setFavoriteOverride] = useState(null);
|
||||
@@ -328,15 +283,7 @@ export default function ProductAllSection({
|
||||
|
||||
const [mobileSendPopupOpen, setMobileSendPopupOpen] = useState(false);
|
||||
|
||||
// useReviews에서 모든 리뷰 데이터 관리
|
||||
const reviewTotalCount = stats.totalReviews;
|
||||
// const reviewData = {
|
||||
// reviewList: previewReviews,
|
||||
// reviewDetail: {
|
||||
// totRvwCnt: stats.totalReviews,
|
||||
// avgRvwScr: stats.averageRating,
|
||||
// },
|
||||
// };
|
||||
const { getScrollTo, scrollTop } = useScrollTo();
|
||||
|
||||
const scrollToSection = useCallback(
|
||||
@@ -361,6 +308,22 @@ export default function ProductAllSection({
|
||||
[scrollToSection]
|
||||
);
|
||||
|
||||
// 비디오 다음 이미지로 스크롤하는 핸들러
|
||||
const handleScrollToImages = useCallback(() => {
|
||||
scrollToSection('scroll-marker-after-video');
|
||||
|
||||
// 기존 timeout이 있으면 클리어
|
||||
if (scrollToImagesTimeoutRef.current) {
|
||||
clearTimeout(scrollToImagesTimeoutRef.current);
|
||||
}
|
||||
|
||||
// 250ms 후 ProductDetail로 포커스 이동
|
||||
scrollToImagesTimeoutRef.current = setTimeout(() => {
|
||||
Spotlight.move('down');
|
||||
scrollToImagesTimeoutRef.current = null;
|
||||
}, 250);
|
||||
}, [scrollToSection]);
|
||||
|
||||
const scrollContainerRef = useRef(null);
|
||||
const productDetailRef = useRef(null); //높이값 변경때문
|
||||
const descriptionRef = useRef(null);
|
||||
@@ -516,6 +479,12 @@ export default function ProductAllSection({
|
||||
});
|
||||
timersRef.current = [];
|
||||
|
||||
// handleScrollToImages timeout cleanup
|
||||
if (scrollToImagesTimeoutRef.current) {
|
||||
clearTimeout(scrollToImagesTimeoutRef.current);
|
||||
scrollToImagesTimeoutRef.current = null;
|
||||
}
|
||||
|
||||
// console.log('[ProductAllSection] All timers cleaned up on unmount');
|
||||
};
|
||||
}, []);
|
||||
@@ -727,40 +696,47 @@ export default function ProductAllSection({
|
||||
onFocus={() => handleButtonFocus('product')}
|
||||
onBlur={handleButtonBlur}
|
||||
>
|
||||
{renderItems.length > 0 ? (
|
||||
renderItems.map((item, index) =>
|
||||
item.type === 'video' ? (
|
||||
productVideoVersion === 1 ? (
|
||||
<ProductVideo
|
||||
key="product-video-0"
|
||||
productInfo={productData}
|
||||
videoUrl={item.url}
|
||||
thumbnailUrl={item.thumbnail}
|
||||
/>
|
||||
) : (
|
||||
<ProductVideoV2
|
||||
key="product-video-v2-0"
|
||||
productInfo={productData}
|
||||
videoUrl={item.url}
|
||||
thumbnailUrl={item.thumbnail}
|
||||
autoPlay={true}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<ProductDetail
|
||||
key={`product-detail-${index}`}
|
||||
productInfo={{
|
||||
...productData,
|
||||
singleImage: item.url,
|
||||
imageIndex: item.index,
|
||||
totalImages: renderItems.length,
|
||||
}}
|
||||
{/* 비디오가 있으면 먼저 렌더링 */}
|
||||
{hasVideo && renderItems[0].type === 'video' && (
|
||||
<>
|
||||
{productVideoVersion === 1 ? (
|
||||
<ProductVideo
|
||||
key="product-video-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
onScrollToImages={handleScrollToImages}
|
||||
/>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<ProductDetail productInfo={productData} />
|
||||
) : (
|
||||
<ProductVideoV2
|
||||
key="product-video-v2-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
autoPlay={true}
|
||||
onScrollToImages={handleScrollToImages}
|
||||
/>
|
||||
)}
|
||||
<div id="scroll-marker-after-video" className={css.scrollMarker}></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 이미지들만 렌더링 (비디오 제외) */}
|
||||
{renderItems.length > 0
|
||||
? renderItems
|
||||
.filter((item) => item.type === 'image')
|
||||
.map((item, index) => (
|
||||
<ProductDetail
|
||||
key={`product-detail-${index}`}
|
||||
productInfo={{
|
||||
...productData,
|
||||
singleImage: item.url,
|
||||
imageIndex: item.index,
|
||||
totalImages: renderItems.length,
|
||||
}}
|
||||
/>
|
||||
))
|
||||
: !hasVideo && <ProductDetail productInfo={productData} />}
|
||||
</div>
|
||||
<div
|
||||
id="product-description-section"
|
||||
|
||||
@@ -13,7 +13,7 @@ import css from './ProductVideo.module.less';
|
||||
|
||||
const SpottableComponent = Spottable('div');
|
||||
|
||||
export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl }) {
|
||||
export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl, onScrollToImages }) {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// MediaPanel 상태 체크를 위한 selectors 추가
|
||||
@@ -70,6 +70,20 @@ export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl }) {
|
||||
}
|
||||
}, [canPlayVideo, dispatch]);
|
||||
|
||||
// Spotlight Down 키 핸들러 - 비디오 다음 이미지로 스크롤
|
||||
const handleSpotlightDown = useCallback(
|
||||
(e) => {
|
||||
if (canPlayVideo && onScrollToImages) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onScrollToImages();
|
||||
return true; // 이벤트 처리 완료
|
||||
}
|
||||
return false; // Spotlight가 기본 동작 수행
|
||||
},
|
||||
[canPlayVideo, onScrollToImages]
|
||||
);
|
||||
|
||||
// MediaPanel 비디오 클릭 핸들러 + 모달 토글 기능
|
||||
const handleVideoClick = useCallback(() => {
|
||||
console.log('[ProductVideo] ========== handleVideoClick 호출 ==========');
|
||||
@@ -148,6 +162,7 @@ export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl }) {
|
||||
onClick={handleVideoClick}
|
||||
onFocus={videoContainerOnFocus}
|
||||
onBlur={videoContainerOnBlur}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
spotlightId="product-video-player"
|
||||
aria-label={`${productInfo?.prdtNm} 동영상 재생`}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user