diff --git a/com.twin.app.shoptime/src/actions/playActions.js b/com.twin.app.shoptime/src/actions/playActions.js index 3ccbeb93..564a3485 100644 --- a/com.twin.app.shoptime/src/actions/playActions.js +++ b/com.twin.app.shoptime/src/actions/playActions.js @@ -1,10 +1,10 @@ -import Spotlight from "@enact/spotlight"; +import Spotlight from '@enact/spotlight'; -import { URLS } from "../api/apiConfig"; -import { TAxios } from "../api/TAxios"; -import { panel_names } from "../utils/Config"; -import { types } from "./actionTypes"; -import { popPanel, pushPanel, updatePanel } from "./panelActions"; +import { URLS } from '../api/apiConfig'; +import { TAxios } from '../api/TAxios'; +import { panel_names } from '../utils/Config'; +import { types } from './actionTypes'; +import { popPanel, pushPanel, updatePanel } from './panelActions'; //yhcho /* @@ -30,7 +30,7 @@ export const startVideoPlayer = const panels = getState().panels.panels; const topPanel = panels[panels.length - 1]; let panelWorkingAction = pushPanel; - + const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL; if (topPanel && topPanel.name === panelName) { @@ -57,6 +57,7 @@ export const startVideoPlayer = }, 0); } }; + export const finishVideoPreview = () => (dispatch, getState) => { const panels = getState().panels.panels; const topPanel = panels[panels.length - 1]; @@ -68,12 +69,77 @@ export const finishVideoPreview = () => (dispatch, getState) => { dispatch(popPanel()); } }; + +export const finishModalVideoForce = () => (dispatch, getState) => { + const panels = getState().panels.panels; + + // modal PlayerPanel이 존재하는지 확인 (스택 어디에 있든) + const hasModalPlayerPanel = panels.some( + (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal + ); + + if (hasModalPlayerPanel) { + if (startVideoFocusTimer) { + clearTimeout(startVideoFocusTimer); + startVideoFocusTimer = null; + } + // panelName을 지정하면 스택 어디에 있든 해당 패널을 제거 + dispatch(popPanel(panel_names.PLAYER_PANEL)); + } +}; + +// 모달 비디오를 일시정지 (패널은 유지) +export const pauseModalVideo = () => (dispatch, getState) => { + const panels = getState().panels.panels; + + // modal PlayerPanel 찾기 + const modalPlayerPanel = panels.find( + (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal + ); + + if (modalPlayerPanel) { + console.log('[pauseModalVideo] Pausing modal video'); + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + ...modalPlayerPanel.panelInfo, + isPaused: true, // 일시정지 플래그 추가 + }, + }) + ); + } +}; + +// 모달 비디오를 재생 (일시정지 해제) +export const resumeModalVideo = () => (dispatch, getState) => { + const panels = getState().panels.panels; + + // modal PlayerPanel 찾기 + const modalPlayerPanel = panels.find( + (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal + ); + + if (modalPlayerPanel && modalPlayerPanel.panelInfo?.isPaused) { + console.log('[resumeModalVideo] Resuming modal video'); + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + ...modalPlayerPanel.panelInfo, + isPaused: false, // 일시정지 해제 + }, + }) + ); + } +}; + // 채팅 로그 가져오기 IF-LGSP-371 export const getChatLog = ({ patnrId, showId }) => (dispatch, getState) => { const onSuccess = (response) => { - console.log("getChatLog onSuccess", response.data); + console.log('getChatLog onSuccess', response.data); dispatch({ type: types.GET_CHAT_LOG, @@ -82,10 +148,10 @@ export const getChatLog = }; const onFail = (error) => { - console.error("getChatLog onFail", error); + console.error('getChatLog onFail', error); }; - TAxios(dispatch, getState, "get", URLS.CHAT_LOG, { patnrId, showId }, {}, onSuccess, onFail); + TAxios(dispatch, getState, 'get', URLS.CHAT_LOG, { patnrId, showId }, {}, onSuccess, onFail); }; // VOD 자막 가져오기 IF-LGSP-072 @@ -93,7 +159,7 @@ export const getSubTitle = ({ showSubtitleUrl }) => (dispatch, getState) => { const onSuccess = (response) => { - console.log("getSubTitle onSuccess", response.data); + console.log('getSubTitle onSuccess', response.data); dispatch({ type: types.GET_SUBTITLE, @@ -102,15 +168,15 @@ export const getSubTitle = }; const onFail = (error) => { - console.error("getSubTitle onFail", error); + console.error('getSubTitle onFail', error); dispatch({ type: types.GET_SUBTITLE, - payload: { url: showSubtitleUrl, data: "Error" }, + payload: { url: showSubtitleUrl, data: 'Error' }, }); }; if (!getState().play.subTitleBlobs[showSubtitleUrl]) { - TAxios(dispatch, getState, "get", URLS.SUBTITLE, { showSubtitleUrl }, {}, onSuccess, onFail); + TAxios(dispatch, getState, 'get', URLS.SUBTITLE, { showSubtitleUrl }, {}, onSuccess, onFail); } else { console.log("playActions getSubTitle no Nothing it's exist", showSubtitleUrl); } @@ -129,33 +195,35 @@ export const CLEAR_PLAYER_INFO = () => ({ * @param {object} videoInfo - 재생할 비디오 정보 (url, id 등) */ export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) => { - const { playerControl } = getState().home; - const currentOwnerId = playerControl.ownerId; + const { playerControl } = getState().home; + const currentOwnerId = playerControl.ownerId; - if (currentOwnerId === ownerId) return; // 이미 제어권 소유 + if (currentOwnerId === ownerId) return; // 이미 제어권 소유 - if (currentOwnerId) { - // 현재 제어중인 컴포넌트가 영구재생 배너이면 '일시정지' - if (currentOwnerId === 'banner0_persistent') { - dispatch(pausePlayerControl()); - } else { - // 다른 미리보기라면 완전히 숨김 - dispatch(releasePlayControl(currentOwnerId, true)); - } + if (currentOwnerId) { + // 현재 제어중인 컴포넌트가 영구재생 배너이면 '일시정지' + if (currentOwnerId === 'banner0_persistent') { + dispatch(pausePlayerControl()); + } else { + // 다른 미리보기라면 완전히 숨김 + dispatch(releasePlayControl(currentOwnerId, true)); } - - // 1. 매니저 상태 업데이트 - dispatch({ type: types.SET_PLAYER_CONTROL, payload: { ownerId } }); - - // 2. 공유 PlayerPanel의 상태 업데이트 - dispatch(updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - isHidden: false, - modal: true, - ...videoInfo - } - })); + } + + // 1. 매니저 상태 업데이트 + dispatch({ type: types.SET_PLAYER_CONTROL, payload: { ownerId } }); + + // 2. 공유 PlayerPanel의 상태 업데이트 + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + isHidden: false, + modal: true, + ...videoInfo, + }, + }) + ); }; /** @@ -163,28 +231,34 @@ export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) = * @param {string} ownerId - 제어권을 해제하는 컴포넌트의 고유 ID * @param {boolean} fromPreemption - 다른 요청에 의해 강제로 중단되었는지 여부 */ -export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch, getState) => { +export const releasePlayControl = + (ownerId, fromPreemption = false) => + (dispatch, getState) => { const { playerControl } = getState().home; if (fromPreemption || playerControl.ownerId === ownerId) { - // 1. 공유 PlayerPanel을 다시 숨김 - dispatch(updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - isHidden: true, - } - })); + // 1. 공유 PlayerPanel을 다시 숨김 + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + isHidden: true, + }, + }) + ); - // 2. 매니저 상태 업데이트 (현재 소유주 없음) - dispatch({ type: types.CLEAR_PLAYER_CONTROL }); + // 2. 매니저 상태 업데이트 (현재 소유주 없음) + dispatch({ type: types.CLEAR_PLAYER_CONTROL }); - // 3. 만약 '일시정지'된 영구재생 비디오가 있었다면, 제어권을 되돌려주고 다시 재생 - if (playerControl.isPaused && playerControl.ownerId === 'banner0_persistent') { - const persistentVideoInfo = { /* 영구 비디오 정보를 가져오는 로직 (필요시) */ }; - dispatch(requestPlayControl('banner0_persistent', persistentVideoInfo)); - } + // 3. 만약 '일시정지'된 영구재생 비디오가 있었다면, 제어권을 되돌려주고 다시 재생 + if (playerControl.isPaused && playerControl.ownerId === 'banner0_persistent') { + const persistentVideoInfo = { + /* 영구 비디오 정보를 가져오는 로직 (필요시) */ + }; + dispatch(requestPlayControl('banner0_persistent', persistentVideoInfo)); + } } -}; + }; /** * 현재 재생 중인 비디오를 '일시정지' 상태로 변경하는 액션. @@ -224,25 +298,25 @@ export const resumePlayerControl = (ownerId) => (dispatch, getState) => { * 이 액션은 어떤 배너에서든 클릭 시 호출됩니다. */ export const goToFullScreen = () => (dispatch, getState) => { - // 공유 PlayerPanel의 'modal' 상태를 false로 변경하여 전체화면으로 전환 - dispatch(updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - modal: false, - isHidden: false, // 혹시 숨겨져 있었다면 보이도록 - } - })); + // 공유 PlayerPanel의 'modal' 상태를 false로 변경하여 전체화면으로 전환 + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + modal: false, + isHidden: false, // 혹시 숨겨져 있었다면 보이도록 + }, + }) + ); }; - /** * 영구재생 비디오를 일시정지 상태로 만듭니다. (내부 사용) */ export const pausePlayerControl = () => ({ - type: types.PAUSE_PLAYER_CONTROL + type: types.PAUSE_PLAYER_CONTROL, }); - /** * 전체화면 플레이어에서 미리보기 상태로 복귀할 때 호출됩니다. * 중앙 'playerControl' 상태를 확인하여 올바른 위치와 비디오로 복원합니다. @@ -270,4 +344,4 @@ export const returnToPreview = () => (dispatch, getState) => { // 돌아갈 곳이 없으면 그냥 플레이어를 닫음 dispatch(finishVideoPreview()); } -}; \ No newline at end of file +}; diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx index 13aac021..dcf54e9f 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx @@ -495,7 +495,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha // ); const renderItem = useCallback( - (index, isHorizontal) => { + (index, isHorizontal, videoPlayerable = false) => { const data = bannerDataList?.[index] ?? {}; return (
@@ -507,6 +507,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha spotlightId={'banner' + index} handleShelfFocus={_handleShelfFocus} handleItemFocus={_handleItemFocus} + videoPlayerable={videoPlayerable} /> ) : data.shptmDspyTpNm === 'Random' ? ( ) : ( @@ -629,10 +631,10 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha return ( <> - {renderItem(0, true)} - {renderItem(1, true)} + {renderItem(0, true, true)} + {renderItem(1, true, true)} - {renderItem(2, false)} + {renderItem(2, false, false)} {/* //NOTE - 약관 동의 여부 & 추후 API 따라 팝업 표시 여부 결정 */} {introTermsAgree === 'Y' ? (
@@ -645,7 +647,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha />
) : ( - renderItem(3, false) + renderItem(3, false, false) )} ); @@ -653,23 +655,23 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha case 'DSP00202': { return ( <> - {renderItem(0, false)} + {renderItem(0, false, false)} - {renderItem(1, true)} - {renderItem(2, true)} + {renderItem(1, true, true)} + {renderItem(2, true, true)} - {renderItem(3, false)} + {renderItem(3, false, false)} ); } case 'DSP00203': { return ( <> - {renderItem(0, false)} - {renderItem(1, false)} + {renderItem(0, false, false)} + {renderItem(1, false, false)} - {renderItem(2, true)} - {renderItem(3, true)} + {renderItem(2, true, true)} + {renderItem(3, true, true)} ); diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx index b3f687a6..f26d3b62 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx @@ -1,55 +1,40 @@ -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import classNames from "classnames"; -import { useDispatch, useSelector } from "react-redux"; +import classNames from 'classnames'; +import { useDispatch, useSelector } from 'react-redux'; -import Spotlight from "@enact/spotlight"; -import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; -import Spottable from "@enact/spotlight/Spottable"; -import { getContainerId } from "@enact/spotlight/src/container"; +import Spotlight from '@enact/spotlight'; +import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import Spottable from '@enact/spotlight/Spottable'; +import { getContainerId } from '@enact/spotlight/src/container'; -import btnPlay from "../../../../assets/images/btn/btn-play-thumb-nor.png"; -import defaultLogoImg from "../../../../assets/images/ic-tab-partners-default@3x.png"; -import emptyHorImage from "../../../../assets/images/img-home-banner-empty-hor.png"; -import emptyVerImage from "../../../../assets/images/img-home-banner-empty-ver.png"; -import defaultImageItem from "../../../../assets/images/img-thumb-empty-product@3x.png"; -import liveShow from "../../../../assets/images/tag-liveshow.png"; -import { changeAppStatus } from "../../../actions/commonActions"; -import { updateHomeInfo } from "../../../actions/homeActions"; -import { - sendLogTopContents, - sendLogTotalRecommend, -} from "../../../actions/logActions"; -import { pushPanel } from "../../../actions/panelActions"; -import { - finishVideoPreview, - startVideoPlayer, -} from "../../../actions/playActions"; -import CustomImage from "../../../components/CustomImage/CustomImage"; -import usePriceInfo from "../../../hooks/usePriceInfo"; +import btnPlay from '../../../../assets/images/btn/btn-play-thumb-nor.png'; +import defaultLogoImg from '../../../../assets/images/ic-tab-partners-default@3x.png'; +import emptyHorImage from '../../../../assets/images/img-home-banner-empty-hor.png'; +import emptyVerImage from '../../../../assets/images/img-home-banner-empty-ver.png'; +import defaultImageItem from '../../../../assets/images/img-thumb-empty-product@3x.png'; +import liveShow from '../../../../assets/images/tag-liveshow.png'; +import { changeAppStatus } from '../../../actions/commonActions'; +import { updateHomeInfo } from '../../../actions/homeActions'; +import { sendLogTopContents, sendLogTotalRecommend } from '../../../actions/logActions'; +import { pushPanel } from '../../../actions/panelActions'; +import { finishVideoPreview, startVideoPlayer } from '../../../actions/playActions'; +import CustomImage from '../../../components/CustomImage/CustomImage'; +import usePriceInfo from '../../../hooks/usePriceInfo'; import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, LOG_TP_NO, panel_names, -} from "../../../utils/Config"; -import { $L, formatGMTString } from "../../../utils/helperMethods"; -import { TEMPLATE_CODE_CONF } from "../HomePanel"; -import css from "./RandomUnit.module.less"; +} from '../../../utils/Config'; +import { $L, formatGMTString } from '../../../utils/helperMethods'; +import { TEMPLATE_CODE_CONF } from '../HomePanel'; +import css from './RandomUnit.module.less'; -const SpottableComponent = Spottable("div"); +const SpottableComponent = Spottable('div'); -const Container = SpotlightContainerDecorator( - { enterTo: "last-focused" }, - "div" -); +const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); export default function RandomUnit({ bannerData, @@ -58,30 +43,25 @@ export default function RandomUnit({ handleShelfFocus, handleItemFocus, randomNumber, + videoPlayerable = false, }) { const dispatch = useDispatch(); const bannerDetailInfos = - bannerData && bannerData.bannerDetailInfos - ? bannerData.bannerDetailInfos - : []; + bannerData && bannerData.bannerDetailInfos ? bannerData.bannerDetailInfos : []; - const shptmTmplCd = useSelector( - (state) => state.home?.bannerData?.shptmTmplCd - ); + const shptmTmplCd = useSelector((state) => state.home?.bannerData?.shptmTmplCd); const nowMenu = useSelector((state) => state.common.menu.nowMenu); const entryMenu = useSelector((state) => state.common.menu.entryMenu); - const homeCategory = useSelector( - (state) => state.home.menuData?.data?.homeCategory - ); + const homeCategory = useSelector((state) => state.home.menuData?.data?.homeCategory); const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd); // 정상적으로 로딩되면 빈객체로 넘어가고 , 에러가 나면 객체안에 타입이 담겨옵니다. const broadcast = useSelector((state) => state.common.broadcast); const { curationId, curationTitle } = useSelector((state) => state.home); - const [randomData, setRandomData] = useState(""); - const [priceInfos, setpriceInfos] = useState(""); + const [randomData, setRandomData] = useState(''); + const [priceInfos, setpriceInfos] = useState(''); const [isFocused, setIsFocused] = useState(false); const [videoError, setVideoError] = useState(false); const [liveIndicies, setLiveIndicies] = useState([]); @@ -89,9 +69,7 @@ export default function RandomUnit({ const timerRef = useRef(); const bannerDataRef = useRef(bannerData); const randomDataRef = useRef( - bannerDetailInfos && - randomNumber !== undefined && - bannerDetailInfos.length > 0 + bannerDetailInfos && randomNumber !== undefined && bannerDetailInfos.length > 0 ? bannerDetailInfos[randomNumber] : null ); @@ -104,14 +82,14 @@ export default function RandomUnit({ switch (currentRandomData?.shptmBanrTpCd) { // case: "LIVE" or "VOD" - case "DSP00301": - case "DSP00302": + case 'DSP00301': + case 'DSP00302': contId = currentRandomData?.showId; contNm = currentRandomData?.showNm; break; // case: "Image Banner" - case "DSP00303": + case 'DSP00303': contId = currentRandomData?.shptmLnkTpCd; contNm = currentRandomData?.shptmLnkTpNm; break; @@ -124,27 +102,27 @@ export default function RandomUnit({ } if ( - currentRandomData?.shptmLnkTpCd === "DSP00503" || // "Hot Picks" - currentRandomData?.shptmLnkTpCd === "DSP00509" // "Theme" + currentRandomData?.shptmLnkTpCd === 'DSP00503' || // "Hot Picks" + currentRandomData?.shptmLnkTpCd === 'DSP00509' // "Theme" ) { - contNm = contNm + " | " + currentRandomData?.lnkCurationId; + contNm = contNm + ' | ' + currentRandomData?.lnkCurationId; } return { banrNo: `${currentRandomData?.banrDpOrd}`, banrTpNm: currentRandomData?.vtctpYn - ? currentRandomData.vtctpYn === "Y" - ? "Vertical" - : "Horizontal" - : "", + ? currentRandomData.vtctpYn === 'Y' + ? 'Vertical' + : 'Horizontal' + : '', contId, contNm, - contTpNm: currentRandomData?.shptmBanrTpNm ?? "", - dspyTpNm: bannerDataRef.current?.shptmDspyTpNm ?? "", - expsOrd: bannerDataRef.current?.banrLctnNo ?? "", - linkTpCd: "", - patncNm: currentRandomData?.patncNm ?? "", - patnrId: currentRandomData?.patnrId ?? "", + contTpNm: currentRandomData?.shptmBanrTpNm ?? '', + dspyTpNm: bannerDataRef.current?.shptmDspyTpNm ?? '', + expsOrd: bannerDataRef.current?.banrLctnNo ?? '', + linkTpCd: '', + patncNm: currentRandomData?.patncNm ?? '', + patnrId: currentRandomData?.patnrId ?? '', tmplCd: shptmTmplCd, }; } @@ -157,26 +135,24 @@ export default function RandomUnit({ const data = randomDataRef.current; const newParams = - data.shptmBanrTpNm === "LIVE" + data.shptmBanrTpNm === 'LIVE' ? { showId: data.showId, showTitle: data.showNm, - displayType: "Fix", - bannerType: "Horizontal", + displayType: 'Fix', + bannerType: 'Horizontal', } : { contentId: data.showId, contentTitle: data.showNm, - displayType: "Rolling", - bannerType: "Vertical", + displayType: 'Rolling', + bannerType: 'Vertical', }; if (data && nowMenu === LOG_MENU.HOME_TOP) { const logParams = { contextName: LOG_CONTEXT_NAME.HOME, - messageId: bannerClick - ? LOG_MESSAGE_ID.BANNER_CLICK - : LOG_MESSAGE_ID.BANNER, + messageId: bannerClick ? LOG_MESSAGE_ID.BANNER_CLICK : LOG_MESSAGE_ID.BANNER, ...newParams, curationId, curationTitle, @@ -189,9 +165,9 @@ export default function RandomUnit({ }; dispatch(sendLogTotalRecommend(logParams)); if (bannerClick) { - console.log("###bannerClick", logParams); + console.log('###bannerClick', logParams); } else { - console.log("###bannerShow", logParams); + console.log('###bannerShow', logParams); } } }, @@ -204,15 +180,9 @@ export default function RandomUnit({ // 라이브 영상이 1개 라도 순간적인 네트워크 오류나, 일시적인 오류 일수 있으므로, 일정 시간을 주고, 비디오를 다시 호출 한다. useEffect(() => { - if ( - bannerDetailInfos && - bannerDetailInfos.length > 0 && - randomNumber !== undefined - ) { + if (bannerDetailInfos && bannerDetailInfos.length > 0 && randomNumber !== undefined) { const indices = bannerDetailInfos - .map((info, index) => - info && info.shptmBanrTpNm === "LIVE" ? index : null - ) + .map((info, index) => (info && info.shptmBanrTpNm === 'LIVE' ? index : null)) .filter((index) => index !== null && index !== randomNumber); setLiveIndicies(indices); @@ -224,7 +194,7 @@ export default function RandomUnit({ return dispatch( pushPanel({ name: panel_names.FEATURED_BRANDS_PANEL, - panelInfo: { from: "gnb", patnrId: randomData.patnrId }, + panelInfo: { from: 'gnb', patnrId: randomData.patnrId }, }) ); }, [randomData, dispatch]); @@ -233,6 +203,11 @@ export default function RandomUnit({ const onFocus = useCallback(() => { setIsFocused(true); + // video가 플레이 가능한 경우 기존 비디오 즉시 종료료 + if (videoPlayerable) { + dispatch(finishVideoPreview()); + } + if (handleItemFocus) { handleItemFocus(); } @@ -249,9 +224,9 @@ export default function RandomUnit({ setIsFocused(false); clearTimeout(timerRef.current); - console.log("[RandomUnit] onBlur"); - dispatch(finishVideoPreview()); - console.log("[RandomUnit] finishVideoPreview"); + console.log('[RandomUnit] onBlur'); + // dispatch(finishVideoPreview()); + console.log('[RandomUnit] finishVideoPreview'); }, [isFocused]); // DSP00501 : Featured Brands @@ -265,11 +240,9 @@ export default function RandomUnit({ // DSP00509 : Theme const categoryData = useMemo(() => { - if (randomData && randomData.shptmLnkTpCd === "DSP00505") { + if (randomData && randomData.shptmLnkTpCd === 'DSP00505') { if (homeCategory && homeCategory.length > 0) { - const foundCategory = homeCategory.find( - (data) => data.lgCatCd === randomData.lgCatCd - ); + const foundCategory = homeCategory.find((data) => data.lgCatCd === randomData.lgCatCd); if (foundCategory) { return { lgCatNm: foundCategory.lgCatNm, @@ -287,21 +260,21 @@ export default function RandomUnit({ const linkType = randomData.shptmLnkTpCd; switch (linkType) { - case "DSP00501": + case 'DSP00501': linkInfo = { name: panel_names.FEATURED_BRANDS_PANEL, - panelInfo: { from: "gnb", patnrId: randomData.patnrId }, + panelInfo: { from: 'gnb', patnrId: randomData.patnrId }, }; break; - case "DSP00502": + case 'DSP00502': linkInfo = { name: panel_names.TRENDING_NOW_PANEL, panelInfo: {}, }; break; - case "DSP00503": + case 'DSP00503': linkInfo = { name: panel_names.HOT_PICKS_PANEL, panelInfo: { @@ -311,7 +284,7 @@ export default function RandomUnit({ }; break; - case "DSP00504": + case 'DSP00504': linkInfo = { name: panel_names.ON_SALE_PANEL, panelInfo: { @@ -320,7 +293,7 @@ export default function RandomUnit({ }; break; - case "DSP00505": + case 'DSP00505': if (Object.keys(categoryData).length > 0) { linkInfo = { name: panel_names.CATEGORY_PANEL, @@ -337,7 +310,7 @@ export default function RandomUnit({ } break; - case "DSP00506": + case 'DSP00506': linkInfo = { name: panel_names.DETAIL_PANEL, panelInfo: { @@ -348,29 +321,29 @@ export default function RandomUnit({ }; break; - case "DSP00507": + case 'DSP00507': linkInfo = { patnrId: randomData.patnrId, showId: randomData.showId, - shptmBanrTpNm: "VOD", + shptmBanrTpNm: 'VOD', lgCatCd: randomData.lgCatCd, modal: false, }; break; - case "DSP00508": + case 'DSP00508': linkInfo = { name: panel_names.DETAIL_PANEL, panelInfo: { patnrId: randomData.patnrId, curationId: randomData.lnkCurationId, prdtId: randomData.prdtId, - type: "theme", + type: 'theme', }, }; break; - case "DSP00509": + case 'DSP00509': linkInfo = { name: panel_names.THEME_CURATION_PANEL, panelInfo: { @@ -387,14 +360,14 @@ export default function RandomUnit({ break; } - let action = linkType === "DSP00507" ? startVideoPlayer : pushPanel; + let action = linkType === 'DSP00507' ? startVideoPlayer : pushPanel; dispatch(action(linkInfo)); sendBannerLog(true); dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); @@ -428,17 +401,11 @@ export default function RandomUnit({ dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); - }, [ - dispatch, - randomData?.patnrId, - randomData?.prdtId, - topContentsLogInfo, - sendBannerLog, - ]); + }, [dispatch, randomData?.patnrId, randomData?.prdtId, topContentsLogInfo, sendBannerLog]); // 비디오 클릭 const videoClick = useCallback(() => { @@ -451,7 +418,7 @@ export default function RandomUnit({ panelInfo: { lastFocusedTargetId, focusedContainerId: TEMPLATE_CODE_CONF.TOP, - currentSpot: currentSpot?.getAttribute("data-spotlight-id"), + currentSpot: currentSpot?.getAttribute('data-spotlight-id'), }, }) ); @@ -462,7 +429,7 @@ export default function RandomUnit({ showUrl: randomData.showUrl, patnrId: randomData.patnrId, showId: randomData.showId, - shptmBanrTpNm: randomData.showId ? randomData.shptmBanrTpNm : "MEDIA", + shptmBanrTpNm: randomData.showId ? randomData.shptmBanrTpNm : 'MEDIA', lgCatCd: randomData.lgCatCd, chanId: randomData.brdcChnlId, modal: false, @@ -474,22 +441,14 @@ export default function RandomUnit({ dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); sendBannerLog(true); onBlur(); - }, [ - randomData, - spotlightId, - topContentsLogInfo, - nowMenu, - randomDataRef, - sendBannerLog, - onBlur, - ]); + }, [randomData, spotlightId, topContentsLogInfo, nowMenu, randomDataRef, sendBannerLog, onBlur]); // 투데이즈 딜 가격 정보 const { originalPrice, discountedPrice, discountRate, offerInfo } = @@ -504,7 +463,7 @@ export default function RandomUnit({ const params = { ...topContentsLogInfo, entryMenu: _entryMenu, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.VIEW, nowMenu: _nowMenu, }; @@ -544,9 +503,7 @@ export default function RandomUnit({ showUrl: randomData.showUrl, patnrId: randomData.patnrId, showId: randomData.showId, - shptmBanrTpNm: randomData.showId - ? randomData.shptmBanrTpNm - : "MEDIA", + shptmBanrTpNm: randomData.showId ? randomData.shptmBanrTpNm : 'MEDIA', lgCatCd: randomData.lgCatCd, chanId: randomData.brdcChnlId, modal: true, @@ -568,7 +525,7 @@ export default function RandomUnit({ }, [isFocused]); useEffect(() => { - if (isFocused && broadcast?.type === "videoError") { + if (isFocused && broadcast?.type === 'videoError') { clearTimeout(timerRef.current); setVideoError(true); dispatch(finishVideoPreview()); @@ -595,23 +552,15 @@ export default function RandomUnit({ return ( <> - {randomData?.shptmBanrTpNm == "Image Banner" ? ( + {randomData?.shptmBanrTpNm == 'Image Banner' ? (
- ) : randomData?.shptmBanrTpNm == "LIVE" || - randomData?.shptmBanrTpNm == "VOD" ? ( + ) : randomData?.shptmBanrTpNm == 'LIVE' || randomData?.shptmBanrTpNm == 'VOD' ? ( - {randomData.shptmBanrTpNm == "LIVE" && videoError === false && ( + {randomData.shptmBanrTpNm == 'LIVE' && videoError === false && (

- +

)} @@ -656,26 +594,16 @@ export default function RandomUnit({
{randomData.patncLogoPath && ( - + )} -

- {$L("Click the screen to see more products!")} -

+

{$L('Click the screen to see more products!')}

)} {/* 배너 메인 이미지 */} {videoError === false && ( -
+
{randomData.tmnlImgPath ? ( @@ -699,7 +625,7 @@ export default function RandomUnit({ {/* 플레이 버튼 [>] */} {videoError === false && (
- {randomData.tmnlImgPath == null ? "" : } + {randomData.tmnlImgPath == null ? '' : }
)} @@ -723,15 +649,13 @@ export default function RandomUnit({ className={classNames( css.itemBox, css.todaysDeals, - countryCode === "RU" ? css.ru : "", - countryCode === "DE" ? css.de : "", + countryCode === 'RU' ? css.ru : '', + countryCode === 'DE' ? css.de : '', isHorizontal && css.isHorizontal )} onClick={todayDealClick} spotlightId={spotlightId} - aria-label={ - randomData.prdtNm ? randomData.prdtNm : randomData.tmnlImgNm - } + aria-label={randomData.prdtNm ? randomData.prdtNm : randomData.tmnlImgNm} >
{$L("TODAY's DEALS")}
@@ -742,7 +666,7 @@ export default function RandomUnit({ }} />
- {parseFloat(originalPrice?.replace("$", "")) === 0 + {parseFloat(originalPrice?.replace('$', '')) === 0 ? randomData?.offerInfo : discountRate ? discountedPrice @@ -751,10 +675,9 @@ export default function RandomUnit({ {originalPrice} )}
- {isHorizontal && - parseFloat(originalPrice?.replace("$", "")) !== 0 && ( - {originalPrice} - )} + {isHorizontal && parseFloat(originalPrice?.replace('$', '')) !== 0 && ( + {originalPrice} + )}
diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.module.less b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.module.less index 91cd742d..7f9ffe8a 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.module.less +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.module.less @@ -269,8 +269,20 @@ } } +// .videoModal { +// &::after { +// .focused(@boxShadow:0, @borderRadius: 12px); +// border: 6px solid @PRIMARY_COLOR_RED; +// top: -4px; +// right: -4px; +// bottom: -4px; +// left: -4px; +// } +// } + .videoModal { - &::after { + // 포커스를 받았을 때만 붉은색 테두리 표시 + &:focus-within::after { .focused(@boxShadow:0, @borderRadius: 12px); border: 6px solid @PRIMARY_COLOR_RED; top: -4px; @@ -278,4 +290,4 @@ bottom: -4px; left: -4px; } -} +} \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx index 98b6393c..c896fbd8 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx @@ -1,62 +1,50 @@ -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import classNames from "classnames"; -import { useDispatch, useSelector } from "react-redux"; +import classNames from 'classnames'; +import { useDispatch, useSelector } from 'react-redux'; -import Spotlight from "@enact/spotlight"; -import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; -import Spottable from "@enact/spotlight/Spottable"; -import { getContainerId } from "@enact/spotlight/src/container"; +import Spotlight from '@enact/spotlight'; +import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import Spottable from '@enact/spotlight/Spottable'; +import { getContainerId } from '@enact/spotlight/src/container'; -import btnPlay from "../../../../assets/images/btn/btn-play-thumb-nor.png"; -import defaultLogoImg from "../../../../assets/images/ic-tab-partners-default@3x.png"; -import emptyHorImage from "../../../../assets/images/img-home-banner-empty-hor.png"; -import emptyVerImage from "../../../../assets/images/img-home-banner-empty-ver.png"; -import defaultImageItem from "../../../../assets/images/img-thumb-empty-product@3x.png"; -import liveShow from "../../../../assets/images/tag-liveshow.png"; -import { setBannerIndex, updateHomeInfo } from "../../../actions/homeActions"; -import { - sendLogTopContents, - sendLogTotalRecommend, -} from "../../../actions/logActions"; -import { pushPanel } from "../../../actions/panelActions"; -import { startVideoPlayer } from "../../../actions/playActions"; -import CustomImage from "../../../components/CustomImage/CustomImage"; -import usePriceInfo from "../../../hooks/usePriceInfo"; +import btnPlay from '../../../../assets/images/btn/btn-play-thumb-nor.png'; +import defaultLogoImg from '../../../../assets/images/ic-tab-partners-default@3x.png'; +import emptyHorImage from '../../../../assets/images/img-home-banner-empty-hor.png'; +import emptyVerImage from '../../../../assets/images/img-home-banner-empty-ver.png'; +import defaultImageItem from '../../../../assets/images/img-thumb-empty-product@3x.png'; +import liveShow from '../../../../assets/images/tag-liveshow.png'; +import { setBannerIndex, updateHomeInfo } from '../../../actions/homeActions'; +import { sendLogTopContents, sendLogTotalRecommend } from '../../../actions/logActions'; +import { pushPanel } from '../../../actions/panelActions'; +import { startVideoPlayer } from '../../../actions/playActions'; +import CustomImage from '../../../components/CustomImage/CustomImage'; +import usePriceInfo from '../../../hooks/usePriceInfo'; import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, LOG_TP_NO, panel_names, -} from "../../../utils/Config"; -import { $L, formatGMTString } from "../../../utils/helperMethods"; -import { TEMPLATE_CODE_CONF } from "../HomePanel"; -import css from "./RollingUnit.module.less"; +} from '../../../utils/Config'; +import { $L, formatGMTString } from '../../../utils/helperMethods'; +import { TEMPLATE_CODE_CONF } from '../HomePanel'; +import css from './RollingUnit.module.less'; -const SpottableComponent = Spottable("div"); +const SpottableComponent = Spottable('div'); -const Container = SpotlightContainerDecorator( - { enterTo: "last-focused", preserveId: true }, - "div" -); +const Container = SpotlightContainerDecorator({ enterTo: 'last-focused', preserveId: true }, 'div'); const LINK_TYPES = { - FEATURED_BRANDS: "DSP00501", - TRENDING_NOW: "DSP00502", - HOT_PICKS: "DSP00503", - ON_SALE: "DSP00504", - CATEGORY: "DSP00505", - PRODUCT_DETAIL: "DSP00506", - VOD: "DSP00507", - SHOW_DETAIL: "DSP00508", - THEME: "DSP00509", + FEATURED_BRANDS: 'DSP00501', + TRENDING_NOW: 'DSP00502', + HOT_PICKS: 'DSP00503', + ON_SALE: 'DSP00504', + CATEGORY: 'DSP00505', + PRODUCT_DETAIL: 'DSP00506', + VOD: 'DSP00507', + SHOW_DETAIL: 'DSP00508', + THEME: 'DSP00509', }; const createPanelInfo = (data, categoryData = {}) => ({ @@ -78,6 +66,7 @@ export default function RollingUnit({ isHorizontal, handleItemFocus, handleShelfFocus, + videoPlayerable = false, }) { const rollingData = bannerData.bannerDetailInfos; const rollingDataLength = bannerData.bannerDetailInfos.length; @@ -86,23 +75,17 @@ export default function RollingUnit({ const { curationId, curationTitle } = useSelector((state) => state.home); const curtNm = useSelector((state) => state.home?.bannerData?.curtNm); - const shptmTmplCd = useSelector( - (state) => state.home?.bannerData?.shptmTmplCd - ); + const shptmTmplCd = useSelector((state) => state.home?.bannerData?.shptmTmplCd); const nowMenu = useSelector((state) => state.common.menu.nowMenu); const entryMenu = useSelector((state) => state.common.menu.entryMenu); - const homeCategory = useSelector( - (state) => state.home.menuData?.data?.homeCategory - ); + const homeCategory = useSelector((state) => state.home.menuData?.data?.homeCategory); const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd); const bannerId = `banner-${bannerData.banrLctnNo}`; const savedIndex = useSelector((state) => state.home.bannerIndices[bannerId]); - const [startIndex, setStartIndex] = useState( - savedIndex !== undefined ? savedIndex : 0 - ); + const [startIndex, setStartIndex] = useState(savedIndex !== undefined ? savedIndex : 0); const lastIndexRef = useRef(rollingDataLength - 1); const doRollingRef = useRef(false); const [unitHasFocus, setUnitHasFocus] = useState(false); @@ -124,14 +107,14 @@ export default function RollingUnit({ switch (currentRollingData?.shptmBanrTpCd) { // case: "LIVE" or "VOD" - case "DSP00301": - case "DSP00302": + case 'DSP00301': + case 'DSP00302': contId = currentRollingData?.showId; contNm = currentRollingData?.showNm; break; // case: "Image Banner" - case "DSP00303": + case 'DSP00303': contId = currentRollingData?.shptmLnkTpCd; contNm = currentRollingData?.shptmLnkTpNm; break; @@ -144,27 +127,27 @@ export default function RollingUnit({ } if ( - currentRollingData?.shptmLnkTpCd === "DSP00503" || // "Hot Picks" - currentRollingData?.shptmLnkTpCd === "DSP00509" // "Theme" + currentRollingData?.shptmLnkTpCd === 'DSP00503' || // "Hot Picks" + currentRollingData?.shptmLnkTpCd === 'DSP00509' // "Theme" ) { - contNm = contNm + " | " + currentRollingData?.lnkCurationId; + contNm = contNm + ' | ' + currentRollingData?.lnkCurationId; } return { banrNo: `${currentRollingData?.banrDpOrd}`, banrTpNm: currentRollingData?.vtctpYn - ? currentRollingData.vtctpYn === "Y" - ? "Vertical" - : "Horizontal" - : "", + ? currentRollingData.vtctpYn === 'Y' + ? 'Vertical' + : 'Horizontal' + : '', contId, contNm, - contTpNm: currentRollingData?.shptmBanrTpNm ?? "", - dspyTpNm: bannerDataRef.current?.shptmDspyTpNm ?? "", - expsOrd: bannerDataRef.current?.banrLctnNo ?? "", - linkTpCd: "", - patncNm: currentRollingData?.patncNm ?? "", - patnrId: currentRollingData?.patnrId ?? "", + contTpNm: currentRollingData?.shptmBanrTpNm ?? '', + dspyTpNm: bannerDataRef.current?.shptmDspyTpNm ?? '', + expsOrd: bannerDataRef.current?.banrLctnNo ?? '', + linkTpCd: '', + patncNm: currentRollingData?.patncNm ?? '', + patnrId: currentRollingData?.patnrId ?? '', tmplCd: shptmTmplCd, }; } @@ -175,19 +158,17 @@ export default function RollingUnit({ (bannerClick) => { const data = rollingDataRef.current[startIndex]; const newParams = - bannerData.banrLctnNo === "2" + bannerData.banrLctnNo === '2' ? { - bannerType: "Horizontal", + bannerType: 'Horizontal', } : { - bannerType: "Vertical", + bannerType: 'Vertical', }; if (rollingDataRef.current && nowMenu === LOG_MENU.HOME_TOP) { const logParams = { contextName: LOG_CONTEXT_NAME.HOME, - messageId: bannerClick - ? LOG_MESSAGE_ID.BANNER_CLICK - : LOG_MESSAGE_ID.BANNER, + messageId: bannerClick ? LOG_MESSAGE_ID.BANNER_CLICK : LOG_MESSAGE_ID.BANNER, curationId: curationId, curationTitle: curationTitle, contentType: data.shptmBanrTpNm, @@ -195,7 +176,7 @@ export default function RollingUnit({ contentTitle: data.showNm, productId: data.prdtId, productTitle: data.prdtNm, - displayType: "button", + displayType: 'button', partner: data.patncNm, brand: data.brndNm, location: bannerData.banrLctnNo, @@ -203,9 +184,9 @@ export default function RollingUnit({ }; dispatch(sendLogTotalRecommend(logParams)); if (bannerClick) { - console.log("###bannerClick", logParams); + console.log('###bannerClick', logParams); } else { - console.log("###bannerShow", logParams); + console.log('###bannerShow', logParams); } } }, @@ -223,16 +204,14 @@ export default function RollingUnit({ const deltaTime = time - previousTimeRef.current; if (deltaTime >= 10000 && doRollingRef.current) { - setStartIndex((prevIndex) => - prevIndex === lastIndexRef.current ? 0 : prevIndex + 1 - ); + setStartIndex((prevIndex) => (prevIndex === lastIndexRef.current ? 0 : prevIndex + 1)); previousTimeRef.current = time; } } else { previousTimeRef.current = time; } - if (typeof window === "object") { + if (typeof window === 'object') { requestRef.current = window.requestAnimationFrame(animate); } }, []); @@ -270,7 +249,7 @@ export default function RollingUnit({ // 인디케이터 아래키 누를시 [<] const prevKeyDown = (event) => { - if (event.key === "ArrowDown") { + if (event.key === 'ArrowDown') { setNextFocus(true); setContentsFocus(true); } @@ -278,7 +257,7 @@ export default function RollingUnit({ // 인디케이터 아래키 누를시 [>] const nextKeyDown = (event) => { - if (event.key === "ArrowDown") { + if (event.key === 'ArrowDown') { setPrevFocus(true); setContentsFocus(true); } @@ -362,7 +341,7 @@ export default function RollingUnit({ dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); @@ -372,23 +351,17 @@ export default function RollingUnit({ switch (linkType) { case LINK_TYPES.FEATURED_BRANDS: handlePushPanel(panel_names.FEATURED_BRANDS_PANEL, { - from: "gnb", + from: 'gnb', patnrId: currentData.patnrId, }); break; case LINK_TYPES.TRENDING_NOW: - handlePushPanel( - panel_names.TRENDING_NOW_PANEL, - createPanelInfo(currentData) - ); + handlePushPanel(panel_names.TRENDING_NOW_PANEL, createPanelInfo(currentData)); break; case LINK_TYPES.HOT_PICKS: - handlePushPanel( - panel_names.HOT_PICKS_PANEL, - createPanelInfo(currentData) - ); + handlePushPanel(panel_names.HOT_PICKS_PANEL, createPanelInfo(currentData)); break; case LINK_TYPES.ON_SALE: @@ -399,10 +372,7 @@ export default function RollingUnit({ case LINK_TYPES.CATEGORY: if (Object.keys(categoryData).length > 0) { - handlePushPanel( - panel_names.CATEGORY_PANEL, - createPanelInfo(currentData, categoryData) - ); + handlePushPanel(panel_names.CATEGORY_PANEL, createPanelInfo(currentData, categoryData)); } break; @@ -430,7 +400,7 @@ export default function RollingUnit({ dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); @@ -456,7 +426,7 @@ export default function RollingUnit({ panelInfo: { lastFocusedTargetId, focusedContainerId: TEMPLATE_CODE_CONF.TOP, - currentSpot: currentSpot?.getAttribute("data-spotlight-id"), + currentSpot: currentSpot?.getAttribute('data-spotlight-id'), }, }) ); @@ -472,7 +442,7 @@ export default function RollingUnit({ showUrl: currentData.showUrl, patnrId: currentData.patnrId, showId: currentData.showId, - shptmBanrTpNm: currentData.showId ? currentData.shptmBanrTpNm : "MEDIA", + shptmBanrTpNm: currentData.showId ? currentData.shptmBanrTpNm : 'MEDIA', lgCatCd: currentData.lgCatCd, chanId: currentData.brdcChnlId, modal: false, @@ -484,18 +454,11 @@ export default function RollingUnit({ dispatch( sendLogTopContents({ ...topContentsLogInfo, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK, }) ); - }, [ - rollingData, - startIndex, - bannerId, - dispatch, - handleStartVideoPlayer, - topContentsLogInfo, - ]); + }, [rollingData, startIndex, bannerId, dispatch, handleStartVideoPlayer, topContentsLogInfo]); // 10초 롤링 useEffect(() => { @@ -504,20 +467,20 @@ export default function RollingUnit({ previousTimeRef.current = undefined; if (rollingDataLength <= 1 || unitHasFocus) { doRollingRef.current = false; - if (typeof window === "object") { + if (typeof window === 'object') { window.cancelAnimationFrame(requestRef.current); } return; } doRollingRef.current = true; - if (typeof window === "object") { + if (typeof window === 'object') { requestRef.current = window.requestAnimationFrame(animate); } return () => { doRollingRef.current = false; - if (typeof window === "object") { + if (typeof window === 'object') { window.cancelAnimationFrame(requestRef.current); } }; @@ -531,7 +494,7 @@ export default function RollingUnit({ const params = { ...topContentsLogInfo, entryMenu: _entryMenu, - inDt: formatGMTString(new Date()) ?? "", + inDt: formatGMTString(new Date()) ?? '', logTpNo: LOG_TP_NO.TOP_CONTENTS.VIEW, nowMenu: _nowMenu, }; @@ -557,10 +520,7 @@ export default function RollingUnit({ return ( @@ -570,15 +530,14 @@ export default function RollingUnit({ onClick={handlePrev} onFocus={indicatorFocus} onBlur={indicatorBlur} - spotlightId={spotlightId + "Prev"} + spotlightId={spotlightId + 'Prev'} spotlightDisabled={prevFocus} onKeyDown={prevKeyDown} aria-label="Move to left Button" /> ) : null} - {rollingData && - rollingData[startIndex].shptmBanrTpNm === "Image Banner" ? ( + {rollingData && rollingData[startIndex].shptmBanrTpNm === 'Image Banner' ? (
- ) : rollingData[startIndex].shptmBanrTpNm === "LIVE" ? ( + ) : rollingData[startIndex].shptmBanrTpNm === 'LIVE' ? (

- +

-
+
{rollingData[startIndex].tmnlImgPath == null ? ( @@ -643,13 +588,9 @@ export default function RollingUnit({
{rollingData[startIndex].tmnlImgPath == null ? ( - "" + '' ) : ( - + )}
@@ -664,7 +605,7 @@ export default function RollingUnit({ />

- ) : rollingData[startIndex].shptmBanrTpNm === "VOD" ? ( + ) : rollingData[startIndex].shptmBanrTpNm === 'VOD' ? ( -
+
{rollingData[startIndex].tmnlImgPath == null ? ( ) : ( @@ -700,13 +632,9 @@ export default function RollingUnit({
{rollingData[startIndex].tmnlImgPath == null ? ( - "" + '' ) : ( - + )}
@@ -728,8 +656,8 @@ export default function RollingUnit({ className={classNames( css.itemBox, css.todaysDeals, - countryCode === "RU" ? css.ru : "", - countryCode === "DE" ? css.de : "", + countryCode === 'RU' ? css.ru : '', + countryCode === 'DE' ? css.de : '', isHorizontal && css.isHorizontal )} onClick={imageBannerClick} @@ -752,7 +680,7 @@ export default function RollingUnit({ }} />
- {parseFloat(originalPrice?.replace("$", "")) === 0 + {parseFloat(originalPrice?.replace('$', '')) === 0 ? rollingData[startIndex].offerInfo : discountRate ? discountedPrice @@ -761,10 +689,9 @@ export default function RollingUnit({ {originalPrice} )}
- {isHorizontal && - parseFloat(originalPrice?.replace("$", "")) !== 0 && ( - {originalPrice} - )} + {isHorizontal && parseFloat(originalPrice?.replace('$', '')) !== 0 && ( + {originalPrice} + )}
@@ -786,7 +713,7 @@ export default function RollingUnit({ onClick={handleNext} onFocus={indicatorFocus} onBlur={indicatorBlur} - spotlightId={spotlightId + "Next"} + spotlightId={spotlightId + 'Next'} spotlightDisabled={nextFocus} onKeyDown={nextKeyDown} aria-label="Move to right Button" diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx index 8bef5c6d..736a1c00 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx @@ -36,6 +36,8 @@ import { getChatLog, getSubTitle, startVideoPlayer, + pauseModalVideo, + resumeModalVideo, } from '../../actions/playActions'; import { convertUtcToLocal } from '../../components/MediaPlayer/util'; import TPanel from '../../components/TPanel/TPanel'; @@ -308,6 +310,53 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props } }, [panelInfo?.modal, panelInfo?.shptmBanrTpNm]); + // useEffect(()=>{ + // console.log('[PlayerPanel] isOnTop:', { + // isOnTop, + // panelInfo + // }); + // if (panelInfo && panelInfo.modal) { + // if (!isOnTop) { + // console.log('[PlayerPanel] Not on top - pausing video'); + // dispatch(pauseModalVideo()); + // } else if (isOnTop && panelInfo.isPaused) { + // console.log('[PlayerPanel] Back on top - resuming video'); + // dispatch(resumeModalVideo()); + // } + // } + // },[isOnTop, panelInfo]) + + // PlayerPanel.jsx의 라인 313-327 useEffect 수정 + useEffect(() => { + console.log('[PlayerPanel] isOnTop:', { + isOnTop, + panelInfo, + }); + + if (panelInfo && panelInfo.modal) { + if (!isOnTop) { + console.log('[PlayerPanel] Not on top - pausing video'); + dispatch(pauseModalVideo()); + } else if (isOnTop && panelInfo.isPaused) { + console.log('[PlayerPanel] Back on top - resuming video'); + dispatch(resumeModalVideo()); + } + } + }, [isOnTop, panelInfo]); + + // 새로운 useEffect 추가 (라인 328 이후) + useEffect(() => { + if (panelInfo?.modal && videoPlayer.current) { + if (panelInfo.isPaused) { + console.log('[PlayerPanel] Executing pause via videoPlayer.current'); + videoPlayer.current.pause(); + } else if (panelInfo.isPaused === false) { + console.log('[PlayerPanel] Executing play via videoPlayer.current'); + videoPlayer.current.play(); + } + } + }, [panelInfo?.isPaused, panelInfo?.modal]); + // creating live log params useEffect(() => { if (currentLiveShowInfo && Object.keys(currentLiveShowInfo).length > 0) {