diff --git a/com.twin.app.shoptime/src/actions/actionTypes.js b/com.twin.app.shoptime/src/actions/actionTypes.js index 7290b862..68a17a80 100644 --- a/com.twin.app.shoptime/src/actions/actionTypes.js +++ b/com.twin.app.shoptime/src/actions/actionTypes.js @@ -201,9 +201,13 @@ export const types = { * * SET_PLAYER_CONTROL: 특정 컴포넌트에게 비디오 재생 제어권을 부여합니다. * CLEAR_PLAYER_CONTROL: 컴포넌트로부터 비디오 재생 제어권을 회수합니다. + * PAUSE_PLAYER_CONTROL: 현재 제어권을 가진 비디오를 '일시정지' 상태로 변경합니다. + * RESUME_PLAYER_CONTROL: '일시정지' 상태의 비디오를 다시 재생합니다. */ SET_PLAYER_CONTROL: "SET_PLAYER_CONTROL", CLEAR_PLAYER_CONTROL: "CLEAR_PLAYER_CONTROL", + PAUSE_PLAYER_CONTROL: "PAUSE_PLAYER_CONTROL", + RESUME_PLAYER_CONTROL: "RESUME_PLAYER_CONTROL", // reset action RESET_REDUX_STATE: "RESET_REDUX_STATE", diff --git a/com.twin.app.shoptime/src/actions/playActions.js b/com.twin.app.shoptime/src/actions/playActions.js index dd03f9ae..c7ba7025 100644 --- a/com.twin.app.shoptime/src/actions/playActions.js +++ b/com.twin.app.shoptime/src/actions/playActions.js @@ -133,13 +133,25 @@ export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) => { const { playerControl } = getState().home; const currentOwnerId = playerControl.ownerId; + const isPersistentOwner = currentOwnerId === 'banner0_persistent'; - // 이미 다른 컴포넌트가 제어권을 가지고 있다면, 먼저 해제한다. (선점) - if (currentOwnerId && currentOwnerId !== ownerId) { - dispatch(releasePlayControl(currentOwnerId, true)); // fromPreemption = true + // 이미 같은 컴포넌트가 제어권을 가지고 있다면 아무것도 하지 않음 + if (currentOwnerId === ownerId) { + return; } - // 새로운 제어권을 설정하고 비디오를 재생한다. + // 다른 컴포넌트가 제어권을 가지고 있을 때의 처리 (선점 로직) + if (currentOwnerId && currentOwnerId !== ownerId) { + // 만약 현재 재생중인 비디오가 영구 재생 비디오라면, 종료하는 대신 '일시정지' + if (isPersistentOwner) { + dispatch(pausePlayerControl(currentOwnerId)); + } else { + // 그 외의 경우는 기존처럼 완전히 종료 + dispatch(releasePlayControl(currentOwnerId, true)); // fromPreemption = true + } + } + + // 새로운 제어권을 설정하고 비디오를 재생 dispatch({ type: types.SET_PLAYER_CONTROL, payload: { ownerId }, @@ -158,6 +170,7 @@ export const requestPlayControl = */ export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch, getState) => { const { playerControl } = getState().home; + const isPersistentOwner = playerControl.ownerId === 'banner0_persistent'; // 제어권을 가진 컴포넌트가 자신일 경우에만 해제 // 단, 선점 로직에 의해 호출된 경우는 소유권 확인 없이 즉시 실행 @@ -166,5 +179,43 @@ export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch type: types.CLEAR_PLAYER_CONTROL, }); dispatch(finishVideoPreview()); + + // 제어권 해제 후, 만약 이전에 일시정지된 영구 비디오가 있었다면 다시 재생 + if (isPersistentOwner && playerControl.isPaused) { + dispatch(resumePlayerControl('banner0_persistent')); + } + } +}; + +/** + * 현재 재생 중인 비디오를 '일시정지' 상태로 변경하는 액션. + * 이 함수는 플레이어 패널을 닫지 않고, 단순히 비디오 재생을 멈추는 신호를 보냅니다. + * + * @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID. + */ +export const pausePlayerControl = (ownerId) => (dispatch, getState) => { + const { playerControl } = getState().home; + + // 제어권을 가진 컴포넌트가 자신일 경우에만 일시정지 + if (playerControl.ownerId === ownerId) { + dispatch({ + type: types.PAUSE_PLAYER_CONTROL, + }); + } +}; + +/** + * '일시정지' 상태의 비디오를 다시 재생하는 액션. + * + * @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID. + */ +export const resumePlayerControl = (ownerId) => (dispatch, getState) => { + const { playerControl } = getState().home; + + // 제어권을 가진 컴포넌트가 자신이고, 일시정지 상태일 때만 재개 + if (playerControl.ownerId === ownerId && playerControl.isPaused) { + dispatch({ + type: types.RESUME_PLAYER_CONTROL, + }); } }; diff --git a/com.twin.app.shoptime/src/reducers/homeReducer.js b/com.twin.app.shoptime/src/reducers/homeReducer.js index 988084e6..cc9eeec0 100644 --- a/com.twin.app.shoptime/src/reducers/homeReducer.js +++ b/com.twin.app.shoptime/src/reducers/homeReducer.js @@ -23,6 +23,7 @@ const initialState = { curationTitle: "", playerControl: { ownerId: null, + isPaused: false, }, }; @@ -198,6 +199,7 @@ export const homeReducer = (state = initialState, action) => { playerControl: { ...state.playerControl, ownerId: action.payload.ownerId, + isPaused: false, }, }; } @@ -208,6 +210,27 @@ export const homeReducer = (state = initialState, action) => { playerControl: { ...state.playerControl, ownerId: null, + isPaused: false, + }, + }; + } + + case types.PAUSE_PLAYER_CONTROL: { + return { + ...state, + playerControl: { + ...state.playerControl, + isPaused: true, + }, + }; + } + + case types.RESUME_PLAYER_CONTROL: { + return { + ...state, + playerControl: { + ...state.playerControl, + isPaused: false, }, }; } 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 b6ddfd7b..5e96fdf6 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx @@ -266,27 +266,80 @@ export default function HomeBanner({ } }, [shouldShowOptionalTermsPopup, termsLoading]); + // const renderItem = useCallback( + // (index, isHorizontal) => { + // const data = bannerDataList?.[index] ?? {}; + + // if (index === 1) { + // return ( + //
+ // + //
+ // ); + // } + + // return ( + //
+ // {data.shptmDspyTpNm === "Rolling" ? ( + // + // ) : data.shptmDspyTpNm === "Random" ? ( + // + // ) : ( + // + // + // + // )} + //
+ // ); + // }, + // [ + // bannerDataList, + // _handleItemFocus, + // _handleShelfFocus, + // handleSecondBannerFocus, + // handleSecondBannerBlur, + // ], + // ); + const renderItem = useCallback( (index, isHorizontal) => { const data = bannerDataList?.[index] ?? {}; - - if (index === 1) { - return ( -
- -
- ); - } - return (
{data.shptmDspyTpNm === "Rolling" ? ( @@ -328,13 +381,7 @@ export default function HomeBanner({
); }, - [ - bannerDataList, - _handleItemFocus, - _handleShelfFocus, - handleSecondBannerFocus, - handleSecondBannerBlur, - ], + [_handleItemFocus, _handleShelfFocus, bannerDataList] ); const renderItemPersistentVideo = useCallback( diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.new.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.new.jsx index 8f6234b7..a0e84133 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.new.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.new.jsx @@ -1,796 +1,771 @@ import React, { - useCallback, - useEffect, - useLayoutEffect, - useMemo, - useRef, - } from "react"; - - import classNames from "classnames"; - import { useDispatch } from "react-redux"; - - import { Job } from "@enact/core/util"; - import Spotlight from "@enact/spotlight"; - import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; - import { setContainerLastFocusedElement } from "@enact/spotlight/src/container"; - - import dummyVtt from "../../../assets/mock/video.vtt"; - import { - changeAppStatus, - changeLocalSettings, - requestLiveSubtitle, - sendBroadCast, - setHidePopup, - } from "../../actions/commonActions"; - import { - sendLogGNB, - sendLogLive, - sendLogTotalRecommend, - sendLogVOD, - } from "../../actions/logActions"; - import { - clearShopNowInfo, - getHomeFullVideoInfo, - getMainCategoryShowDetail, - getMainLiveShow, - getMainLiveShowNowProduct, - } from "../../actions/mainActions"; - import * as PanelActions from "../../actions/panelActions"; - import { updatePanel } from "../../actions/panelActions"; - import { - CLEAR_PLAYER_INFO, - getChatLog, - getSubTitle, - startVideoPlayer, - } from "../../actions/playActions"; - import { convertUtcToLocal } from "../../components/MediaPlayer/util"; - import TPanel from "../../components/TPanel/TPanel"; - import TPopUp from "../../components/TPopUp/TPopUp"; - import Media from "../../components/VideoPlayer/Media"; - import TReactPlayer from "../../components/VideoPlayer/TReactPlayer"; - import { VideoPlayer } from "../../components/VideoPlayer/VideoPlayer"; - import usePrevious from "../../hooks/usePrevious"; - import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate"; - import * as Config from "../../utils/Config"; - import { ACTIVE_POPUP, panel_names } from "../../utils/Config"; - import { $L, formatGMTString } from "../../utils/helperMethods"; - import { SpotlightIds } from "../../utils/SpotlightIds"; - import { removeDotAndColon } from "./PlayerItemCard/PlayerItemCard"; - import PlayerOverlayChat from "./PlayerOverlay/PlayerOverlayChat"; - import PlayerOverlayQRCode from "./PlayerOverlay/PlayerOverlayQRCode"; - import css from "./PlayerPanel.module.less"; - import PlayerTabButton from "./PlayerTabContents/TabButton/PlayerTabButton"; - import TabContainer from "./PlayerTabContents/TabContainer"; - - const Container = SpotlightContainerDecorator( - { enterTo: "default-element", preserveld: true }, - "div" - ); - - const findSelector = (selector, maxAttempts = 5, currentAttempts = 0) => { - try { - if (currentAttempts >= maxAttempts) { - throw new Error("selector not found"); - } - - const initialSelector = document.querySelector(selector); - - if (initialSelector) { - return initialSelector; - } else { - return findSelector(selector, maxAttempts, currentAttempts + 1); - } - } catch (error) { - // console.error(error.message); + useCallback, + useEffect, + useLayoutEffect, + useMemo, + useRef, +} from "react"; + +import classNames from "classnames"; +import { useDispatch } from "react-redux"; + +import { Job } from "@enact/core/util"; +import Spotlight from "@enact/spotlight"; +import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; +import { setContainerLastFocusedElement } from "@enact/spotlight/src/container"; + +import dummyVtt from "../../../assets/mock/video.vtt"; +import { + changeAppStatus, + changeLocalSettings, + requestLiveSubtitle, + sendBroadCast, + setHidePopup, +} from "../../actions/commonActions"; +import { + sendLogGNB, + sendLogLive, + sendLogTotalRecommend, + sendLogVOD, +} from "../../actions/logActions"; +import { + clearShopNowInfo, + getHomeFullVideoInfo, + getMainCategoryShowDetail, + getMainLiveShow, + getMainLiveShowNowProduct, +} from "../../actions/mainActions"; +import * as PanelActions from "../../actions/panelActions"; +import { updatePanel } from "../../actions/panelActions"; +import { + CLEAR_PLAYER_INFO, + getChatLog, + getSubTitle, + startVideoPlayer, +} from "../../actions/playActions"; +import { convertUtcToLocal } from "../../components/MediaPlayer/util"; +import TPanel from "../../components/TPanel/TPanel"; +import TPopUp from "../../components/TPopUp/TPopUp"; +import Media from "../../components/VideoPlayer/Media"; +import TReactPlayer from "../../components/VideoPlayer/TReactPlayer"; +import { VideoPlayer } from "../../components/VideoPlayer/VideoPlayer"; +import usePrevious from "../../hooks/usePrevious"; +import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate"; +import * as Config from "../../utils/Config"; +import { ACTIVE_POPUP, panel_names } from "../../utils/Config"; +import { $L, formatGMTString } from "../../utils/helperMethods"; +import { SpotlightIds } from "../../utils/SpotlightIds"; +import { removeDotAndColon } from "./PlayerItemCard/PlayerItemCard"; +import PlayerOverlayChat from "./PlayerOverlay/PlayerOverlayChat"; +import PlayerOverlayQRCode from "./PlayerOverlay/PlayerOverlayQRCode"; +import css from "./PlayerPanel.module.less"; +import PlayerTabButton from "./PlayerTabContents/TabButton/PlayerTabButton"; +import TabContainer from "./PlayerTabContents/TabContainer"; + +const Container = SpotlightContainerDecorator( + { enterTo: "default-element", preserveld: true }, + "div", +); + +const findSelector = (selector, maxAttempts = 5, currentAttempts = 0) => { + try { + if (currentAttempts >= maxAttempts) { + throw new Error("selector not found"); } - }; - - const getLogTpNo = (type, nowMenu) => { - if (type === "LIVE") { - switch (nowMenu) { - case Config.LOG_MENU.HOME_TOP: - return Config.LOG_TP_NO.LIVE.HOME; - // case Config.LOG_MENU.FEATURED_BRANDS_LIVE_CHANNELS: - // return Config.LOG_TP_NO.LIVE.FEATURED_BRANDS; - case Config.LOG_MENU.FULL_SHOP_NOW: - case Config.LOG_MENU.FULL_YOU_MAY_LIKE: - case Config.LOG_MENU.FULL_LIVE_CHANNELS: - return Config.LOG_TP_NO.LIVE.FULL; - default: - return Config.LOG_TP_NO.LIVE.FEATURED_BRANDS; - } - } else if (type === "VOD") { - switch (nowMenu) { - case Config.LOG_MENU.HOME_TOP: - return Config.LOG_TP_NO.VOD.HOME_VOD; // 153 - case Config.LOG_MENU.TRENDING_NOW_POPULAR_SHOWS: - return Config.LOG_TP_NO.VOD.POPULAR_SHOWS_AND_HOT_PICKS; // 151 - case Config.LOG_MENU.FULL_SHOP_NOW: - case Config.LOG_MENU.FULL_YOU_MAY_LIKE: - case Config.LOG_MENU.FULL_FEATURED_SHOWS: - return Config.LOG_TP_NO.VOD.FULL_VOD; // 150 - default: - return; - } - } else if (type === "MEDIA") { - switch (nowMenu) { - case Config.LOG_MENU.HOME_TOP: - return Config.LOG_TP_NO.VOD.HOME_VOD; // 153 - case Config.LOG_MENU.HOT_PICKS: - return Config.LOG_TP_NO.VOD.POPULAR_SHOWS_AND_HOT_PICKS; // 151 - case Config.LOG_MENU.DETAIL_PAGE_BILLING_PRODUCT_DETAIL: - case Config.LOG_MENU.DETAIL_PAGE_PRODUCT_DETAIL: - case Config.LOG_MENU.DETAIL_PAGE_GROUP_DETAIL: - case Config.LOG_MENU.DETAIL_PAGE_THEME_DETAIL: - case Config.LOG_MENU.DETAIL_PAGE_TRAVEL_THEME_DETAIL: - return Config.LOG_TP_NO.VOD.ITEM_DETAIL_MEDIA; // 156 - case Config.LOG_MENU.FULL: - return Config.LOG_TP_NO.VOD.FULL_MEDIA; // 155 - default: - return; - } + + const initialSelector = document.querySelector(selector); + + if (initialSelector) { + return initialSelector; + } else { + return findSelector(selector, maxAttempts, currentAttempts + 1); } - }; - - const YOUTUBECONFIG = { - playerVars: { - controls: 0, // 플레이어 컨트롤 표시 - autoplay: 1, - disablekb: 1, - enablejsapi: 1, - listType: "user_uploads", - fs: 0, - rel: 0, // 관련 동영상 표시 안 함 - showinfo: 0, - loop: 0, - iv_load_policy: 3, - modestbranding: 1, - wmode: "opaque", - cc_lang_pref: "en", - cc_load_policy: 0, - playsinline: 1, - }, - }; - - const INITIAL_TIMEOUT = 30000; - const REGULAR_TIMEOUT = 30000; - const TAB_CONTAINER_SPOTLIGHT_ID = "tab-container-spotlight-id"; - const TARGET_EVENTS = ["mousemove", "keydown", "click"]; - - // last time error - const VIDEO_END_ACTION_DELAY = 1500; - - const PlayerPanelNew = ({ + } catch (error) { + // console.error(error.message); + } +}; + +const getLogTpNo = (type, nowMenu) => { + if (type === "LIVE") { + switch (nowMenu) { + case Config.LOG_MENU.HOME_TOP: + return Config.LOG_TP_NO.LIVE.HOME; + // case Config.LOG_MENU.FEATURED_BRANDS_LIVE_CHANNELS: + // return Config.LOG_TP_NO.LIVE.FEATURED_BRANDS; + case Config.LOG_MENU.FULL_SHOP_NOW: + case Config.LOG_MENU.FULL_YOU_MAY_LIKE: + case Config.LOG_MENU.FULL_LIVE_CHANNELS: + return Config.LOG_TP_NO.LIVE.FULL; + default: + return Config.LOG_TP_NO.LIVE.FEATURED_BRANDS; + } + } else if (type === "VOD") { + switch (nowMenu) { + case Config.LOG_MENU.HOME_TOP: + return Config.LOG_TP_NO.VOD.HOME_VOD; // 153 + case Config.LOG_MENU.TRENDING_NOW_POPULAR_SHOWS: + return Config.LOG_TP_NO.VOD.POPULAR_SHOWS_AND_HOT_PICKS; // 151 + case Config.LOG_MENU.FULL_SHOP_NOW: + case Config.LOG_MENU.FULL_YOU_MAY_LIKE: + case Config.LOG_MENU.FULL_FEATURED_SHOWS: + return Config.LOG_TP_NO.VOD.FULL_VOD; // 150 + default: + return; + } + } else if (type === "MEDIA") { + switch (nowMenu) { + case Config.LOG_MENU.HOME_TOP: + return Config.LOG_TP_NO.VOD.HOME_VOD; // 153 + case Config.LOG_MENU.HOT_PICKS: + return Config.LOG_TP_NO.VOD.POPULAR_SHOWS_AND_HOT_PICKS; // 151 + case Config.LOG_MENU.DETAIL_PAGE_BILLING_PRODUCT_DETAIL: + case Config.LOG_MENU.DETAIL_PAGE_PRODUCT_DETAIL: + case Config.LOG_MENU.DETAIL_PAGE_GROUP_DETAIL: + case Config.LOG_MENU.DETAIL_PAGE_THEME_DETAIL: + case Config.LOG_MENU.DETAIL_PAGE_TRAVEL_THEME_DETAIL: + return Config.LOG_TP_NO.VOD.ITEM_DETAIL_MEDIA; // 156 + case Config.LOG_MENU.FULL: + return Config.LOG_TP_NO.VOD.FULL_MEDIA; // 155 + default: + return; + } + } +}; + +const YOUTUBECONFIG = { + playerVars: { + controls: 0, // 플레이어 컨트롤 표시 + autoplay: 1, + disablekb: 1, + enablejsapi: 1, + listType: "user_uploads", + fs: 0, + rel: 0, // 관련 동영상 표시 안 함 + showinfo: 0, + loop: 0, + iv_load_policy: 3, + modestbranding: 1, + wmode: "opaque", + cc_lang_pref: "en", + cc_load_policy: 0, + playsinline: 1, + }, +}; + +const INITIAL_TIMEOUT = 30000; +const REGULAR_TIMEOUT = 30000; +const TAB_CONTAINER_SPOTLIGHT_ID = "tab-container-spotlight-id"; +const TARGET_EVENTS = ["mousemove", "keydown", "click"]; + +// last time error +const VIDEO_END_ACTION_DELAY = 1500; + +const PlayerPanelNew = ({ + isTabActivated, + panelInfo, + isOnTop, + spotlightId, + ...props +}) => { + const dispatch = useDispatch(); + const { USE_STATE, USE_SELECTOR } = useWhyDidYouUpdate(spotlightId, { isTabActivated, panelInfo, isOnTop, - spotlightId, - ...props - }) => { - const dispatch = useDispatch(); - const { USE_STATE, USE_SELECTOR } = useWhyDidYouUpdate(spotlightId, { - isTabActivated, - panelInfo, - isOnTop, - ...props, - }); - - const videoPlayer = useRef(null); - const [playListInfo, setPlayListInfo] = USE_STATE("playListInfo", ""); - const [shopNowInfo, setShopNowInfo] = USE_STATE("shopNowInfo"); - const [backupInitialIndex, setBackupInitialIndex] = USE_STATE( - "backupInitialIndex", - 0 - ); - const [modalStyle, setModalStyle] = USE_STATE("modalStyle", {}); - const [modalScale, setModalScale] = USE_STATE("modalScale", 1); - const [mediaId, setMediaId] = USE_STATE("mediaId", null); - const [currentLiveTimeSeconds, setCurrentLiveTimeSeconds] = USE_STATE( - "currentLiveTimeSeconds", - 1 - ); - const [prevChannelIndex, setPrevChannelIndex] = USE_STATE( - "prevChannelIndex", - 0 - ); - const [sideContentsVisible, setSideContentsVisible] = USE_STATE( - "sideContentsVisible", - true - ); - const [currentTime, setCurrentTime] = USE_STATE("currentTime", 0); - const [isInitialFocusOccurred, setIsInitialFocusOccurred] = USE_STATE( - "isInitialFocusOccurred", - false - ); - const [selectedIndex, setSelectedIndex] = USE_STATE( - "selectedIndex", - panelInfo.shptmBanrTpNm === "LIVE" ? null : 0 - ); - const [isUpdate, setIsUpdate] = USE_STATE("isUpdate", false); - const [isSubtitleActive, setIsSubtitleActive] = USE_STATE( - "isSubtitleActive", - true - ); - const [logStatus, setLogStatus] = USE_STATE("logStatus", { - isModalLiveLogReady: false, - isFullLiveLogReady: false, - isDetailLiveLogReady: false, - isModalVodLogReady: false, - isFullVodLogReady: false, - isDetailVodLogReady: false, - isModalMediaLogReady: false, - isFullMediaLogReady: false, - isDetailMediaReady: false, - }); - const [isVODPaused, setIsVODPaused] = USE_STATE("isVODPaused", false); - - const panels = USE_SELECTOR("panels", (state) => state.panels.panels); - const chatData = USE_SELECTOR("chatData", (state) => state.play.chatData); - - const popupVisible = USE_SELECTOR( - "popupVisible", - (state) => state.common.popup.popupVisible - ); - const activePopup = USE_SELECTOR( - "activePopup", - (state) => state.common.popup.activePopup - ); - const showDetailInfo = USE_SELECTOR( - "showDetailInfo", - (state) => state.main.showDetailInfo - ); - const productImageLength = USE_SELECTOR( - "productImageLength", - (state) => state.product.productImageLength - ); - const themeProductInfos = USE_SELECTOR( - "themeProductInfos", - (state) => state.home.themeCurationDetailInfoData - ); - const hotelInfos = USE_SELECTOR( - "hotelInfos", - (state) => state.home.themeCurationHotelDetailData - ); - const captionEnable = USE_SELECTOR( - "captionEnable", - (state) => state.common.appStatus.captionEnable - ); - const fullVideolgCatCd = USE_SELECTOR( - "fullVideolgCatCd", - (state) => state.main.fullVideolgCatCd - ); - const featuredShowsInfos = USE_SELECTOR( - "featuredShowsInfos", - (state) => state.main.featuredShowsInfos - ); - const localRecentItems = USE_SELECTOR( - "localRecentItems", - (state) => state.localSettings?.recentItems - ); - const httpHeader = USE_SELECTOR( - "httpHeader", - (state) => state.common?.httpHeader - ); - const countryCode = USE_SELECTOR( - "countryCode", - (state) => state.common.httpHeader?.cntry_cd - ); - const liveChannelInfos = USE_SELECTOR( - "liveChannelInfos", - (state) => state.main.liveChannelInfos - ); - const showNowInfos = USE_SELECTOR( - "showNowInfos", - (state) => state.main.showNowInfo - ); - const liveShowInfos = USE_SELECTOR( - "liveShowInfos", - (state) => state.main.liveShowInfos - ); - const vodSubtitleData = USE_SELECTOR( - "vodSubtitleData", - (state) => state.play.subTitleBlobs - ); - const broadcast = USE_SELECTOR( - "broadcast", - (state) => state.common.broadcast - ); - - const lastPanelAction = USE_SELECTOR( - "lastPanelAction", - (state) => state.panels.lastPanelAction - ); - const nowMenu = USE_SELECTOR("nowMenu", (state) => state.common.menu.nowMenu); - const nowMenuRef = usePrevious(nowMenu); - const entryMenu = USE_SELECTOR( - "entryMenu", - (state) => state.common.menu.entryMenu - ); - const [videoLoaded, setVideoLoaded] = USE_STATE("videoLoaded", false); - const entryMenuRef = usePrevious(entryMenu); - const panelInfoRef = usePrevious(panelInfo); - - const initialFocusTimeoutJob = useRef(new Job((func) => func(), 100)); - const liveLogParamsRef = useRef(null); - const vodLogParamsRef = useRef(null); - const mediaLogParamsRef = useRef(null); - const prevNowMenuRef = useRef(null); - const watchInterval = useRef(null); - // useEffect(() => { - // console.log("###videoLoaded", videoLoaded); - // if (nowMenu) { - // } - // }, [videoLoaded]); - const currentLiveShowInfo = useMemo(() => { - if (liveShowInfos && liveShowInfos.length > 0) { - const panelInfoChanId = panelInfo?.chanId; - const isLive = panelInfo?.shptmBanrTpNm === "LIVE"; - - if (isLive) { - const liveShowInfo = liveShowInfos // - .find(({ chanId }) => panelInfoChanId === chanId); - - return liveShowInfo; - } - - return {}; + ...props, + }); + + const videoPlayer = useRef(null); + const [playListInfo, setPlayListInfo] = USE_STATE("playListInfo", ""); + const [shopNowInfo, setShopNowInfo] = USE_STATE("shopNowInfo"); + const [backupInitialIndex, setBackupInitialIndex] = USE_STATE( + "backupInitialIndex", + 0, + ); + const [modalStyle, setModalStyle] = USE_STATE("modalStyle", {}); + const [modalScale, setModalScale] = USE_STATE("modalScale", 1); + const [mediaId, setMediaId] = USE_STATE("mediaId", null); + const [currentLiveTimeSeconds, setCurrentLiveTimeSeconds] = USE_STATE( + "currentLiveTimeSeconds", + 1, + ); + const [prevChannelIndex, setPrevChannelIndex] = USE_STATE( + "prevChannelIndex", + 0, + ); + const [sideContentsVisible, setSideContentsVisible] = USE_STATE( + "sideContentsVisible", + true, + ); + const [currentTime, setCurrentTime] = USE_STATE("currentTime", 0); + const [isInitialFocusOccurred, setIsInitialFocusOccurred] = USE_STATE( + "isInitialFocusOccurred", + false, + ); + const [selectedIndex, setSelectedIndex] = USE_STATE( + "selectedIndex", + panelInfo.shptmBanrTpNm === "LIVE" ? null : 0, + ); + const [isUpdate, setIsUpdate] = USE_STATE("isUpdate", false); + const [isSubtitleActive, setIsSubtitleActive] = USE_STATE( + "isSubtitleActive", + true, + ); + const [logStatus, setLogStatus] = USE_STATE("logStatus", { + isModalLiveLogReady: false, + isFullLiveLogReady: false, + isDetailLiveLogReady: false, + isModalVodLogReady: false, + isFullVodLogReady: false, + isDetailVodLogReady: false, + isModalMediaLogReady: false, + isFullMediaLogReady: false, + isDetailMediaReady: false, + }); + const [isVODPaused, setIsVODPaused] = USE_STATE("isVODPaused", false); + + const playerControl = USE_SELECTOR( + "playerControl", + (state) => state.home.playerControl, + ); + const panels = USE_SELECTOR("panels", (state) => state.panels.panels); + const chatData = USE_SELECTOR("chatData", (state) => state.play.chatData); + + const popupVisible = USE_SELECTOR( + "popupVisible", + (state) => state.common.popup.popupVisible, + ); + const activePopup = USE_SELECTOR( + "activePopup", + (state) => state.common.popup.activePopup, + ); + const showDetailInfo = USE_SELECTOR( + "showDetailInfo", + (state) => state.main.showDetailInfo, + ); + const productImageLength = USE_SELECTOR( + "productImageLength", + (state) => state.product.productImageLength, + ); + const themeProductInfos = USE_SELECTOR( + "themeProductInfos", + (state) => state.home.themeCurationDetailInfoData, + ); + const hotelInfos = USE_SELECTOR( + "hotelInfos", + (state) => state.home.themeCurationHotelDetailData, + ); + const captionEnable = USE_SELECTOR( + "captionEnable", + (state) => state.common.appStatus.captionEnable, + ); + const fullVideolgCatCd = USE_SELECTOR( + "fullVideolgCatCd", + (state) => state.main.fullVideolgCatCd, + ); + const featuredShowsInfos = USE_SELECTOR( + "featuredShowsInfos", + (state) => state.main.featuredShowsInfos, + ); + const localRecentItems = USE_SELECTOR( + "localRecentItems", + (state) => state.localSettings?.recentItems, + ); + const httpHeader = USE_SELECTOR( + "httpHeader", + (state) => state.common?.httpHeader, + ); + const countryCode = USE_SELECTOR( + "countryCode", + (state) => state.common.httpHeader?.cntry_cd, + ); + const liveChannelInfos = USE_SELECTOR( + "liveChannelInfos", + (state) => state.main.liveChannelInfos, + ); + const showNowInfos = USE_SELECTOR( + "showNowInfos", + (state) => state.main.showNowInfo, + ); + const liveShowInfos = USE_SELECTOR( + "liveShowInfos", + (state) => state.main.liveShowInfos, + ); + const vodSubtitleData = USE_SELECTOR( + "vodSubtitleData", + (state) => state.play.subTitleBlobs, + ); + const broadcast = USE_SELECTOR( + "broadcast", + (state) => state.common.broadcast, + ); + + const lastPanelAction = USE_SELECTOR( + "lastPanelAction", + (state) => state.panels.lastPanelAction, + ); + const nowMenu = USE_SELECTOR("nowMenu", (state) => state.common.menu.nowMenu); + const nowMenuRef = usePrevious(nowMenu); + const entryMenu = USE_SELECTOR( + "entryMenu", + (state) => state.common.menu.entryMenu, + ); + const [videoLoaded, setVideoLoaded] = USE_STATE("videoLoaded", false); + const entryMenuRef = usePrevious(entryMenu); + const panelInfoRef = usePrevious(panelInfo); + + const initialFocusTimeoutJob = useRef(new Job((func) => func(), 100)); + const liveLogParamsRef = useRef(null); + const vodLogParamsRef = useRef(null); + const mediaLogParamsRef = useRef(null); + const prevNowMenuRef = useRef(null); + const watchInterval = useRef(null); + // useEffect(() => { + // console.log("###videoLoaded", videoLoaded); + // if (nowMenu) { + // } + // }, [videoLoaded]); + const currentLiveShowInfo = useMemo(() => { + if (liveShowInfos && liveShowInfos.length > 0) { + const panelInfoChanId = panelInfo?.chanId; + const isLive = panelInfo?.shptmBanrTpNm === "LIVE"; + + if (isLive) { + const liveShowInfo = liveShowInfos // + .find(({ chanId }) => panelInfoChanId === chanId); + + return liveShowInfo; } - + return {}; - }, [liveShowInfos, panelInfo?.chanId, panelInfo?.shptmBanrTpNm]); - - const currentVODShowInfo = useMemo(() => { - if (showDetailInfo && showDetailInfo.length > 0) { - const isVOD = panelInfo?.shptmBanrTpNm === "VOD"; - - if (isVOD) { - const vodShowInfo = showDetailInfo[0]; - - return vodShowInfo; - } - - return {}; + } + + return {}; + }, [liveShowInfos, panelInfo?.chanId, panelInfo?.shptmBanrTpNm]); + + const currentVODShowInfo = useMemo(() => { + if (showDetailInfo && showDetailInfo.length > 0) { + const isVOD = panelInfo?.shptmBanrTpNm === "VOD"; + + if (isVOD) { + const vodShowInfo = showDetailInfo[0]; + + return vodShowInfo; } - + return {}; - }, [panelInfo?.shptmBanrTpNm, showDetailInfo]); - - useEffect(() => { - if (!panelInfo?.modal && panelInfo?.shptmBanrTpNm === "MEDIA") { - dispatch(sendLogGNB(Config.LOG_MENU.FULL)); - prevNowMenuRef.current = nowMenuRef.current; - - return () => dispatch(sendLogGNB(prevNowMenuRef.current)); + } + + return {}; + }, [panelInfo?.shptmBanrTpNm, showDetailInfo]); + + useEffect(() => { + if (!panelInfo?.modal && panelInfo?.shptmBanrTpNm === "MEDIA") { + dispatch(sendLogGNB(Config.LOG_MENU.FULL)); + prevNowMenuRef.current = nowMenuRef.current; + + return () => dispatch(sendLogGNB(prevNowMenuRef.current)); + } + }, [panelInfo?.modal, panelInfo?.shptmBanrTpNm]); + + // creating live log params + useEffect(() => { + if (currentLiveShowInfo && Object.keys(currentLiveShowInfo).length > 0) { + if (currentLiveShowInfo.showId !== panelInfo?.showId) { + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + chanId: currentLiveShowInfo.chanId, + modalContainerId: panelInfo?.modalContainerId, + patnrId: currentLiveShowInfo.patnrId, + showId: currentLiveShowInfo.showId, + showUrl: currentLiveShowInfo.showUrl, + }, + }), + ); + + return; } - }, [panelInfo?.modal, panelInfo?.shptmBanrTpNm]); - - // creating live log params - useEffect(() => { - if (currentLiveShowInfo && Object.keys(currentLiveShowInfo).length > 0) { - if (currentLiveShowInfo.showId !== panelInfo?.showId) { - dispatch( - updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - chanId: currentLiveShowInfo.chanId, - modalContainerId: panelInfo?.modalContainerId, - patnrId: currentLiveShowInfo.patnrId, - showId: currentLiveShowInfo.showId, - showUrl: currentLiveShowInfo.showUrl, - }, - }) - ); - - return; - } - - let logTemplateNo; - - if (isOnTop && panelInfo?.modal) { - logTemplateNo = getLogTpNo("LIVE", nowMenu); - setLogStatus((status) => ({ ...status, isModalLiveLogReady: true })); - } - // - else if (isOnTop && !panelInfo?.modal) { - logTemplateNo = Config.LOG_TP_NO.LIVE.FULL; - setLogStatus((status) => ({ ...status, isFullLiveLogReady: true })); - } - // - else if (!isOnTop && !panelInfo?.modal) { - logTemplateNo = Config.LOG_TP_NO.LIVE.ITEM_DETAIL; - setLogStatus((status) => ({ ...status, isDetailLiveLogReady: true })); - } - - liveLogParamsRef.current = { - entryMenu: entryMenuRef.current, - lgCatCd: currentLiveShowInfo.catCd ?? "", - lgCatNm: currentLiveShowInfo.catNm ?? "", - linkTpCd: panelInfo?.linkTpCd ?? "", - logTpNo: logTemplateNo, - nowMenu: nowMenuRef.current, - patncNm: currentLiveShowInfo.patncNm, - patnrId: currentLiveShowInfo.patnrId, - showId: currentLiveShowInfo.showId, - showNm: currentLiveShowInfo.showNm, - vdoTpNm: currentLiveShowInfo.vtctpYn - ? currentLiveShowInfo.vtctpYn === "Y" - ? "Vertical" - : "Horizontal" - : "", - }; + + let logTemplateNo; + + if (isOnTop && panelInfo?.modal) { + logTemplateNo = getLogTpNo("LIVE", nowMenu); + setLogStatus((status) => ({ ...status, isModalLiveLogReady: true })); } - }, [ - currentLiveShowInfo, - isOnTop, - nowMenu, - panelInfo?.linkTpCd, - panelInfo?.modal, - panelInfo?.modalContainerId, - panelInfo?.showId, - setLogStatus, - ]); - - // send live log - useEffect(() => { - if (broadcast && Object.keys(broadcast).length === 0) { - // case: live, modal - if ( - logStatus.isModalLiveLogReady && - isOnTop && - panelInfo?.modal && - liveLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...liveLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isModalLiveLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - - // case: live, full - if ( - logStatus.isFullLiveLogReady && - isOnTop && - !panelInfo?.modal && - liveLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...liveLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isFullLiveLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - - // case: live, item detail - if ( - logStatus.isDetailLiveLogReady && - !isOnTop && - !panelInfo?.modal && - liveLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...liveLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isDetailLiveLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } + // + else if (isOnTop && !panelInfo?.modal) { + logTemplateNo = Config.LOG_TP_NO.LIVE.FULL; + setLogStatus((status) => ({ ...status, isFullLiveLogReady: true })); } - }, [ - broadcast, - isOnTop, - logStatus.isDetailLiveLogReady, - logStatus.isFullLiveLogReady, - logStatus.isModalLiveLogReady, - panelInfo?.modal, - panelInfo?.showId, - setLogStatus, - ]); - - // creating VOD log params - useEffect(() => { + // + else if (!isOnTop && !panelInfo?.modal) { + logTemplateNo = Config.LOG_TP_NO.LIVE.ITEM_DETAIL; + setLogStatus((status) => ({ ...status, isDetailLiveLogReady: true })); + } + + liveLogParamsRef.current = { + entryMenu: entryMenuRef.current, + lgCatCd: currentLiveShowInfo.catCd ?? "", + lgCatNm: currentLiveShowInfo.catNm ?? "", + linkTpCd: panelInfo?.linkTpCd ?? "", + logTpNo: logTemplateNo, + nowMenu: nowMenuRef.current, + patncNm: currentLiveShowInfo.patncNm, + patnrId: currentLiveShowInfo.patnrId, + showId: currentLiveShowInfo.showId, + showNm: currentLiveShowInfo.showNm, + vdoTpNm: currentLiveShowInfo.vtctpYn + ? currentLiveShowInfo.vtctpYn === "Y" + ? "Vertical" + : "Horizontal" + : "", + }; + } + }, [ + currentLiveShowInfo, + isOnTop, + nowMenu, + panelInfo?.linkTpCd, + panelInfo?.modal, + panelInfo?.modalContainerId, + panelInfo?.showId, + setLogStatus, + ]); + + // send live log + useEffect(() => { + if (broadcast && Object.keys(broadcast).length === 0) { + // case: live, modal if ( - currentVODShowInfo && - Object.keys(currentVODShowInfo).length > 0 && - !isVODPaused + logStatus.isModalLiveLogReady && + isOnTop && + panelInfo?.modal && + liveLogParamsRef.current?.showId === panelInfo?.showId ) { - let logTemplateNo; - - if (isOnTop && panelInfo?.modal) { - logTemplateNo = getLogTpNo("VOD", nowMenu); - setLogStatus((status) => ({ ...status, isModalVodLogReady: true })); - } - // - else if (isOnTop && !panelInfo?.modal) { - logTemplateNo = Config.LOG_TP_NO.VOD.FULL_VOD; - setLogStatus((status) => ({ ...status, isFullVodLogReady: true })); - } - // - else if (!isOnTop && !panelInfo?.modal) { - logTemplateNo = Config.LOG_TP_NO.VOD.ITEM_DETAIL_VOD; - setLogStatus((status) => ({ ...status, isDetailVodLogReady: true })); - } - - vodLogParamsRef.current = { - entryMenu: entryMenuRef.current, - lgCatCd: currentVODShowInfo?.showCatCd ?? "", - lgCatNm: currentVODShowInfo?.showCatNm ?? "", - logTpNo: logTemplateNo, - linkTpCd: panelInfo?.linkTpCd ?? "", - nowMenu: nowMenuRef.current, - patncNm: currentVODShowInfo?.patncNm, - patnrId: currentVODShowInfo?.patnrId, - showId: currentVODShowInfo?.showId, - showNm: currentVODShowInfo?.showNm, - vdoTpNm: currentVODShowInfo?.vtctpYn - ? currentVODShowInfo.vtctpYn === "Y" - ? "Vertical" - : "Horizontal" - : "", - }; - } - }, [ - currentVODShowInfo, - isOnTop, - isVODPaused, - nowMenu, - panelInfo?.linkTpCd, - panelInfo?.modal, - ]); - - // send VOD log - useEffect(() => { - if (broadcast && Object.keys(broadcast).length === 0 && !isVODPaused) { - // case: VOD, modal - if ( - logStatus.isModalVodLogReady && - isOnTop && - panelInfo?.modal && - vodLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...vodLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isModalVodLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - - // case: VOD, full - if ( - logStatus.isFullVodLogReady && - isOnTop && - !panelInfo?.modal && - vodLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...vodLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isFullVodLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - - // case: VOD, item detail - if ( - logStatus.isDetailVodLogReady && - !isOnTop && - !panelInfo?.modal && - vodLogParamsRef.current?.showId === panelInfo?.showId - ) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...vodLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isDetailVodLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - } - }, [ - broadcast, - isOnTop, - isVODPaused, - logStatus.isDetailVodLogReady, - logStatus.isFullVodLogReady, - logStatus.isModalVodLogReady, - panelInfo?.modal, - panelInfo?.showId, - setLogStatus, - ]); - - // creating media log params - useEffect(() => { - if (panelInfo?.shptmBanrTpNm === "MEDIA" && isOnTop && !isVODPaused) { - let logTemplateNo; - - if (panelInfo?.modal) { - logTemplateNo = getLogTpNo("MEDIA", nowMenu); - setLogStatus((status) => ({ ...status, isModalMediaLogReady: true })); - } - // - else if (!panelInfo?.modal) { - logTemplateNo = Config.LOG_TP_NO.VOD.FULL_MEDIA; - setLogStatus((status) => ({ ...status, isFullMediaLogReady: true })); - } - - mediaLogParamsRef.current = { - entryMenu: entryMenuRef.current, - lgCatCd: panelInfo?.lgCatCd ?? "", - lgCatNm: panelInfo?.lgCatNm ?? "", - logTpNo: logTemplateNo, - linkTpCd: panelInfo?.linkTpCd ?? "", - nowMenu: nowMenuRef.current, - patncNm: panelInfo?.patncNm ?? "", - patnrId: panelInfo?.patnrId ?? "", - showId: panelInfo?.prdtId ?? panelInfo?.showId, - showNm: panelInfo?.prdtNm ?? panelInfo?.showNm, - vdoTpNm: "Horizontal", - }; - } - }, [ - isOnTop, - isVODPaused, - nowMenu, - panelInfo?.lgCatCd, - panelInfo?.lgCatNm, - panelInfo?.linkTpCd, - panelInfo?.modal, - panelInfo?.patncNm, - panelInfo?.patnrId, - panelInfo?.prdtId, - panelInfo?.prdtNm, - panelInfo?.showId, - panelInfo?.showNm, - panelInfo?.shptmBanrTpNm, - setLogStatus, - ]); - - // send log media - useEffect(() => { - if (broadcast && Object.keys(broadcast).length === 0 && !isVODPaused) { - // case: media, modal - if (logStatus.isModalMediaLogReady && panelInfo?.modal) { - let watchStrtDt = formatGMTString(new Date()); - - watchInterval.current = setInterval(() => { - let watchEndDt = formatGMTString(new Date()); - let watchRecord = { - ...mediaLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isModalMediaLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - sendLogVOD({ ...mediaLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) - ); - }; - } - } - - // case: media, full - if (logStatus.isFullMediaLogReady && !panelInfo?.modal) { let watchStrtDt = formatGMTString(new Date()); - + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...liveLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isModalLiveLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + + // case: live, full + if ( + logStatus.isFullLiveLogReady && + isOnTop && + !panelInfo?.modal && + liveLogParamsRef.current?.showId === panelInfo?.showId + ) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...liveLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isFullLiveLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + + // case: live, item detail + if ( + logStatus.isDetailLiveLogReady && + !isOnTop && + !panelInfo?.modal && + liveLogParamsRef.current?.showId === panelInfo?.showId + ) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...liveLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isDetailLiveLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + } + }, [ + broadcast, + isOnTop, + logStatus.isDetailLiveLogReady, + logStatus.isFullLiveLogReady, + logStatus.isModalLiveLogReady, + panelInfo?.modal, + panelInfo?.showId, + setLogStatus, + ]); + + // creating VOD log params + useEffect(() => { + if ( + currentVODShowInfo && + Object.keys(currentVODShowInfo).length > 0 && + !isVODPaused + ) { + let logTemplateNo; + + if (isOnTop && panelInfo?.modal) { + logTemplateNo = getLogTpNo("VOD", nowMenu); + setLogStatus((status) => ({ ...status, isModalVodLogReady: true })); + } + // + else if (isOnTop && !panelInfo?.modal) { + logTemplateNo = Config.LOG_TP_NO.VOD.FULL_VOD; + setLogStatus((status) => ({ ...status, isFullVodLogReady: true })); + } + // + else if (!isOnTop && !panelInfo?.modal) { + logTemplateNo = Config.LOG_TP_NO.VOD.ITEM_DETAIL_VOD; + setLogStatus((status) => ({ ...status, isDetailVodLogReady: true })); + } + + vodLogParamsRef.current = { + entryMenu: entryMenuRef.current, + lgCatCd: currentVODShowInfo?.showCatCd ?? "", + lgCatNm: currentVODShowInfo?.showCatNm ?? "", + logTpNo: logTemplateNo, + linkTpCd: panelInfo?.linkTpCd ?? "", + nowMenu: nowMenuRef.current, + patncNm: currentVODShowInfo?.patncNm, + patnrId: currentVODShowInfo?.patnrId, + showId: currentVODShowInfo?.showId, + showNm: currentVODShowInfo?.showNm, + vdoTpNm: currentVODShowInfo?.vtctpYn + ? currentVODShowInfo.vtctpYn === "Y" + ? "Vertical" + : "Horizontal" + : "", + }; + } + }, [ + currentVODShowInfo, + isOnTop, + isVODPaused, + nowMenu, + panelInfo?.linkTpCd, + panelInfo?.modal, + ]); + + // send VOD log + useEffect(() => { + if (broadcast && Object.keys(broadcast).length === 0 && !isVODPaused) { + // case: VOD, modal + if ( + logStatus.isModalVodLogReady && + isOnTop && + panelInfo?.modal && + vodLogParamsRef.current?.showId === panelInfo?.showId + ) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...vodLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isModalVodLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + + // case: VOD, full + if ( + logStatus.isFullVodLogReady && + isOnTop && + !panelInfo?.modal && + vodLogParamsRef.current?.showId === panelInfo?.showId + ) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...vodLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isFullVodLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + + // case: VOD, item detail + if ( + logStatus.isDetailVodLogReady && + !isOnTop && + !panelInfo?.modal && + vodLogParamsRef.current?.showId === panelInfo?.showId + ) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...vodLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isDetailVodLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + sendLogVOD({ ...vodLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), + ); + }; + } + } + }, [ + broadcast, + isOnTop, + isVODPaused, + logStatus.isDetailVodLogReady, + logStatus.isFullVodLogReady, + logStatus.isModalVodLogReady, + panelInfo?.modal, + panelInfo?.showId, + setLogStatus, + ]); + + // creating media log params + useEffect(() => { + if (panelInfo?.shptmBanrTpNm === "MEDIA" && isOnTop && !isVODPaused) { + let logTemplateNo; + + if (panelInfo?.modal) { + logTemplateNo = getLogTpNo("MEDIA", nowMenu); + setLogStatus((status) => ({ ...status, isModalMediaLogReady: true })); + } + // + else if (!panelInfo?.modal) { + logTemplateNo = Config.LOG_TP_NO.VOD.FULL_MEDIA; + setLogStatus((status) => ({ ...status, isFullMediaLogReady: true })); + } + + mediaLogParamsRef.current = { + entryMenu: entryMenuRef.current, + lgCatCd: panelInfo?.lgCatCd ?? "", + lgCatNm: panelInfo?.lgCatNm ?? "", + logTpNo: logTemplateNo, + linkTpCd: panelInfo?.linkTpCd ?? "", + nowMenu: nowMenuRef.current, + patncNm: panelInfo?.patncNm ?? "", + patnrId: panelInfo?.patnrId ?? "", + showId: panelInfo?.prdtId ?? panelInfo?.showId, + showNm: panelInfo?.prdtNm ?? panelInfo?.showNm, + vdoTpNm: "Horizontal", + }; + } + }, [ + isOnTop, + isVODPaused, + nowMenu, + panelInfo?.lgCatCd, + panelInfo?.lgCatNm, + panelInfo?.linkTpCd, + panelInfo?.modal, + panelInfo?.patncNm, + panelInfo?.patnrId, + panelInfo?.prdtId, + panelInfo?.prdtNm, + panelInfo?.showId, + panelInfo?.showNm, + panelInfo?.shptmBanrTpNm, + setLogStatus, + ]); + + // send log media + useEffect(() => { + if (broadcast && Object.keys(broadcast).length === 0 && !isVODPaused) { + // case: media, modal + if (logStatus.isModalMediaLogReady && panelInfo?.modal) { + let watchStrtDt = formatGMTString(new Date()); + watchInterval.current = setInterval(() => { let watchEndDt = formatGMTString(new Date()); let watchRecord = { @@ -800,1482 +775,1539 @@ import React, { }; dispatch(changeLocalSettings({ watchRecord })); }, 10000); - + return () => { setLogStatus((status) => ({ ...status, - isFullMediaLogReady: false, + isModalMediaLogReady: false, })); clearInterval(watchInterval.current); dispatch( sendLogVOD({ ...mediaLogParamsRef.current, watchStrtDt }, () => - dispatch(changeLocalSettings({ watchRecord: {} })) - ) + dispatch(changeLocalSettings({ watchRecord: {} })), + ), ); }; } - }, [ - broadcast, - isVODPaused, - logStatus.isFullMediaLogReady, - logStatus.isModalMediaLogReady, - panelInfo?.modal, - setLogStatus, - ]); - - const videoVerticalVisible = useMemo(() => { - if (playListInfo && playListInfo[selectedIndex]?.vtctpYn === "Y") { - return true; - } - return false; - }, [playListInfo, selectedIndex]); - - const handleItemFocus = useCallback( - (menu) => { - dispatch(sendLogGNB(menu)); - - if (!videoVerticalVisible) { - resetTimer(REGULAR_TIMEOUT); - } - }, - [resetTimer, videoVerticalVisible] - ); - - const onClickBack = useCallback( - (ev, isEnd) => { - //modal로부터 Full 전환된 경우 다시 preview 모드로 돌아감. - - if ( - sideContentsVisible && - !videoVerticalVisible && - panelInfo.shptmBanrTpNm !== "MEDIA" - ) { - setSideContentsVisible(false); - ev?.stopPropagation(); - // ev?.preventDefault(); - return; - } - - if (panelInfo.modalContainerId && !panelInfo.modal) { - dispatch( - startVideoPlayer({ - ...panelInfo, - modal: true, - modalClassName: "", - }) - ); - videoPlayer.current?.hideControls(); - setSelectedIndex(backupInitialIndex); - if (panelInfo.shptmBanrTpNm === "MEDIA") { - dispatch( - updatePanel({ - name: panel_names.DETAIL_PANEL, - panelInfo: { - launchedFromPlayer: false, - }, - }) - ); - } - ev?.stopPropagation(); - // ev?.preventDefault(); - return; - } - - if (!panelInfo.modal) { - dispatch(PanelActions.popPanel()); - dispatch(changeAppStatus({ cursorVisible: false })); - - //딮링크로 플레이어 진입 후 이전버튼 클릭시 - if (panels.length === 1) { - setTimeout(() => { - Spotlight.focus(SpotlightIds.HOME_TBODY); - }); - } - ev?.stopPropagation(); - // ev?.preventDefault(); - return; - } - }, - [ - dispatch, - panelInfo, - videoPlayer, - sideContentsVisible, - videoVerticalVisible, - backupInitialIndex, - ] - ); - - useEffect(() => { - //todo if(modal) + } + + // case: media, full + if (logStatus.isFullMediaLogReady && !panelInfo?.modal) { + let watchStrtDt = formatGMTString(new Date()); + + watchInterval.current = setInterval(() => { + let watchEndDt = formatGMTString(new Date()); + let watchRecord = { + ...mediaLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + return () => { - // 패널이 2개 존재할때만 popPanel 진행 - if (panelInfo.modal && !isOnTop) { - dispatch(PanelActions.popPanel()); - } else { - Spotlight.focus("tbody"); - } - }; - }, [panelInfo?.modal, isOnTop]); - - useEffect(() => { - if (showNowInfos && panelInfo.shptmBanrTpNm === "LIVE") { - const period = - showNowInfos.period !== undefined ? showNowInfos.period : 30; - const periodInMilliseconds = period * 1000; - - const timer = setTimeout(() => { - dispatch( - getMainLiveShowNowProduct({ - patnrId: panelInfo.patnrId - ? panelInfo.patnrId - : playListInfo[selectedIndex].patnrId, - showId: panelInfo.showId - ? panelInfo.showId - : playListInfo[selectedIndex].showId, - lstChgDt: showNowInfos.lstChgDt, - }) - ); - }, periodInMilliseconds); - - return () => { - clearTimeout(timer); - }; - } - }, [showNowInfos, panelInfo]); - - const videoItemFocused = useCallback(() => { - // 아이템클릭 진입시 포커스 - let hasProperSpot = false; - let targetId; - if (!isInitialFocusOccurred) { - targetId = panelInfo.targetId; - - initialFocusTimeoutJob.current.start(() => { - const initialFocusTarget = findSelector( - `[data-spotlight-id="${targetId}"]` - ); - - if (initialFocusTarget) { - hasProperSpot = true; - Spotlight.focus(initialFocusTarget); - setIsInitialFocusOccurred(true); - - return; - } - }); - } - }, [ - isInitialFocusOccurred, - panelInfo.targetId, - panelInfo.modal, - videoVerticalVisible, - ]); - - const videoInitialFocused = useCallback(() => { - if (panelInfo.isUpdatedByClick || !isOnTop) { - return; - } - setContainerLastFocusedElement(null, ["playVideoShopNowBox"]); - - // 세로형모드 포커스 - if (videoVerticalVisible) { - Spotlight.focus("tab-0"); - return; - } - - // 화살표버튼 포커스 - const current = Spotlight.getCurrent(); - let hasProperSpot = false; - if (current) { - const spotId = current.getAttribute("data-spotlight-id"); - if (spotId && spotId.indexOf("tabChannel-video") >= 0) { - hasProperSpot = true; - } - } - - if (!panelInfo.modal && !videoVerticalVisible && !hasProperSpot) { - Spotlight.focus(SpotlightIds.PLAYER_TAB_BUTTON); - return; - } - //비디오 진입시 포커스 - if (panelInfo.isIndicatorByClick && shopNowInfo?.length > 0) { - Spotlight.focus("playVideoShopNowBox"); - return; - } - }, [ - shopNowInfo, - videoVerticalVisible, - isOnTop, - panelInfo.modal, - panelInfo.isUpdatedByClick, - panelInfo.isIndicatorByClick, - - panelInfo.shptmBanrTpNm, - ]); - - const cannotPlay = useMemo(() => { - const topPanel = panels[panels.length - 1]; - return !isOnTop && topPanel?.name === panel_names.PLAYER_PANEL; - }, [panels, isOnTop]); - - const getPlayer = useCallback((ref) => { - videoPlayer.current = ref; - }, []); - - /** for VOD */ - const addPanelInfoToPlayList = useCallback( - (featuredShowsInfos) => { - if (Array.isArray(featuredShowsInfos)) { - const showId = showDetailInfo[0]?.showId; - - const index = featuredShowsInfos.findIndex( - (show) => show.showId === showId - ); - - let newArray = []; - if (index > -1) { - // 인덱스를 찾은 경우 그대로 - newArray = [...featuredShowsInfos]; - setBackupInitialIndex(index); - setSelectedIndex(index); - } else { - // 인덱스를 찾지 못한 경우 showDetailInfo 를 제일 앞에 배치 - newArray = [{ ...showDetailInfo[0] }, ...featuredShowsInfos]; - setBackupInitialIndex(0); - setSelectedIndex(0); - } - setPlayListInfo(newArray); - } - }, - - [showDetailInfo] - ); - - useEffect(() => { - if (panelInfo.shptmBanrTpNm === "LIVE") { - if (panelInfo.patnrId && panelInfo.showId) { - dispatch( - getMainCategoryShowDetail({ - patnrId: panelInfo.patnrId, - showId: panelInfo.showId, - curationId: panelInfo.curationId, - }) - ); - } - dispatch(getMainLiveShow({ vodIncFlag: "Y" })); - } - }, [ - dispatch, - panelInfo?.curationId, - panelInfo?.lgCatCd, - panelInfo?.patnrId, - panelInfo?.showId, - panelInfo?.shptmBanrTpNm, - ]); - - useEffect(() => { - if ( - panelInfo.shptmBanrTpNm === "VOD" && - showDetailInfo && - showDetailInfo.length > 0 && - showDetailInfo[0]?.showCatCd && - fullVideolgCatCd !== showDetailInfo[0]?.showCatCd //기존에 호출했으면 안한다. - ) { + setLogStatus((status) => ({ + ...status, + isFullMediaLogReady: false, + })); + clearInterval(watchInterval.current); dispatch( - getHomeFullVideoInfo({ - lgCatCd: showDetailInfo[0].showCatCd, - }) + sendLogVOD({ ...mediaLogParamsRef.current, watchStrtDt }, () => + dispatch(changeLocalSettings({ watchRecord: {} })), + ), ); + }; + } + }, [ + broadcast, + isVODPaused, + logStatus.isFullMediaLogReady, + logStatus.isModalMediaLogReady, + panelInfo?.modal, + setLogStatus, + ]); + + const videoVerticalVisible = useMemo(() => { + if (playListInfo && playListInfo[selectedIndex]?.vtctpYn === "Y") { + return true; + } + return false; + }, [playListInfo, selectedIndex]); + + const handleItemFocus = useCallback( + (menu) => { + dispatch(sendLogGNB(menu)); + + if (!videoVerticalVisible) { + resetTimer(REGULAR_TIMEOUT); } + }, + [resetTimer, videoVerticalVisible], + ); + + const onClickBack = useCallback( + (ev, isEnd) => { + //modal로부터 Full 전환된 경우 다시 preview 모드로 돌아감. + if ( - panelInfo.shptmBanrTpNm === "VOD" && - showDetailInfo && - showDetailInfo[0] && - showDetailInfo[0].showId && - showDetailInfo[0].patnrId + sideContentsVisible && + !videoVerticalVisible && + panelInfo.shptmBanrTpNm !== "MEDIA" ) { - if (!featuredShowsInfos || Object.keys(featuredShowsInfos).length === 0) { - setPlayListInfo(showDetailInfo); - } - setShopNowInfo(showDetailInfo[0].productInfos); - saveToLocalSettings(showDetailInfo[0].showId, showDetailInfo[0].patnrId); + setSideContentsVisible(false); + ev?.stopPropagation(); + // ev?.preventDefault(); + return; } - }, [showDetailInfo]); - - //LIVE - useEffect(() => { - if ( - playListInfo && - playListInfo.length > 0 && - panelInfo.shptmBanrTpNm === "LIVE" - ) { - if (playListInfo[selectedIndex]?.patnrId) { - dispatch( - getMainLiveShowNowProduct({ - patnrId: playListInfo[selectedIndex]?.patnrId, - showId: playListInfo[selectedIndex]?.showId, - }) - ); - } - - if (playListInfo[selectedIndex]?.catCd) { - dispatch( - getHomeFullVideoInfo({ - lgCatCd: playListInfo[selectedIndex]?.catCd, - }) - ); - } - } - }, [selectedIndex]); - - useEffect(() => { - if (showDetailInfo && showDetailInfo.length > 0) { - dispatch(CLEAR_PLAYER_INFO()); - - if ( - showDetailInfo[0]?.liveFlag === "N" && - showDetailInfo[0]?.chatLogFlag === "Y" && - panelInfo.shptmBanrTpNm === "VOD" - ) { - dispatch( - getChatLog({ patnrId: panelInfo.patnrId, showId: panelInfo.showId }) - ); - } - } - }, [showDetailInfo]); - - // videoClick focused - useEffect(() => { - if (playListInfo && playListInfo.length > 0) { - if (panelInfo.targetId) { - videoItemFocused(); - } else { - videoInitialFocused(); - } - } - }, [playListInfo]); - - //10초 후 닫힐때 TabButton 포커스 - useEffect(() => { - if (playListInfo && playListInfo.length > 0) { - videoInitialFocused(); - } - }, [sideContentsVisible, panelInfo.modal]); - - // liveChannel initial selectedIndex - useEffect(() => { - if (panelInfo?.shptmBanrTpNm === "LIVE" && playListInfo?.length > 0) { - const index = playListInfo.findIndex( - (item) => item.chanId === panelInfo.chanId + + if (panelInfo.modalContainerId && !panelInfo.modal) { + dispatch( + startVideoPlayer({ + ...panelInfo, + modal: true, + modalClassName: "", + }), ); - if (index !== -1 && !isUpdate) { + videoPlayer.current?.hideControls(); + setSelectedIndex(backupInitialIndex); + if (panelInfo.shptmBanrTpNm === "MEDIA") { + dispatch( + updatePanel({ + name: panel_names.DETAIL_PANEL, + panelInfo: { + launchedFromPlayer: false, + }, + }), + ); + } + ev?.stopPropagation(); + // ev?.preventDefault(); + return; + } + + if (!panelInfo.modal) { + dispatch(PanelActions.popPanel()); + dispatch(changeAppStatus({ cursorVisible: false })); + + //딮링크로 플레이어 진입 후 이전버튼 클릭시 + if (panels.length === 1) { + setTimeout(() => { + Spotlight.focus(SpotlightIds.HOME_TBODY); + }); + } + ev?.stopPropagation(); + // ev?.preventDefault(); + return; + } + }, + [ + dispatch, + panelInfo, + videoPlayer, + sideContentsVisible, + videoVerticalVisible, + backupInitialIndex, + ], + ); + + useEffect(() => { + //todo if(modal) + return () => { + // 패널이 2개 존재할때만 popPanel 진행 + if (panelInfo.modal && !isOnTop) { + dispatch(PanelActions.popPanel()); + } else { + Spotlight.focus("tbody"); + } + }; + }, [panelInfo?.modal, isOnTop]); + + useEffect(() => { + if (showNowInfos && panelInfo.shptmBanrTpNm === "LIVE") { + const period = + showNowInfos.period !== undefined ? showNowInfos.period : 30; + const periodInMilliseconds = period * 1000; + + const timer = setTimeout(() => { + dispatch( + getMainLiveShowNowProduct({ + patnrId: panelInfo.patnrId + ? panelInfo.patnrId + : playListInfo[selectedIndex].patnrId, + showId: panelInfo.showId + ? panelInfo.showId + : playListInfo[selectedIndex].showId, + lstChgDt: showNowInfos.lstChgDt, + }), + ); + }, periodInMilliseconds); + + return () => { + clearTimeout(timer); + }; + } + }, [showNowInfos, panelInfo]); + + const videoItemFocused = useCallback(() => { + // 아이템클릭 진입시 포커스 + let hasProperSpot = false; + let targetId; + if (!isInitialFocusOccurred) { + targetId = panelInfo.targetId; + + initialFocusTimeoutJob.current.start(() => { + const initialFocusTarget = findSelector( + `[data-spotlight-id="${targetId}"]`, + ); + + if (initialFocusTarget) { + hasProperSpot = true; + Spotlight.focus(initialFocusTarget); + setIsInitialFocusOccurred(true); + + return; + } + }); + } + }, [ + isInitialFocusOccurred, + panelInfo.targetId, + panelInfo.modal, + videoVerticalVisible, + ]); + + const videoInitialFocused = useCallback(() => { + if (panelInfo.isUpdatedByClick || !isOnTop) { + return; + } + setContainerLastFocusedElement(null, ["playVideoShopNowBox"]); + + // 세로형모드 포커스 + if (videoVerticalVisible) { + Spotlight.focus("tab-0"); + return; + } + + // 화살표버튼 포커스 + const current = Spotlight.getCurrent(); + let hasProperSpot = false; + if (current) { + const spotId = current.getAttribute("data-spotlight-id"); + if (spotId && spotId.indexOf("tabChannel-video") >= 0) { + hasProperSpot = true; + } + } + + if (!panelInfo.modal && !videoVerticalVisible && !hasProperSpot) { + Spotlight.focus(SpotlightIds.PLAYER_TAB_BUTTON); + return; + } + //비디오 진입시 포커스 + if (panelInfo.isIndicatorByClick && shopNowInfo?.length > 0) { + Spotlight.focus("playVideoShopNowBox"); + return; + } + }, [ + shopNowInfo, + videoVerticalVisible, + isOnTop, + panelInfo.modal, + panelInfo.isUpdatedByClick, + panelInfo.isIndicatorByClick, + + panelInfo.shptmBanrTpNm, + ]); + + const cannotPlay = useMemo(() => { + const topPanel = panels[panels.length - 1]; + return !isOnTop && topPanel?.name === panel_names.PLAYER_PANEL; + }, [panels, isOnTop]); + + const getPlayer = useCallback((ref) => { + videoPlayer.current = ref; + }, []); + + /** for VOD */ + const addPanelInfoToPlayList = useCallback( + (featuredShowsInfos) => { + if (Array.isArray(featuredShowsInfos)) { + const showId = showDetailInfo[0]?.showId; + + const index = featuredShowsInfos.findIndex( + (show) => show.showId === showId, + ); + + let newArray = []; + if (index > -1) { + // 인덱스를 찾은 경우 그대로 + newArray = [...featuredShowsInfos]; setBackupInitialIndex(index); setSelectedIndex(index); - setIsUpdate(true); + } else { + // 인덱스를 찾지 못한 경우 showDetailInfo 를 제일 앞에 배치 + newArray = [{ ...showDetailInfo[0] }, ...featuredShowsInfos]; + setBackupInitialIndex(0); + setSelectedIndex(0); } + setPlayListInfo(newArray); } - }, [panelInfo?.shptmBanrTpNm, playListInfo]); - - // live subtitle Luna API - useEffect(() => { - if (currentSubtitleBlob) { - return; - } else if (isYoutube) { + }, + + [showDetailInfo], + ); + + useEffect(() => { + if (panelInfo.shptmBanrTpNm === "LIVE") { + if (panelInfo.patnrId && panelInfo.showId) { + dispatch( + getMainCategoryShowDetail({ + patnrId: panelInfo.patnrId, + showId: panelInfo.showId, + curationId: panelInfo.curationId, + }), + ); + } + dispatch(getMainLiveShow({ vodIncFlag: "Y" })); + } + }, [ + dispatch, + panelInfo?.curationId, + panelInfo?.lgCatCd, + panelInfo?.patnrId, + panelInfo?.showId, + panelInfo?.shptmBanrTpNm, + ]); + + useEffect(() => { + if ( + panelInfo.shptmBanrTpNm === "VOD" && + showDetailInfo && + showDetailInfo.length > 0 && + showDetailInfo[0]?.showCatCd && + fullVideolgCatCd !== showDetailInfo[0]?.showCatCd //기존에 호출했으면 안한다. + ) { + dispatch( + getHomeFullVideoInfo({ + lgCatCd: showDetailInfo[0].showCatCd, + }), + ); + } + if ( + panelInfo.shptmBanrTpNm === "VOD" && + showDetailInfo && + showDetailInfo[0] && + showDetailInfo[0].showId && + showDetailInfo[0].patnrId + ) { + if (!featuredShowsInfos || Object.keys(featuredShowsInfos).length === 0) { + setPlayListInfo(showDetailInfo); + } + setShopNowInfo(showDetailInfo[0].productInfos); + saveToLocalSettings(showDetailInfo[0].showId, showDetailInfo[0].patnrId); + } + }, [showDetailInfo]); + + //LIVE + useEffect(() => { + if ( + playListInfo && + playListInfo.length > 0 && + panelInfo.shptmBanrTpNm === "LIVE" + ) { + if (playListInfo[selectedIndex]?.patnrId) { + dispatch( + getMainLiveShowNowProduct({ + patnrId: playListInfo[selectedIndex]?.patnrId, + showId: playListInfo[selectedIndex]?.showId, + }), + ); + } + + if (playListInfo[selectedIndex]?.catCd) { + dispatch( + getHomeFullVideoInfo({ + lgCatCd: playListInfo[selectedIndex]?.catCd, + }), + ); + } + } + }, [selectedIndex]); + + useEffect(() => { + if (showDetailInfo && showDetailInfo.length > 0) { + dispatch(CLEAR_PLAYER_INFO()); + + if ( + showDetailInfo[0]?.liveFlag === "N" && + showDetailInfo[0]?.chatLogFlag === "Y" && + panelInfo.shptmBanrTpNm === "VOD" + ) { + dispatch( + getChatLog({ patnrId: panelInfo.patnrId, showId: panelInfo.showId }), + ); + } + } + }, [showDetailInfo]); + + // videoClick focused + useEffect(() => { + if (playListInfo && playListInfo.length > 0) { + if (panelInfo.targetId) { + videoItemFocused(); + } else { + videoInitialFocused(); + } + } + }, [playListInfo]); + + //10초 후 닫힐때 TabButton 포커스 + useEffect(() => { + if (playListInfo && playListInfo.length > 0) { + videoInitialFocused(); + } + }, [sideContentsVisible, panelInfo.modal]); + + // liveChannel initial selectedIndex + useEffect(() => { + if (panelInfo?.shptmBanrTpNm === "LIVE" && playListInfo?.length > 0) { + const index = playListInfo.findIndex( + (item) => item.chanId === panelInfo.chanId, + ); + if (index !== -1 && !isUpdate) { + setBackupInitialIndex(index); + setSelectedIndex(index); + setIsUpdate(true); + } + } + }, [panelInfo?.shptmBanrTpNm, playListInfo]); + + // live subtitle Luna API + useEffect(() => { + if (currentSubtitleBlob) { + return; + } else if (isYoutube) { + if (mediaId) { + dispatch(requestLiveSubtitle({ mediaId, enable: false })); + setMediaId(null); + } + return; + //do caption action on VideoPlayer(componentDidUpdate) + } else { + if (mediaId && captionEnable && isSubtitleActive && !panelInfo?.modal) { + dispatch(requestLiveSubtitle({ mediaId, enable: true })); + } else { if (mediaId) { dispatch(requestLiveSubtitle({ mediaId, enable: false })); - setMediaId(null); - } - return; - //do caption action on VideoPlayer(componentDidUpdate) - } else { - if (mediaId && captionEnable && isSubtitleActive && !panelInfo?.modal) { - dispatch(requestLiveSubtitle({ mediaId, enable: true })); - } else { - if (mediaId) { - dispatch(requestLiveSubtitle({ mediaId, enable: false })); - } } } - }, [ - mediaId, - isYoutube, - captionEnable, - isSubtitleActive, - currentSubtitleBlob, - panelInfo.modal, - panelInfo.shptmBanrTpNm, - ]); - - // get PlayListInfo - useEffect(() => { - if (panelInfo?.shptmBanrTpNm === "VOD") { - if (showDetailInfo && showDetailInfo.length > 0) { - if (featuredShowsInfos && featuredShowsInfos.length > 0) { - addPanelInfoToPlayList(featuredShowsInfos); - } + } + }, [ + mediaId, + isYoutube, + captionEnable, + isSubtitleActive, + currentSubtitleBlob, + panelInfo.modal, + panelInfo.shptmBanrTpNm, + ]); + + // get PlayListInfo + useEffect(() => { + if (panelInfo?.shptmBanrTpNm === "VOD") { + if (showDetailInfo && showDetailInfo.length > 0) { + if (featuredShowsInfos && featuredShowsInfos.length > 0) { + addPanelInfoToPlayList(featuredShowsInfos); } } - }, [featuredShowsInfos]); - - // get PlayListInfo - useEffect(() => { - if (!panelInfo) return; - - switch (panelInfo.shptmBanrTpNm) { - case "LIVE": { - const playlist = liveShowInfos ?? liveChannelInfos; - - if (!Array.isArray(playlist)) return; - - const modifiedList = []; - - playlist.forEach((item) => { - if (item.showType === "vod" && Array.isArray(item.vodInfos)) { - const mergedVodInfos = item.vodInfos.map((vod) => ({ - ...vod, - patnrId: item.patnrId, - patncNm: item.patncNm, - patncLogoPath: item.patncLogoPath, - showType: "vod", - })); - - modifiedList.push(...mergedVodInfos); - } else { - modifiedList.push(item); - } - }); - - setPlayListInfo(modifiedList); - - if (showNowInfos?.prdtChgYn === "N") { - return; - } - - if (showNowInfos || showDetailInfo?.length > 0) { - const productInfos = showNowInfos - ? showNowInfos.productInfos - : showDetailInfo[0]?.productInfos; - setShopNowInfo(productInfos); - } - break; - } - case "MEDIA": - setPlayListInfo([panelInfo]); - break; - default: - break; - } - }, [ - panelInfo, - showDetailInfo, - featuredShowsInfos, - liveChannelInfos, - liveShowInfos, - showNowInfos, - dispatch, - ]); - - const liveTotalTime = useMemo(() => { - let liveTotalTime; - if (liveShowInfos && panelInfo?.shptmBanrTpNm === "LIVE") { - const startDtMoment = new Date(liveShowInfos[selectedIndex]?.strtDt); - const endDtMoment = new Date(liveShowInfos[selectedIndex]?.endDt); - - liveTotalTime = Math.floor((endDtMoment - startDtMoment) / 1000); - - return liveTotalTime; - } - }, [liveShowInfos, selectedIndex, panelInfo.shptmBanrTpNm]); - - useEffect(() => { - const handleVisibilityChange = () => { - if ( - document.visibilityState === "visible" && - liveShowInfos && - panelInfo?.shptmBanrTpNm === "LIVE" - ) { - const localStartDt = convertUtcToLocal( - liveShowInfos[selectedIndex]?.strtDt - ); - - const curDt = new Date(); - const localStartSec = localStartDt?.getTime() / 1000; - const curSec = curDt?.getTime() / 1000; - - const calculatedLiveTime = curSec - localStartSec; - if (calculatedLiveTime >= liveTotalTime) { - setCurrentLiveTimeSeconds(0); + } + }, [featuredShowsInfos]); + + // get PlayListInfo + useEffect(() => { + if (!panelInfo) return; + + switch (panelInfo.shptmBanrTpNm) { + case "LIVE": { + const playlist = liveShowInfos ?? liveChannelInfos; + + if (!Array.isArray(playlist)) return; + + const modifiedList = []; + + playlist.forEach((item) => { + if (item.showType === "vod" && Array.isArray(item.vodInfos)) { + const mergedVodInfos = item.vodInfos.map((vod) => ({ + ...vod, + patnrId: item.patnrId, + patncNm: item.patncNm, + patncLogoPath: item.patncLogoPath, + showType: "vod", + })); + + modifiedList.push(...mergedVodInfos); } else { - setCurrentLiveTimeSeconds(calculatedLiveTime); + modifiedList.push(item); } + }); + + setPlayListInfo(modifiedList); + + if (showNowInfos?.prdtChgYn === "N") { + return; } - }; - - document.addEventListener("visibilitychange", handleVisibilityChange); - - if (panelInfo.offsetHour) { - setCurrentLiveTimeSeconds(parseInt(panelInfo.offsetHour)); - } else if (liveShowInfos && panelInfo?.shptmBanrTpNm === "LIVE") { + + if (showNowInfos || showDetailInfo?.length > 0) { + const productInfos = showNowInfos + ? showNowInfos.productInfos + : showDetailInfo[0]?.productInfos; + setShopNowInfo(productInfos); + } + break; + } + case "MEDIA": + setPlayListInfo([panelInfo]); + break; + default: + break; + } + }, [ + panelInfo, + showDetailInfo, + featuredShowsInfos, + liveChannelInfos, + liveShowInfos, + showNowInfos, + dispatch, + ]); + + const liveTotalTime = useMemo(() => { + let liveTotalTime; + if (liveShowInfos && panelInfo?.shptmBanrTpNm === "LIVE") { + const startDtMoment = new Date(liveShowInfos[selectedIndex]?.strtDt); + const endDtMoment = new Date(liveShowInfos[selectedIndex]?.endDt); + + liveTotalTime = Math.floor((endDtMoment - startDtMoment) / 1000); + + return liveTotalTime; + } + }, [liveShowInfos, selectedIndex, panelInfo.shptmBanrTpNm]); + + useEffect(() => { + const handleVisibilityChange = () => { + if ( + document.visibilityState === "visible" && + liveShowInfos && + panelInfo?.shptmBanrTpNm === "LIVE" + ) { const localStartDt = convertUtcToLocal( - liveShowInfos[selectedIndex]?.strtDt + liveShowInfos[selectedIndex]?.strtDt, ); - + const curDt = new Date(); const localStartSec = localStartDt?.getTime() / 1000; const curSec = curDt?.getTime() / 1000; - + const calculatedLiveTime = curSec - localStartSec; if (calculatedLiveTime >= liveTotalTime) { setCurrentLiveTimeSeconds(0); } else { setCurrentLiveTimeSeconds(calculatedLiveTime); } - } else { + } + }; + + document.addEventListener("visibilitychange", handleVisibilityChange); + + if (panelInfo.offsetHour) { + setCurrentLiveTimeSeconds(parseInt(panelInfo.offsetHour)); + } else if (liveShowInfos && panelInfo?.shptmBanrTpNm === "LIVE") { + const localStartDt = convertUtcToLocal( + liveShowInfos[selectedIndex]?.strtDt, + ); + + const curDt = new Date(); + const localStartSec = localStartDt?.getTime() / 1000; + const curSec = curDt?.getTime() / 1000; + + const calculatedLiveTime = curSec - localStartSec; + if (calculatedLiveTime >= liveTotalTime) { setCurrentLiveTimeSeconds(0); + } else { + setCurrentLiveTimeSeconds(calculatedLiveTime); } - - return () => { - document.removeEventListener("visibilitychange", handleVisibilityChange); - }; - }, [ - liveShowInfos, - selectedIndex, - panelInfo.offsetHour, - panelInfo.shptmBanrTpNm, - playListInfo, - liveTotalTime, - ]); - - useEffect(() => { - if (panelInfo.shptmBanrTpNm == "LIVE" && liveTotalTime > 0) { - const interval = setInterval(() => { - setCurrentLiveTimeSeconds((prev) => { - if (prev >= liveTotalTime) { - return 1; - } - return prev + 1; - }); - }, 1000); - - return () => clearInterval(interval); + } else { + setCurrentLiveTimeSeconds(0); + } + + return () => { + document.removeEventListener("visibilitychange", handleVisibilityChange); + }; + }, [ + liveShowInfos, + selectedIndex, + panelInfo.offsetHour, + panelInfo.shptmBanrTpNm, + playListInfo, + liveTotalTime, + ]); + + useEffect(() => { + if (panelInfo.shptmBanrTpNm == "LIVE" && liveTotalTime > 0) { + const interval = setInterval(() => { + setCurrentLiveTimeSeconds((prev) => { + if (prev >= liveTotalTime) { + return 1; + } + return prev + 1; + }); + }, 1000); + + return () => clearInterval(interval); + } + }, [liveTotalTime]); + + useEffect(() => { + if (currentLiveTimeSeconds > liveTotalTime) { + setTimeout(() => { + dispatch(getMainLiveShow()); + setShopNowInfo(""); + dispatch( + getHomeFullVideoInfo({ + lgCatCd: playListInfo[selectedIndex].showCatCd, + }), + ); + }, 3000); + } + }, [currentLiveTimeSeconds, liveTotalTime]); + + const mediainfoHandler = useCallback( + (ev) => { + const type = ev.type; + if (type !== "timeupdate" && type !== "durationchange") { + console.log( + "mediainfoHandler....", + type, + ev, + videoPlayer.current?.getMediaState(), + ); } - }, [liveTotalTime]); - - useEffect(() => { - if (currentLiveTimeSeconds > liveTotalTime) { - setTimeout(() => { - dispatch(getMainLiveShow()); - setShopNowInfo(""); - dispatch( - getHomeFullVideoInfo({ - lgCatCd: playListInfo[selectedIndex].showCatCd, - }) - ); - }, 3000); + if ( + ev === "hlsError" && + isNaN(Number(videoPlayer.current?.getMediaState().playbackRate)) + ) { + dispatch( + sendBroadCast({ + type: "videoError", + moreInfo: { reason: "hlsError" }, + }), + ); + + return; } - }, [currentLiveTimeSeconds, liveTotalTime]); - - const mediainfoHandler = useCallback( - (ev) => { - const type = ev.type; - if (type !== "timeupdate" && type !== "durationchange") { - console.log( - "mediainfoHandler....", - type, - ev, - videoPlayer.current?.getMediaState() - ); + + switch (type) { + case "timeupdate": { + setCurrentTime(videoPlayer.current?.getMediaState()?.currentTime); + break; } - if ( - ev === "hlsError" && - isNaN(Number(videoPlayer.current?.getMediaState().playbackRate)) - ) { + case "error": { dispatch( sendBroadCast({ type: "videoError", - moreInfo: { reason: "hlsError" }, - }) + moreInfo: { reason: videoPlayer.current?.getMediaState().error }, + }), ); - - return; + break; } - - switch (type) { - case "timeupdate": { - setCurrentTime(videoPlayer.current?.getMediaState()?.currentTime); - break; - } - case "error": { - dispatch( - sendBroadCast({ - type: "videoError", - moreInfo: { reason: videoPlayer.current?.getMediaState().error }, - }) - ); - break; - } - case "loadeddata": { - const mediaId = videoPlayer.current?.video?.media?.mediaId; - setMediaId(mediaId); - setVideoLoaded(true); - } - } - }, - [currentLiveTimeSeconds, liveTotalTime] - ); - - useEffect(() => { - // case: video error when the video is in fullscreen mode - if ( - broadcast?.type === "videoError" && - isOnTop && - !panelInfo?.modal && - panelInfo?.modalContainerId - ) { - // case: Featured Brands - if (panelInfo?.sourcePanel === panel_names.FEATURED_BRANDS_PANEL) { - dispatch(PanelActions.popPanel()); + case "loadeddata": { + const mediaId = videoPlayer.current?.video?.media?.mediaId; + setMediaId(mediaId); + setVideoLoaded(true); } } - }, [ - broadcast?.type, - isOnTop, - panelInfo?.modal, - panelInfo?.modalContainerId, - panelInfo?.sourcePanel, - ]); - - useEffect(() => { - if ( - panelInfo.modal && - panelInfo.modalContainerId && - (lastPanelAction === "previewPush" || lastPanelAction === "previewUpdate") - ) { - const node = document.querySelector( - `[data-spotlight-id="${panelInfo.modalContainerId}"]` - ); - if (node) { - const { width, height, top, left } = node.getBoundingClientRect(); - const modalStyle = { - width: width + "px", - height: height + "px", - top: top + "px", - left: left + "px", - position: "fixed", - overflow: "visible", - }; - setModalStyle(modalStyle); - let scale = 1; - if (typeof window === "object") { - scale = width / window.innerWidth; - setModalScale(scale); - } - dispatch( - updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { modalStyle: modalStyle, modalScale: scale }, - }) - ); - } else { - setModalStyle(panelInfo.modalStyle); - setModalScale(panelInfo.modalScale); - console.error( - "PlayerPanel modalContainerId node not found", - panelInfo.modalContainerId - ); - } - } else if (isOnTop && !panelInfo.modal && videoPlayer.current) { - if (videoPlayer.current?.getMediaState()?.paused) { - videoPlayer.current.play(); - } - - if ( - videoPlayer.current.areControlsVisible && - !videoPlayer.current.areControlsVisible() - ) { - videoPlayer.current.showControls(); - } + }, + [currentLiveTimeSeconds, liveTotalTime], + ); + + useEffect(() => { + // case: video error when the video is in fullscreen mode + if ( + broadcast?.type === "videoError" && + isOnTop && + !panelInfo?.modal && + panelInfo?.modalContainerId + ) { + // case: Featured Brands + if (panelInfo?.sourcePanel === panel_names.FEATURED_BRANDS_PANEL) { + dispatch(PanelActions.popPanel()); } - }, [panelInfo, isOnTop]); - - const smallestOffsetHourIndex = useMemo(() => { - if (shopNowInfo) { - const filteredVideos = shopNowInfo.filter( - (video) => video.offsetHour >= currentTime - ); - const newSmallestOffsetHour = Math.min( - ...filteredVideos.map((video) => video.offsetHour) - ); - - const newSmallestOffsetHourIndex = shopNowInfo.findIndex( - (video) => video.offsetHour === newSmallestOffsetHour.toString() - ); - - if (shopNowInfo.length === 1) { - return 0; - } - if (newSmallestOffsetHourIndex >= 1) { - return newSmallestOffsetHourIndex - 1; - } - return newSmallestOffsetHourIndex; - } - }, [shopNowInfo, currentTime]); - - const currentSubtitleUrl = useMemo(() => { - if (panelInfo?.shptmBanrTpNm === "MEDIA") { - return panelInfo.subtitle; - } - return playListInfo && playListInfo[selectedIndex]?.showSubtitlUrl; - }, [playListInfo, selectedIndex, panelInfo]); - - const currentPlayingUrl = useMemo(() => { - // return "https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"; - - if (broadcast.type === "videoError") { - return null; - } - - // For previews, always use the direct URL from panelInfo. - if (panelInfo.modal) { - return panelInfo.showUrl; - } - - // For fullscreen, the playlist is the primary source. - if (playListInfo && playListInfo.length > 0 && playListInfo[selectedIndex]?.showUrl) { - return playListInfo[selectedIndex]?.showUrl; - } - - // Fallback for fullscreen if playlist isn't ready, use panelInfo URL. - if (!panelInfo.modal && panelInfo.showUrl) { - return panelInfo.showUrl; - } - - return playListInfo && playListInfo[selectedIndex]?.showUrl; - }, [panelInfo, playListInfo, selectedIndex, broadcast]); - - const isYoutube = useMemo(() => { - if (currentPlayingUrl && currentPlayingUrl.includes("youtu")) { - return true; - } else { - return false; - } - }, [currentPlayingUrl]); - - const currentSubtitleBlob = useMemo(() => { - if (Config.DEBUG_VIDEO_SUBTITLE_TEST) { - return dummyVtt; - } - return vodSubtitleData[currentSubtitleUrl]; - }, [vodSubtitleData, currentSubtitleUrl]); - - const isReadyToPlay = useMemo(() => { - if (!currentPlayingUrl) { - return false; - } - if ( - !Config.DEBUG_VIDEO_SUBTITLE_TEST && - currentSubtitleUrl && - !currentSubtitleBlob - ) { - return false; - } - return true; - }, [currentPlayingUrl, currentSubtitleUrl, currentSubtitleBlob, broadcast]); - - const chatVisible = useMemo(() => { - if ( - playListInfo && - chatData && - !panelInfo.modal && - isOnTop && - panelInfo?.shptmBanrTpNm !== "MEDIA" - ) { - return true; - } - return false; - }, [playListInfo, chatData, panelInfo.modal, isOnTop]); - - useEffect(() => { - if (currentSubtitleUrl) { - dispatch(getSubTitle({ showSubtitleUrl: currentSubtitleUrl })); - } - }, [currentSubtitleUrl]); - - useEffect(() => { - setVideoLoaded(false); - }, [currentPlayingUrl]); - - const handlePopupClose = useCallback(() => { - dispatch(setHidePopup()); - setTimeout(() => Spotlight.focus(SpotlightIds.PLAYER_SUBTITLE_BUTTON)); - }, [dispatch]); - const reactPlayerSubtitleConfig = useMemo(() => { - if (isSubtitleActive && currentSubtitleBlob) { - return { - file: { - attributes: { - crossOrigin: "true", - }, - tracks: [ - { kind: "subtitles", src: currentSubtitleBlob, default: true }, - ], - }, - youtube: YOUTUBECONFIG, + } + }, [ + broadcast?.type, + isOnTop, + panelInfo?.modal, + panelInfo?.modalContainerId, + panelInfo?.sourcePanel, + ]); + + useEffect(() => { + if ( + panelInfo.modal && + panelInfo.modalContainerId && + (lastPanelAction === "previewPush" || lastPanelAction === "previewUpdate") + ) { + const node = document.querySelector( + `[data-spotlight-id="${panelInfo.modalContainerId}"]`, + ); + if (node) { + const { width, height, top, left } = node.getBoundingClientRect(); + const modalStyle = { + width: width + "px", + height: height + "px", + top: top + "px", + left: left + "px", + position: "fixed", + overflow: "visible", }; - } else { - return { - youtube: YOUTUBECONFIG, - }; - } - }, [currentSubtitleBlob, isSubtitleActive]); - - const currentSideButtonStatus = useMemo(() => { - if ( - panelInfo?.shptmBanrTpNm !== "MEDIA" && - !panelInfo?.modal && - sideContentsVisible - ) { - return true; - } - return false; - }, [panelInfo, sideContentsVisible]); - - const videoType = useMemo(() => { - if (currentPlayingUrl) { - if (currentPlayingUrl.toLowerCase().endsWith(".mp4")) { - return "video/mp4"; - } else if (currentPlayingUrl.toLowerCase().endsWith(".mpd")) { - return "application/dash+xml"; - } else if (currentPlayingUrl.toLowerCase().endsWith(".m3u8")) { - return "application/mpegurl"; + setModalStyle(modalStyle); + let scale = 1; + if (typeof window === "object") { + scale = width / window.innerWidth; + setModalScale(scale); } - } - return "application/mpegurl"; - }, [currentPlayingUrl]); - - const orderPhoneNumber = useMemo(() => { - if (panelInfo?.shptmBanrTpNm !== "MEDIA" && showDetailInfo) { - return showDetailInfo[0]?.orderPhnNo; - } else { - return playListInfo[selectedIndex]?.orderPhnNo; - } - }, [panelInfo?.shptmBanrTpNm, showDetailInfo, playListInfo, selectedIndex]); - - const videoThumbnailUrl = useMemo(() => { - let res = null; - - if (panelInfo.shptmBanrTpNm === "MEDIA") { - res = panelInfo?.thumbnailUrl; - } else if (playListInfo && playListInfo.length > 0) { - res = playListInfo[selectedIndex]?.thumbnailUrl; - } else if (!res) { - res = showDetailInfo[0]?.thumbnailUrl; - } - - return res; - }, [ - showDetailInfo, - playListInfo, - selectedIndex, - panelInfo.thumbnailUrl, - panelInfo.shptmBanrTpNm, - ]); - - const saveToLocalSettings = useCallback( - (showId, patnrId) => { - let recentItems = []; - if (localRecentItems) { - recentItems = [...localRecentItems]; - } - - const currentDate = new Date(); - - const formattedDate = `${ - currentDate.getMonth() + 1 - }/${currentDate.getDate()}`; - - const existingProductIndex = recentItems.findIndex((item) => { - if (item.showId) return item.showId === showId; - }); - - if (existingProductIndex !== -1) { - recentItems.splice(existingProductIndex, 1); - } - - recentItems.push({ - patnrId: patnrId, - showId: showId, - date: formattedDate, - expireTime: currentDate.getTime() + 1000 * 60 * 60 * 24 * 14, - cntryCd: httpHeader["X-Device-Country"], - }); - - if (recentItems.length >= 51) { - const data = [...recentItems]; - dispatch(changeLocalSettings({ recentItems: data.slice(1) })); - } else { - dispatch(changeLocalSettings({ recentItems })); - } - }, - [httpHeader, localRecentItems, dispatch] - ); - - const handleIndicatorDownClick = useCallback(() => { - if (!initialEnter) { - setInitialEnter(true); - } - - let newIndex = - selectedIndex === playListInfo.length - 1 ? 0 : selectedIndex + 1; - let initialIndex = newIndex; - let attempts = 0; - - while (!playListInfo[newIndex]?.showId && attempts < playListInfo.length) { - newIndex = newIndex === playListInfo.length - 1 ? 0 : newIndex + 1; - attempts++; - if (newIndex === initialIndex) break; - } - if (playListInfo[newIndex]?.showId) { - setSelectedIndex(newIndex); - if (panelInfo.shptmBanrTpNm === "VOD") { - dispatch( - getMainCategoryShowDetail({ - patnrId: playListInfo[newIndex]?.patnrId, - showId: playListInfo[newIndex]?.showId, - curationId: playListInfo[newIndex]?.curationId, - }) - ); - Spotlight.focus("playVideoShopNowBox"); - } else { - dispatch( - updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - chanId: playListInfo[newIndex].chanId, - patnrId: playListInfo[newIndex].patnrId, - showId: playListInfo[newIndex].showId, - shptmBanrTpNm: panelInfo?.shptmBanrTpNm, - isIndicatorByClick: true, - }, - }) - ); - } - } - if (!sideContentsVisible) { - setPrevChannelIndex(selectedIndex); - } - setSideContentsVisible(true); - }, [ - dispatch, - playListInfo, - selectedIndex, - sideContentsVisible, - initialEnter, - ]); - - const handleIndicatorUpClick = useCallback(() => { - if (!initialEnter) { - setInitialEnter(true); - } - - let newIndex = - selectedIndex === 0 ? playListInfo.length - 1 : selectedIndex - 1; - let initialIndex = newIndex; - let attempts = 0; - - while (!playListInfo[newIndex]?.showId && attempts < playListInfo.length) { - newIndex = newIndex === 0 ? playListInfo.length - 1 : newIndex - 1; - attempts++; - if (newIndex === initialIndex) break; - } - - if (playListInfo[newIndex]?.showId) { - setSelectedIndex(newIndex); - if (panelInfo.shptmBanrTpNm === "VOD") { - dispatch( - getMainCategoryShowDetail({ - patnrId: playListInfo[newIndex]?.patnrId, - showId: playListInfo[newIndex]?.showId, - curationId: playListInfo[newIndex]?.curationId, - }) - ); - Spotlight.focus("playVideoShopNowBox"); - } else { - dispatch( - updatePanel({ - name: panel_names.PLAYER_PANEL, - panelInfo: { - chanId: playListInfo[newIndex].chanId, - patnrId: playListInfo[newIndex].patnrId, - showId: playListInfo[newIndex].showId, - shptmBanrTpNm: panelInfo?.shptmBanrTpNm, - isIndicatorByClick: true, - }, - }) - ); - } - } - if (!sideContentsVisible) { - setPrevChannelIndex(selectedIndex); - } - setSideContentsVisible(true); - }, [ - dispatch, - playListInfo, - selectedIndex, - sideContentsVisible, - initialEnter, - ]); - - useEffect(() => { - if ( - panelInfo.shptmBanrTpNm === "VOD" && - panelInfo.patnrId && - panelInfo.showId - ) { - //VOD의 panelInfo.showId 가 변경된 최초 한번만 호출하고, FearchedShow 항목에서 선택시 또는 상하 indicator 선택시 호출한다. - dispatch( - getMainCategoryShowDetail({ - patnrId: panelInfo.patnrId, - showId: panelInfo.showId, - curationId: panelInfo.curationId, - }) - ); - } - }, [panelInfo.showId]); - - useEffect(() => { - return () => { - dispatch(clearShopNowInfo()); - dispatch(CLEAR_PLAYER_INFO()); - setShopNowInfo([]); - }; - }, []); - - const onEnded = useCallback((e) => { - if (panelInfoRef.current.shptmBanrTpNm === "MEDIA") { dispatch( updatePanel({ - name: panel_names.DETAIL_PANEL, - panelInfo: { - launchedFromPlayer: true, - isPlayerFinished: true, - }, - }) + name: panel_names.PLAYER_PANEL, + panelInfo: { modalStyle: modalStyle, modalScale: scale }, + }), + ); + } else { + setModalStyle(panelInfo.modalStyle); + setModalScale(panelInfo.modalScale); + console.error( + "PlayerPanel modalContainerId node not found", + panelInfo.modalContainerId, ); - Spotlight.pause(); - setTimeout(() => { - Spotlight.resume(); - dispatch(PanelActions.popPanel()); - }, VIDEO_END_ACTION_DELAY); - return; } - if (panelInfoRef.current.shptmBanrTpNm === "VOD") { - Spotlight.pause(); - setTimeout(() => { - Spotlight.resume(); - if (panelInfoRef.current.modal) { - videoPlayer.current.play(); - } else { - dispatch(PanelActions.popPanel(panel_names.PLAYER_PANEL)); - } - }, VIDEO_END_ACTION_DELAY); - e?.stopPropagation(); - e?.preventDefault(); - return; + } else if (isOnTop && !panelInfo.modal && videoPlayer.current) { + if (videoPlayer.current?.getMediaState()?.paused) { + videoPlayer.current.play(); } - }, []); - - const onKeyDown = (ev) => { - if (ev.keyCode === 34) { - handleIndicatorDownClick(); - ev.stopPropagation(); - ev.preventDefault(); - } else if (ev.keyCode === 33) { - handleIndicatorUpClick(); - ev.stopPropagation(); - ev.preventDefault(); - } - }; - - const [initialEnter, setInitialEnter] = USE_STATE("initialEnter", true); - const timerId = useRef(null); - const showSideContents = useMemo(() => { - return ( - sideContentsVisible && - playListInfo && - panelInfo?.shptmBanrTpNm !== "MEDIA" && - !panelInfo?.modal && - isOnTop - ); - }, [sideContentsVisible, playListInfo, panelInfo, isOnTop]); - - const qrCurrentItem = useMemo(() => { - if (shopNowInfo?.length && panelInfo?.shptmBanrTpNm === "LIVE") { - return shopNowInfo[shopNowInfo.length - 1]; - } - + if ( - shopNowInfo?.length && - smallestOffsetHourIndex >= 0 && - panelInfo?.shptmBanrTpNm !== "LIVE" + videoPlayer.current.areControlsVisible && + !videoPlayer.current.areControlsVisible() ) { - return shopNowInfo[smallestOffsetHourIndex]; + videoPlayer.current.showControls(); } - - if (panelInfo?.shptmBanrTpNm === "MEDIA" && panelInfo?.qrCurrentItem) { - return panelInfo.qrCurrentItem; + } + }, [panelInfo, isOnTop]); + + const smallestOffsetHourIndex = useMemo(() => { + if (shopNowInfo) { + const filteredVideos = shopNowInfo.filter( + (video) => video.offsetHour >= currentTime, + ); + const newSmallestOffsetHour = Math.min( + ...filteredVideos.map((video) => video.offsetHour), + ); + + const newSmallestOffsetHourIndex = shopNowInfo.findIndex( + (video) => video.offsetHour === newSmallestOffsetHour.toString(), + ); + + if (shopNowInfo.length === 1) { + return 0; } - + if (newSmallestOffsetHourIndex >= 1) { + return newSmallestOffsetHourIndex - 1; + } + return newSmallestOffsetHourIndex; + } + }, [shopNowInfo, currentTime]); + + const currentSubtitleUrl = useMemo(() => { + if (panelInfo?.shptmBanrTpNm === "MEDIA") { + return panelInfo.subtitle; + } + return playListInfo && playListInfo[selectedIndex]?.showSubtitlUrl; + }, [playListInfo, selectedIndex, panelInfo]); + + const currentPlayingUrl = useMemo(() => { + // return "https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"; + + if (broadcast.type === "videoError") { return null; - }, [ - shopNowInfo, - smallestOffsetHourIndex, - panelInfo?.shptmBanrTpNm, - panelInfo?.qrCurrentItem, - ]); - - const isShowType = useMemo(() => { - if (["VOD", "MEDIA"].includes(panelInfo.shptmBanrTpNm)) { - return panelInfo.shptmBanrTpNm; + } + + // For previews, always use the direct URL from panelInfo. + if (panelInfo.modal) { + return panelInfo.showUrl; + } + + // For fullscreen, the playlist is the primary source. + if ( + playListInfo && + playListInfo.length > 0 && + playListInfo[selectedIndex]?.showUrl + ) { + return playListInfo[selectedIndex]?.showUrl; + } + + // Fallback for fullscreen if playlist isn't ready, use panelInfo URL. + if (!panelInfo.modal && panelInfo.showUrl) { + return panelInfo.showUrl; + } + + return playListInfo && playListInfo[selectedIndex]?.showUrl; + }, [panelInfo, playListInfo, selectedIndex, broadcast]); + + const isYoutube = useMemo(() => { + if (currentPlayingUrl && currentPlayingUrl.includes("youtu")) { + return true; + } else { + return false; + } + }, [currentPlayingUrl]); + + const currentSubtitleBlob = useMemo(() => { + if (Config.DEBUG_VIDEO_SUBTITLE_TEST) { + return dummyVtt; + } + return vodSubtitleData[currentSubtitleUrl]; + }, [vodSubtitleData, currentSubtitleUrl]); + + const isReadyToPlay = useMemo(() => { + if (!currentPlayingUrl) { + return false; + } + if ( + !Config.DEBUG_VIDEO_SUBTITLE_TEST && + currentSubtitleUrl && + !currentSubtitleBlob + ) { + return false; + } + return true; + }, [currentPlayingUrl, currentSubtitleUrl, currentSubtitleBlob, broadcast]); + + const chatVisible = useMemo(() => { + if ( + playListInfo && + chatData && + !panelInfo.modal && + isOnTop && + panelInfo?.shptmBanrTpNm !== "MEDIA" + ) { + return true; + } + return false; + }, [playListInfo, chatData, panelInfo.modal, isOnTop]); + + useEffect(() => { + if (currentSubtitleUrl) { + dispatch(getSubTitle({ showSubtitleUrl: currentSubtitleUrl })); + } + }, [currentSubtitleUrl]); + + useEffect(() => { + setVideoLoaded(false); + }, [currentPlayingUrl]); + + const handlePopupClose = useCallback(() => { + dispatch(setHidePopup()); + setTimeout(() => Spotlight.focus(SpotlightIds.PLAYER_SUBTITLE_BUTTON)); + }, [dispatch]); + const reactPlayerSubtitleConfig = useMemo(() => { + if (isSubtitleActive && currentSubtitleBlob) { + return { + file: { + attributes: { + crossOrigin: "true", + }, + tracks: [ + { kind: "subtitles", src: currentSubtitleBlob, default: true }, + ], + }, + youtube: YOUTUBECONFIG, + }; + } else { + return { + youtube: YOUTUBECONFIG, + }; + } + }, [currentSubtitleBlob, isSubtitleActive]); + + const currentSideButtonStatus = useMemo(() => { + if ( + panelInfo?.shptmBanrTpNm !== "MEDIA" && + !panelInfo?.modal && + sideContentsVisible + ) { + return true; + } + return false; + }, [panelInfo, sideContentsVisible]); + + const videoType = useMemo(() => { + if (currentPlayingUrl) { + if (currentPlayingUrl.toLowerCase().endsWith(".mp4")) { + return "video/mp4"; + } else if (currentPlayingUrl.toLowerCase().endsWith(".mpd")) { + return "application/dash+xml"; + } else if (currentPlayingUrl.toLowerCase().endsWith(".m3u8")) { + return "application/mpegurl"; } - - const showType = playListInfo?.[selectedIndex]?.showType; - if (showType === "live") return panelInfo.shptmBanrTpNm; - if (showType === "vod") return "VOD"; - + } + return "application/mpegurl"; + }, [currentPlayingUrl]); + + const orderPhoneNumber = useMemo(() => { + if (panelInfo?.shptmBanrTpNm !== "MEDIA" && showDetailInfo) { + return showDetailInfo[0]?.orderPhnNo; + } else { + return playListInfo[selectedIndex]?.orderPhnNo; + } + }, [panelInfo?.shptmBanrTpNm, showDetailInfo, playListInfo, selectedIndex]); + + const videoThumbnailUrl = useMemo(() => { + let res = null; + + if (panelInfo.shptmBanrTpNm === "MEDIA") { + res = panelInfo?.thumbnailUrl; + } else if (playListInfo && playListInfo.length > 0) { + res = playListInfo[selectedIndex]?.thumbnailUrl; + } else if (!res) { + res = showDetailInfo[0]?.thumbnailUrl; + } + + return res; + }, [ + showDetailInfo, + playListInfo, + selectedIndex, + panelInfo.thumbnailUrl, + panelInfo.shptmBanrTpNm, + ]); + + const saveToLocalSettings = useCallback( + (showId, patnrId) => { + let recentItems = []; + if (localRecentItems) { + recentItems = [...localRecentItems]; + } + + const currentDate = new Date(); + + const formattedDate = `${ + currentDate.getMonth() + 1 + }/${currentDate.getDate()}`; + + const existingProductIndex = recentItems.findIndex((item) => { + if (item.showId) return item.showId === showId; + }); + + if (existingProductIndex !== -1) { + recentItems.splice(existingProductIndex, 1); + } + + recentItems.push({ + patnrId: patnrId, + showId: showId, + date: formattedDate, + expireTime: currentDate.getTime() + 1000 * 60 * 60 * 24 * 14, + cntryCd: httpHeader["X-Device-Country"], + }); + + if (recentItems.length >= 51) { + const data = [...recentItems]; + dispatch(changeLocalSettings({ recentItems: data.slice(1) })); + } else { + dispatch(changeLocalSettings({ recentItems })); + } + }, + [httpHeader, localRecentItems, dispatch], + ); + + const handleIndicatorDownClick = useCallback(() => { + if (!initialEnter) { + setInitialEnter(true); + } + + let newIndex = + selectedIndex === playListInfo.length - 1 ? 0 : selectedIndex + 1; + let initialIndex = newIndex; + let attempts = 0; + + while (!playListInfo[newIndex]?.showId && attempts < playListInfo.length) { + newIndex = newIndex === playListInfo.length - 1 ? 0 : newIndex + 1; + attempts++; + if (newIndex === initialIndex) break; + } + if (playListInfo[newIndex]?.showId) { + setSelectedIndex(newIndex); + if (panelInfo.shptmBanrTpNm === "VOD") { + dispatch( + getMainCategoryShowDetail({ + patnrId: playListInfo[newIndex]?.patnrId, + showId: playListInfo[newIndex]?.showId, + curationId: playListInfo[newIndex]?.curationId, + }), + ); + Spotlight.focus("playVideoShopNowBox"); + } else { + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + chanId: playListInfo[newIndex].chanId, + patnrId: playListInfo[newIndex].patnrId, + showId: playListInfo[newIndex].showId, + shptmBanrTpNm: panelInfo?.shptmBanrTpNm, + isIndicatorByClick: true, + }, + }), + ); + } + } + if (!sideContentsVisible) { + setPrevChannelIndex(selectedIndex); + } + setSideContentsVisible(true); + }, [ + dispatch, + playListInfo, + selectedIndex, + sideContentsVisible, + initialEnter, + ]); + + const handleIndicatorUpClick = useCallback(() => { + if (!initialEnter) { + setInitialEnter(true); + } + + let newIndex = + selectedIndex === 0 ? playListInfo.length - 1 : selectedIndex - 1; + let initialIndex = newIndex; + let attempts = 0; + + while (!playListInfo[newIndex]?.showId && attempts < playListInfo.length) { + newIndex = newIndex === 0 ? playListInfo.length - 1 : newIndex - 1; + attempts++; + if (newIndex === initialIndex) break; + } + + if (playListInfo[newIndex]?.showId) { + setSelectedIndex(newIndex); + if (panelInfo.shptmBanrTpNm === "VOD") { + dispatch( + getMainCategoryShowDetail({ + patnrId: playListInfo[newIndex]?.patnrId, + showId: playListInfo[newIndex]?.showId, + curationId: playListInfo[newIndex]?.curationId, + }), + ); + Spotlight.focus("playVideoShopNowBox"); + } else { + dispatch( + updatePanel({ + name: panel_names.PLAYER_PANEL, + panelInfo: { + chanId: playListInfo[newIndex].chanId, + patnrId: playListInfo[newIndex].patnrId, + showId: playListInfo[newIndex].showId, + shptmBanrTpNm: panelInfo?.shptmBanrTpNm, + isIndicatorByClick: true, + }, + }), + ); + } + } + if (!sideContentsVisible) { + setPrevChannelIndex(selectedIndex); + } + setSideContentsVisible(true); + }, [ + dispatch, + playListInfo, + selectedIndex, + sideContentsVisible, + initialEnter, + ]); + + useEffect(() => { + if ( + panelInfo.shptmBanrTpNm === "VOD" && + panelInfo.patnrId && + panelInfo.showId + ) { + //VOD의 panelInfo.showId 가 변경된 최초 한번만 호출하고, FearchedShow 항목에서 선택시 또는 상하 indicator 선택시 호출한다. + dispatch( + getMainCategoryShowDetail({ + patnrId: panelInfo.patnrId, + showId: panelInfo.showId, + curationId: panelInfo.curationId, + }), + ); + } + }, [panelInfo.showId]); + + useEffect(() => { + return () => { + dispatch(clearShopNowInfo()); + dispatch(CLEAR_PLAYER_INFO()); + setShopNowInfo([]); + }; + }, []); + + const onEnded = useCallback((e) => { + if (panelInfoRef.current.shptmBanrTpNm === "MEDIA") { + dispatch( + updatePanel({ + name: panel_names.DETAIL_PANEL, + panelInfo: { + launchedFromPlayer: true, + isPlayerFinished: true, + }, + }), + ); + Spotlight.pause(); + setTimeout(() => { + Spotlight.resume(); + dispatch(PanelActions.popPanel()); + }, VIDEO_END_ACTION_DELAY); + return; + } + if (panelInfoRef.current.shptmBanrTpNm === "VOD") { + Spotlight.pause(); + setTimeout(() => { + Spotlight.resume(); + if (panelInfoRef.current.modal) { + videoPlayer.current.play(); + } else { + dispatch(PanelActions.popPanel(panel_names.PLAYER_PANEL)); + } + }, VIDEO_END_ACTION_DELAY); + e?.stopPropagation(); + e?.preventDefault(); + return; + } + }, []); + + const onKeyDown = (ev) => { + if (ev.keyCode === 34) { + handleIndicatorDownClick(); + ev.stopPropagation(); + ev.preventDefault(); + } else if (ev.keyCode === 33) { + handleIndicatorUpClick(); + ev.stopPropagation(); + ev.preventDefault(); + } + }; + + const [initialEnter, setInitialEnter] = USE_STATE("initialEnter", true); + const timerId = useRef(null); + const showSideContents = useMemo(() => { + return ( + sideContentsVisible && + playListInfo && + panelInfo?.shptmBanrTpNm !== "MEDIA" && + !panelInfo?.modal && + isOnTop + ); + }, [sideContentsVisible, playListInfo, panelInfo, isOnTop]); + + const qrCurrentItem = useMemo(() => { + if (shopNowInfo?.length && panelInfo?.shptmBanrTpNm === "LIVE") { + return shopNowInfo[shopNowInfo.length - 1]; + } + + if ( + shopNowInfo?.length && + smallestOffsetHourIndex >= 0 && + panelInfo?.shptmBanrTpNm !== "LIVE" + ) { + return shopNowInfo[smallestOffsetHourIndex]; + } + + if (panelInfo?.shptmBanrTpNm === "MEDIA" && panelInfo?.qrCurrentItem) { + return panelInfo.qrCurrentItem; + } + + return null; + }, [ + shopNowInfo, + smallestOffsetHourIndex, + panelInfo?.shptmBanrTpNm, + panelInfo?.qrCurrentItem, + ]); + + const isShowType = useMemo(() => { + if (["VOD", "MEDIA"].includes(panelInfo.shptmBanrTpNm)) { return panelInfo.shptmBanrTpNm; - }, [panelInfo.shptmBanrTpNm, playListInfo, selectedIndex]); - const clearTimer = useCallback(() => { - clearTimeout(timerId.current); - timerId.current = null; - }, []); - - const resetTimer = useCallback((timeout) => { + } + + const showType = playListInfo?.[selectedIndex]?.showType; + if (showType === "live") return panelInfo.shptmBanrTpNm; + if (showType === "vod") return "VOD"; + + return panelInfo.shptmBanrTpNm; + }, [panelInfo.shptmBanrTpNm, playListInfo, selectedIndex]); + const clearTimer = useCallback(() => { + clearTimeout(timerId.current); + timerId.current = null; + }, []); + + const resetTimer = useCallback((timeout) => { + if (timerId.current) { + clearTimer(); + } + + if (initialEnter) { + setInitialEnter(false); + } + + timerId.current = setTimeout(() => { + setSideContentsVisible(false); + }, timeout); + }, []); + + useEffect(() => { + if (isOnTop && !panelInfo.modal && !videoVerticalVisible) { + setSideContentsVisible(true); + } + }, [panelInfo.modal]); + + useEffect(() => { + const node = document.querySelector( + `[data-spotlight-id=${TAB_CONTAINER_SPOTLIGHT_ID}]`, + ); + + if (!showSideContents || !node || videoVerticalVisible) return; + + // NOTE 첫 진입 시에는 10초 후 탭이 닫히도록 설정 + if (initialEnter) { + resetTimer(INITIAL_TIMEOUT); + } + + const handleEvent = () => resetTimer(REGULAR_TIMEOUT); + TARGET_EVENTS.forEach((event) => node.addEventListener(event, handleEvent)); + + return () => { + TARGET_EVENTS.forEach((event) => + node.removeEventListener(event, handleEvent), + ); + if (timerId.current) { clearTimer(); } - - if (initialEnter) { - setInitialEnter(false); + }; + }, [showSideContents, videoVerticalVisible]); + + useEffect(() => { + if (initialEnter || !sideContentsVisible || videoVerticalVisible) return; + + // NOTE button을 통해 탭을 연 경우 5초 후 탭이 닫히도록 설정 + if (sideContentsVisible) { + resetTimer(REGULAR_TIMEOUT); + } + + return () => { + if (timerId.current) { + clearTimer(); } - - timerId.current = setTimeout(() => { - setSideContentsVisible(false); - }, timeout); - }, []); - - useEffect(() => { - if (isOnTop && !panelInfo.modal && !videoVerticalVisible) { - setSideContentsVisible(true); - } - }, [panelInfo.modal]); - - useEffect(() => { - const node = document.querySelector( - `[data-spotlight-id=${TAB_CONTAINER_SPOTLIGHT_ID}]` - ); - - if (!showSideContents || !node || videoVerticalVisible) return; - - // NOTE 첫 진입 시에는 10초 후 탭이 닫히도록 설정 - if (initialEnter) { - resetTimer(INITIAL_TIMEOUT); - } - - const handleEvent = () => resetTimer(REGULAR_TIMEOUT); - TARGET_EVENTS.forEach((event) => node.addEventListener(event, handleEvent)); - - return () => { - TARGET_EVENTS.forEach((event) => - node.removeEventListener(event, handleEvent) - ); - - if (timerId.current) { - clearTimer(); + }; + }, [sideContentsVisible]); + + useLayoutEffect(() => { + const videoContainer = document.querySelector(`.${css.videoContainer}`); + + if (panelInfo.thumbnail && !videoVerticalVisible) { + videoContainer.style.background = `url(${panelInfo.thumbnail}) center center / contain no-repeat`; + videoContainer.style.backgroundColor = "black"; + } + + if (broadcast.type === "videoError" && videoThumbnailUrl) { + videoContainer.style.background = `url(${videoThumbnailUrl}) center center / contain no-repeat`; + videoContainer.style.backgroundColor = "black"; + } + }, [panelInfo.thumbnail, broadcast]); + + const isPlayer = useMemo(() => { + if (!panelInfo?.modal) { + return "full player"; + } + + switch (panels[0].name) { + case "categorypanel": + return "category"; + case "mypagepanel": + return "my page"; + case "searchpanel": + return "search"; + case "hotpickpanel": + return "hot picks"; + case "featuredbrandspanel": + return "featured brands"; + case "trendingnowpanel": + return "trending now"; + case "playerpanel": + return "home"; + } + }, [panelInfo.modal, panels]); + + const createLogParams = useCallback( + (visible) => { + if (videoLoaded && isShowType) { + if (showDetailInfo?.[0]) { + return { + visible, + showType: isShowType, + player: isPlayer, + category: showDetailInfo[0].showCatNm, + contentId: showDetailInfo[0].showId, + contentTitle: showDetailInfo[0].showNm, + partner: showDetailInfo[0].patncNm, + contextName: Config.LOG_CONTEXT_NAME.SHOW, + messageId: Config.LOG_MESSAGE_ID.SHOWVIEW, + }; + } else if (playListInfo?.[selectedIndex]) { + const currentItem = playListInfo[selectedIndex]; + return { + visible, + showType: isShowType, + player: isPlayer, + category: currentItem.catNm, + contentId: currentItem.showId, + contentTitle: currentItem.showNm, + partner: currentItem.patncNm, + contextName: Config.LOG_CONTEXT_NAME.SHOW, + messageId: Config.LOG_MESSAGE_ID.SHOWVIEW, + }; } - }; - }, [showSideContents, videoVerticalVisible]); - - useEffect(() => { - if (initialEnter || !sideContentsVisible || videoVerticalVisible) return; - - // NOTE button을 통해 탭을 연 경우 5초 후 탭이 닫히도록 설정 - if (sideContentsVisible) { - resetTimer(REGULAR_TIMEOUT); } - - return () => { - if (timerId.current) { - clearTimer(); - } - }; - }, [sideContentsVisible]); - - useLayoutEffect(() => { - const videoContainer = document.querySelector(`.${css.videoContainer}`); - - if (panelInfo.thumbnail && !videoVerticalVisible) { - videoContainer.style.background = `url(${panelInfo.thumbnail}) center center / contain no-repeat`; - videoContainer.style.backgroundColor = "black"; + return null; + }, + [ + isShowType, + videoLoaded, + showDetailInfo?.[0]?.showId, + playListInfo?.[selectedIndex]?.showId, + ], + ); + + // isVODPaused 상태 변경 시에만 로그를 보냄 + useEffect(() => { + if (showDetailInfo?.[0]) { + const params = createLogParams(!isVODPaused); + if (params) { + dispatch(sendLogTotalRecommend(params)); } - - if (broadcast.type === "videoError" && videoThumbnailUrl) { - videoContainer.style.background = `url(${videoThumbnailUrl}) center center / contain no-repeat`; - videoContainer.style.backgroundColor = "black"; + } else if (playListInfo?.[selectedIndex]) { + const params = createLogParams(true); + if (params) { + dispatch(sendLogTotalRecommend(params)); } - }, [panelInfo.thumbnail, broadcast]); - - const isPlayer = useMemo(() => { - if (!panelInfo?.modal) { - return "full player"; + } + }, [isVODPaused, createLogParams]); + + // 컴포넌트 언마운트 시에만 로그를 보냄 + useEffect(() => { + return () => { + const params = createLogParams(false); + if (params) { + dispatch(sendLogTotalRecommend(params)); } - - switch (panels[0].name) { - case "categorypanel": - return "category"; - case "mypagepanel": - return "my page"; - case "searchpanel": - return "search"; - case "hotpickpanel": - return "hot picks"; - case "featuredbrandspanel": - return "featured brands"; - case "trendingnowpanel": - return "trending now"; - case "playerpanel": - return "home"; - } - }, [panelInfo.modal, panels]); - - const createLogParams = useCallback( - (visible) => { - if (videoLoaded && isShowType) { - if (showDetailInfo?.[0]) { - return { - visible, - showType: isShowType, - player: isPlayer, - category: showDetailInfo[0].showCatNm, - contentId: showDetailInfo[0].showId, - contentTitle: showDetailInfo[0].showNm, - partner: showDetailInfo[0].patncNm, - contextName: Config.LOG_CONTEXT_NAME.SHOW, - messageId: Config.LOG_MESSAGE_ID.SHOWVIEW, - }; - } else if (playListInfo?.[selectedIndex]) { - const currentItem = playListInfo[selectedIndex]; - return { - visible, - showType: isShowType, - player: isPlayer, - category: currentItem.catNm, - contentId: currentItem.showId, - contentTitle: currentItem.showNm, - partner: currentItem.patncNm, - contextName: Config.LOG_CONTEXT_NAME.SHOW, - messageId: Config.LOG_MESSAGE_ID.SHOWVIEW, - }; + }; + }, [createLogParams, dispatch]); + + useEffect(() => { + if (playerControl.ownerId === spotlightId && videoPlayer.current) { + const internalPlayer = videoPlayer.current.getInternalPlayer(); + if (internalPlayer) { + if (playerControl.isPaused) { + internalPlayer.pause(); + } else { + // It only works when it's already paused. + if (internalPlayer.paused) { + internalPlayer.play(); } } - return null; - }, - [ - isShowType, - videoLoaded, - showDetailInfo?.[0]?.showId, - playListInfo?.[selectedIndex]?.showId, - ] - ); - - // isVODPaused 상태 변경 시에만 로그를 보냄 - useEffect(() => { - if (showDetailInfo?.[0]) { - const params = createLogParams(!isVODPaused); - if (params) { - dispatch(sendLogTotalRecommend(params)); - } - } else if (playListInfo?.[selectedIndex]) { - const params = createLogParams(true); - if (params) { - dispatch(sendLogTotalRecommend(params)); - } } - }, [isVODPaused, createLogParams]); - - // 컴포넌트 언마운트 시에만 로그를 보냄 - useEffect(() => { - return () => { - const params = createLogParams(false); - if (params) { - dispatch(sendLogTotalRecommend(params)); - } - }; - }, [createLogParams, dispatch]); - - return ( - { + if (panelInfo.isUpdatedByClick && panelInfo.isIndicatorByClick) { + videoInitialFocused(); + } + }, [panelInfo.isUpdatedByClick, panelInfo.isIndicatorByClick]); + + return ( + + - - {isReadyToPlay && ( - - {typeof window === "object" && window.PalmSystem && ( - - )} - {isSubtitleActive && - !panelInfo.modal && - captionEnable && - typeof window === "object" && - window.PalmSystem && - currentSubtitleBlob && ( - - )} - - )} - - {chatVisible && ( - - )} - - {currentSideButtonStatus && !videoVerticalVisible && playListInfo && ( - - )} - - {showSideContents && ( - - )} - - - {activePopup === ACTIVE_POPUP.alertPopup && ( - + {typeof window === "object" && window.PalmSystem && ( + )} - button2Text={$L("OK")} - open={popupVisible} - onClose={handlePopupClose} - > + {isSubtitleActive && + !panelInfo.modal && + captionEnable && + typeof window === "object" && + window.PalmSystem && + currentSubtitleBlob && ( + + )} + )} - - ); - }; - - const propsAreEqual = (prev, next) => { - const keys = Object.keys(prev); - const nextKeys = Object.keys(next); - // if (!next.isOnTop) { - // //ignore event on background - // return true; - // } - if (keys.length !== nextKeys.length) { + + {chatVisible && ( + + )} + + {currentSideButtonStatus && !videoVerticalVisible && playListInfo && ( + + )} + + {showSideContents && ( + + )} + + + {activePopup === ACTIVE_POPUP.alertPopup && ( + + )} + + ); +}; + +const propsAreEqual = (prev, next) => { + const keys = Object.keys(prev); + const nextKeys = Object.keys(next); + // if (!next.isOnTop) { + // //ignore event on background + // return true; + // } + if (keys.length !== nextKeys.length) { + return false; + } + for (let i = 0; i < keys.length; i++) { + if (prev[keys[i]] !== next[keys[i]]) { + if (JSON.stringify(prev[keys[i]]) === JSON.stringify(next[keys[i]])) { + continue; + } return false; } - for (let i = 0; i < keys.length; i++) { - if (prev[keys[i]] !== next[keys[i]]) { - if (JSON.stringify(prev[keys[i]]) === JSON.stringify(next[keys[i]])) { - continue; - } - return false; - } - } - return true; - }; - export default React.memo(PlayerPanelNew, propsAreEqual); - \ No newline at end of file + } + return true; +}; +export default React.memo(PlayerPanelNew, propsAreEqual);