diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx index 1418579a..eabbee2e 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx @@ -1,2227 +1,2266 @@ -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); - } -}; - -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 PlayerPanel = ({ - 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); - - 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 {}; - } - - 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 {}; - }, [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; - } - - 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" - : "", - }; - } - }, [ - 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: {} })) - ) - ); - }; - } - } - }, [ - 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 = { - ...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 = { - ...mediaLogParamsRef.current, - watchStrtDt, - watchEndDt, - }; - dispatch(changeLocalSettings({ watchRecord })); - }, 10000); - - return () => { - setLogStatus((status) => ({ - ...status, - isFullMediaLogReady: false, - })); - clearInterval(watchInterval.current); - dispatch( - 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 ( - 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) - 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 //기존에 호출했으면 안한다. - ) { - 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 })); - } - } - } - }, [ - 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); - } else { - setCurrentLiveTimeSeconds(calculatedLiveTime); - } - } - }; - - 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); - } - } 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() - ); - } - if ( - ev === "hlsError" && - isNaN(Number(videoPlayer.current?.getMediaState().playbackRate)) - ) { - dispatch( - sendBroadCast({ - type: "videoError", - moreInfo: { reason: "hlsError" }, - }) - ); - - return; - } - - 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()); - } - } - }, [ - 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(); - } - } - }, [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; - } - return playListInfo && playListInfo[selectedIndex]?.showUrl; - }, [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"; - } - } - 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; - } - - 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(); - } - }; - }, [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"; - } - - 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]); - - useEffect(() => { - if (!panelInfo?.shptmBanrTpNm) return; - - const brandArray = - showDetailInfo?.[0]?.productInfos?.map((item) => item.brndNm) || []; - const categoryArray = - showDetailInfo?.[0]?.productInfos?.map((item) => item.catNm) || []; - const params = { - visible: "true", - showType: panelInfo.shptmBanrTpNm, - player: isPlayer, - contentId: showDetailInfo?.[0]?.showId || "", - contentTitle: showDetailInfo?.[0]?.showNm || "", - partner: showDetailInfo?.[0]?.patncNm || "", - brand: brandArray.join("|") || null, - category: categoryArray.join("|") || null, - contextName: Config.LOG_CONTEXT_NAME.SHOW, - messageId: Config.LOG_MESSAGE_ID.SHOWVIEW, - }; - - dispatch(sendLogTotalRecommend(params)); - - return () => { - const unmountParams = { - ...params, - visible: "false", - }; - dispatch(sendLogTotalRecommend(unmountParams)); - }; - }, [panelInfo?.shptmBanrTpNm, isPlayer]); - - 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 && ( - - )} - - ); -}; - -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; - } - } - return true; -}; -export default React.memo(PlayerPanel, propsAreEqual); +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); + } +}; + +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 PlayerPanel = ({ + 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 {}; + } + + 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 {}; + }, [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; + } + + 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" + : "", + }; + } + }, [ + 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: {} })) + ) + ); + }; + } + } + }, [ + 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 = { + ...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 = { + ...mediaLogParamsRef.current, + watchStrtDt, + watchEndDt, + }; + dispatch(changeLocalSettings({ watchRecord })); + }, 10000); + + return () => { + setLogStatus((status) => ({ + ...status, + isFullMediaLogReady: false, + })); + clearInterval(watchInterval.current); + dispatch( + 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 ( + 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) + 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 //기존에 호출했으면 안한다. + ) { + 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 })); + } + } + } + }, [ + 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); + } else { + setCurrentLiveTimeSeconds(calculatedLiveTime); + } + } + }; + + 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); + } + } 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() + ); + } + if ( + ev === "hlsError" && + isNaN(Number(videoPlayer.current?.getMediaState().playbackRate)) + ) { + dispatch( + sendBroadCast({ + type: "videoError", + moreInfo: { reason: "hlsError" }, + }) + ); + + return; + } + + 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()); + } + } + }, [ + 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(); + } + } + }, [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; + } + return playListInfo && playListInfo[selectedIndex]?.showUrl; + }, [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"; + } + } + 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; + } + + 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(); + } + }; + }, [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"; + } + + 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]; + console.log("###visible", visible); + 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, + }; + } + } + 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 () => { + console.log("###cleanup"); + const params = createLogParams(false); + if (params) { + dispatch(sendLogTotalRecommend(params)); + } + }; + }, [createLogParams, dispatch]); + + 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 && ( + + )} + + ); +}; + +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; + } + } + return true; +}; +export default React.memo(PlayerPanel, propsAreEqual);