diff --git a/com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.module.less b/com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.module.less
index 09630954..183564b6 100644
--- a/com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.module.less
+++ b/com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.module.less
@@ -779,6 +779,8 @@
align-items: center;
gap: 12px;
width: 100%;
+ margin-left: 20px;
+ margin-right: 20px;
}
.times {
diff --git a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.module.less b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.module.less
index 798f4739..22900d9f 100644
--- a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.module.less
+++ b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.module.less
@@ -695,6 +695,7 @@
height: 70px;
width:1800px;
margin-left:60px;
+ margin-right: 59px;
bottom:92px;
> *:first-child {
text-align: right;
diff --git a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less
index d3c91ed5..d674fc53 100644
--- a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less
+++ b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less
@@ -1,19 +1,19 @@
// VideoPlayer.module.less
//
-@import "~@enact/sandstone/styles/variables.less";
+@import "~@enact/sandstone/styles/variables.less";
@import "~@enact/sandstone/styles/mixins.less";
@import "~@enact/sandstone/styles/skin.less";
@import "../../style/utils.module.less";
@import "../../style/CommonStyle.module.less";
-.fullscreen .videoPlayer,
-.videoPlayer {
- // Set by counting the IconButtons inside the side components.
- --liftDistance: 0px;
-
- overflow: hidden;
- padding: 2px;
- margin: 0;
- box-sizing: border-box;
+.fullscreen .videoPlayer,
+.videoPlayer {
+ // Set by counting the IconButtons inside the side components.
+ --liftDistance: 0px;
+
+ overflow: hidden;
+ padding: 2px;
+ margin: 0;
+ box-sizing: border-box;
:focus {
outline: none !important;
@@ -21,51 +21,51 @@
box-shadow: none !important;
}
- &.fullscreen {
- width: 100%;
- height: 100%;
- }
-
- .video {
- height: 100%;
- width: 100%;
- background: #000;
- max-width: none;
- max-height: none;
- }
+ &.fullscreen {
+ width: 100%;
+ height: 100%;
+ }
- .media {
- height: var(--media-height, calc(100% - 4px));
- width: var(--media-width, calc(100% - 4px));
- background: #000;
-
- &.mediaBackground {
- &:after {
- width: 560px;
- height: 200px;
- position: absolute;
- left: 0;
- bottom: 0;
- content: "";
- background: linear-gradient(
- to top,
- rgba(255, 255, 255, 1),
- transparent
- );
- opacity: 0.2;
- }
- }
- }
-
- &.fullscreen {
- --media-width: 100vw;
- --media-height: 100vh;
- }
-
- .fullscreen .videoPlayer .media {
- --media-width: 100vw;
- --media-height: 100vh;
- }
+ .video {
+ height: 100%;
+ width: 100%;
+ background: #000;
+ max-width: none;
+ max-height: none;
+ }
+
+ .media {
+ height: var(--media-height, calc(100% - 4px));
+ width: var(--media-width, calc(100% - 4px));
+ background: #000;
+
+ &.mediaBackground {
+ &:after {
+ width: 560px;
+ height: 200px;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ content: "";
+ background: linear-gradient(
+ to top,
+ rgba(255, 255, 255, 1),
+ transparent
+ );
+ opacity: 0.2;
+ }
+ }
+ }
+
+ &.fullscreen {
+ --media-width: 100vw;
+ --media-height: 100vh;
+ }
+
+ .fullscreen .videoPlayer .media {
+ --media-width: 100vw;
+ --media-height: 100vh;
+ }
.preloadVideo {
display: none;
@@ -613,11 +613,11 @@
}
}
- .overlay {
- .position(@position: absolute, @top: 0, @right: 0, @bottom: 0, @left: 0);
- pointer-events: auto;
- z-index: 10;
- }
+ .overlay {
+ .position(@position: absolute, @top: 0, @right: 0, @bottom: 0, @left: 0);
+ pointer-events: auto;
+ z-index: 10;
+ }
@keyframes spin {
0% {
transform: rotate(0.25turn);
@@ -741,11 +741,11 @@
}
}
- .controlsHandleAbove {
- pointer-events: none;
- z-index: -1;
- .position(@position: absolute, @top: 0, @right: 0, @bottom: auto, @left: 0);
- }
+ .controlsHandleAbove {
+ pointer-events: none;
+ z-index: -1;
+ .position(@position: absolute, @top: 0, @right: 0, @bottom: auto, @left: 0);
+ }
// Skin colors
.applySkins({
diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx
index 29ef1d9c..142d078f 100644
--- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx
+++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx
@@ -1,9 +1,464 @@
-import React from 'react';
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useRef,
+} from 'react';
-import PlayerOverlayContents from './PlayerOverlayContents';
+import classNames from 'classnames';
+import {
+ useDispatch,
+ useSelector,
+} from 'react-redux';
-function MediaOverlayContents(props) {
- return
/gi, ' ') : '';
+ }, [playListInfo, selectedIndex, panelInfo, type]);
+
+ const onSpotlightMoveTabButton = useCallback((e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ Spotlight.focus(SpotlightIds.PLAYER_TAB_BUTTON);
+ }, []);
+
+ const onSpotlightMoveMediaButton = useCallback(
+ (e) => {
+ e.stopPropagation();
+
+ // TabContainerV2의 tabIndex=2일 때 하단 버튼들로 포커스 이동
+ if (tabContainerVersion === 2 && tabIndexV2 === 2) {
+ if (Spotlight.focus('live-channel-next-button')) return;
+ if (Spotlight.focus('below-tab-shop-now-button')) return;
+ }
+
+ if (type === 'LIVE') {
+ return Spotlight.focus('videoIndicator-down-button');
+ }
+ return Spotlight.focus(SpotlightIds.PLAYER_PLAY_BUTTON);
+ },
+ [type, tabContainerVersion, tabIndexV2]
+ );
+
+ const onSpotlightMoveSubtitleButton = useCallback(
+ () => {
+ // 1. 먼저 자막 버튼으로 포커스 시도
+ if (Spotlight.focus('player-subtitlebutton')) {
+ return true;
+ }
+
+ // TabContainerV2의 tabIndex=2일 때 TabContainerV2 버튼들로 포커스 이동
+ if (tabContainerVersion === 2 && tabIndexV2 === 2) {
+ let focusSuccessful = false;
+
+ // 먼저 LiveChannelNext 버튼으로 시도
+ if (Spotlight.focus('live-channel-next-button')) {
+ focusSuccessful = true;
+ }
+ // 실패하면 ShopNowButton으로 시도
+ else if (Spotlight.focus('below-tab-shop-now-button')) {
+ focusSuccessful = true;
+ }
+
+ if (focusSuccessful) {
+ return;
+ }
+ }
+
+ // 기본 동작: 자막 버튼으로 포커스
+ return Spotlight.focus('player-subtitlebutton');
+ },
+ [tabContainerVersion, tabIndexV2]
+ );
+
+ const onSpotlightMoveSlider = useCallback(
+ (e) => {
+ if (type === 'VOD') {
+ e.stopPropagation();
+
+ Spotlight.focus(SpotlightIds.PLAYER_SLIDER);
+ }
+ },
+ [type]
+ );
+
+ const onSpotlightMoveSideTab = useCallback((e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ Spotlight.focus('tab-0');
+ }, []);
+
+ const onSpotlightMoveBelowTab = useCallback(
+ (e) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ console.log(`[onSpotlightMoveBelowTab] tabIndexV2: ${tabIndexV2}`);
+
+ // tabIndexV2에 따라 다른 버튼으로 포커스 이동
+ if (tabIndexV2 === 0) {
+ // ShopNow 탭: Close 버튼으로
+ // Spotlight.focus('below-tab-close-button');
+ const result = Spotlight.focus('shownow_close_button');
+ console.log(`[onSpotlightMoveBelowTab] tabIndexV2=0, focus result:`, result);
+ } else if (tabIndexV2 === 1) {
+ // LIVE CHANNEL 탭: LIVE CHANNEL 버튼으로
+ const result = Spotlight.focus('below-tab-live-channel-button');
+ console.log(`[onSpotlightMoveBelowTab] tabIndexV2=1, focus result:`, result);
+ } else if (tabIndexV2 === 2) {
+ // ShopNowButton: ShopNowButton으로
+ const result = Spotlight.focus('below-tab-shop-now-button');
+ console.log(`[onSpotlightMoveBelowTab] tabIndexV2=2, focus result:`, result);
+ }
+ },
+ [tabIndexV2]
+ );
+
+ // Back Button arrow down 전용 핸들러 - tabIndex에 따라 다른 포커스
+ const handleBackButtonDown = useCallback(
+ (e) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (tabContainerVersion === 2 && belowContentsVisible) {
+ if (tabIndexV2 === 0) {
+ // tabIndexV2가 0일 때 ShopNow 닫기 버튼으로 포커스
+ const result = Spotlight.focus('shownow_close_button');
+ } else if (tabIndexV2 === 1) {
+ // tabIndexV2가 1일 때 below-tab-live-channel-button으로 포커스
+ Spotlight.focus('below-tab-live-channel-button');
+ } else if (tabIndexV2 === 2) {
+ // tabIndexV2가 2일 때 LiveChannelNext로 포커스
+ Spotlight.focus('live-channel-next-button');
+ } else {
+ // 그 외에는 기존 로직 사용
+ onSpotlightMoveMediaButton(e);
+ }
+ } else {
+ onSpotlightMoveMediaButton(e);
+ }
+ },
+ [tabContainerVersion, belowContentsVisible, tabIndexV2, onSpotlightMoveMediaButton]
+ );
+
+ const onSpotlightMoveBackButton = useCallback(() => {
+ return Spotlight.focus(SpotlightIds.PLAYER_BACK_BUTTON);
+ }, []);
+
+ const handleOverlayKeyDownCapture = useCallback(
+ (ev) => {
+ const currentId = Spotlight.getCurrent()?.getAttribute('data-spotlight-id');
+ if (ev.keyCode === 40 && currentId === SpotlightIds.PLAYER_BACK_BUTTON) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ return handleBackButtonDown(ev);
+ }
+ if (ev.keyCode === 39 && currentId === SpotlightIds.PLAYER_BACK_BUTTON) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ return onSpotlightMoveSubtitleButton(ev);
+ }
+ if (ev.keyCode === 37 && currentId === SpotlightIds.PLAYER_SUBTITLE_BUTTON) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ return onSpotlightMoveBackButton(ev);
+ }
+ if (ev.keyCode === 38 && currentId === SpotlightIds.PLAYER_PLAY_BUTTON) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ return onSpotlightMoveBackButton();
+ }
+ },
+ [onSpotlightMoveBackButton, onSpotlightMoveMediaButton, onSpotlightMoveSubtitleButton, handleBackButtonDown]
+ );
+
+ const currentSideButtonStatus = useMemo(() => {
+ if (
+ !panelInfo?.modal &&
+ !sideContentsVisible &&
+ tabContainerVersion === 1
+ ) {
+ return true;
+ }
+ return false;
+ }, [panelInfo, sideContentsVisible, tabContainerVersion]);
+
+ const noLiveContentsVisible = useMemo(() => {
+ if (!Array.isArray(playListInfo) || playListInfo.length === 0) {
+ return false;
+ }
+
+ const noShowIdCount = playListInfo.filter((item) => !item.showId).length;
+ if (playListInfo.length - 1 === noShowIdCount) {
+ return false;
+ }
+
+ return true;
+ }, [playListInfo]);
+
+ return (
+ <>
+ {partnerName}
+
+ {!panelInfo?.modal && (
+
+ )}
+