[PlayerPanel] SideTab 폴더 구조 분해

This commit is contained in:
고동영
2024-04-29 14:35:14 +09:00
parent 15115b44d0
commit 363e3e557c
17 changed files with 280 additions and 155 deletions

View File

@@ -725,7 +725,7 @@ const VideoPlayerBase = class extends React.Component {
static contextType = FloatingLayerContext; static contextType = FloatingLayerContext;
static defaultProps = { static defaultProps = {
autoCloseTimeout: 5000, // autoCloseTimeout: 5000,
feedbackHideDelay: 3000, feedbackHideDelay: 3000,
initialJumpDelay: 400, initialJumpDelay: 400,
jumpBy: 30, jumpBy: 30,

View File

@@ -7,13 +7,10 @@ import React, {
} from "react"; } from "react";
import classNames from "classnames"; import classNames from "classnames";
import ReactPlayer from "react-player";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { Job } from "@enact/core/util"; import { Job } from "@enact/core/util";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import dummyVtt from "../../../assets/mock/video.vtt"; import dummyVtt from "../../../assets/mock/video.vtt";
import * as CommonActions from "../../actions/commonActions"; import * as CommonActions from "../../actions/commonActions";
@@ -30,30 +27,16 @@ import {
getSubTitle, getSubTitle,
startVideoPlayer, startVideoPlayer,
} from "../../actions/playActions"; } from "../../actions/playActions";
import { MediaControls } from "../../components/MediaPlayer";
import TButton from "../../components/TButton/TButton";
import TButtonTab, { LIST_TYPE } from "../../components/TButtonTab/TButtonTab";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
import VideoOverlayWithPhoneNumber from "../../components/VideoOverlayWithPhoneNumber/VideoOverlayWithPhoneNumber"; import VideoOverlayWithPhoneNumber from "../../components/VideoOverlayWithPhoneNumber/VideoOverlayWithPhoneNumber";
import { VideoPlayer } from "../../components/VideoPlayer/VideoPlayer"; import { VideoPlayer } from "../../components/VideoPlayer/VideoPlayer";
import VideoPlayerSubtitle from "../../components/VideoPlayerSubtitle/VideoPlayerSubtitle";
import * as Config from "../../utils/Config"; import * as Config from "../../utils/Config";
import { panel_names } from "../../utils/Config"; import { panel_names } from "../../utils/Config";
import { $L } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
import PlayerOverlayChat from "./PlayerOverlay/PlayerOverlayChat"; import PlayerOverlayChat from "./PlayerOverlay/PlayerOverlayChat";
import PlayerOverlayHeader from "./PlayerOverlay/PlayerOverlayHeader";
import PlayerOverlayQRCode from "./PlayerOverlay/PlayerOverlayQRCode";
import css from "./PlayerPanel.module.less"; import css from "./PlayerPanel.module.less";
import FeaturedShowContents from "./PlayerTabContents/FeaturedShowContents"; import PlayerTabButton from "./PlayerTabContents/TabButton/PlayerTabButton";
import LiveChannelContents from "./PlayerTabContents/LiveChannelContents"; import TabContainer from "./PlayerTabContents/TabContaienr";
import ShopNowContents from "./PlayerTabContents/ShopNowContents";
import YouMayLikeContents from "./PlayerTabContents/YouMayLikeContents";
const SpottableBtn = Spottable("button");
const Container = SpotlightContainerDecorator(
{ enterTo: "default-element" },
"div"
);
const unableToPlay = new Job((callback) => { const unableToPlay = new Job((callback) => {
callback(); callback();
@@ -71,7 +54,6 @@ const PlayerPanel = ({
const [playListInfo, setPlayListInfo] = useState(""); const [playListInfo, setPlayListInfo] = useState("");
const [shopNowInfo, setShopNowInfo] = useState(); const [shopNowInfo, setShopNowInfo] = useState();
const [modalStyle, setModalStyle] = useState({}); const [modalStyle, setModalStyle] = useState({});
const [tab, setTab] = useState(0);
const [sideOpen, setSideOpen] = useState(true); const [sideOpen, setSideOpen] = useState(true);
const [selectedIndex, setSelectedIndex] = useState(0); const [selectedIndex, setSelectedIndex] = useState(0);
const [isUpdate, setIsUpdate] = useState(false); const [isUpdate, setIsUpdate] = useState(false);
@@ -89,12 +71,8 @@ const PlayerPanel = ({
const showNowInfos = useSelector((state) => state.main.showNowInfo); const showNowInfos = useSelector((state) => state.main.showNowInfo);
const showNowProduct = useSelector((state) => state.main.showNowProduct); const showNowProduct = useSelector((state) => state.main.showNowProduct);
const liveShowInfos = useSelector((state) => state.main.liveShowInfos); const liveShowInfos = useSelector((state) => state.main.liveShowInfos);
//getSubTitle
const vodSubtitleData = useSelector((state) => state.play.subTitleBlobs); const vodSubtitleData = useSelector((state) => state.play.subTitleBlobs);
const tabList = [ const { cursorVisible } = useSelector((state) => state.common.appStatus);
$L("SHOP NOW"),
$L(panelInfo?.shptmBanrTpNm === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
];
const onClickBack = useCallback( const onClickBack = useCallback(
(ev) => { (ev) => {
@@ -133,18 +111,6 @@ const PlayerPanel = ({
}; };
}, [panelInfo?.modal]); }, [panelInfo?.modal]);
const handleItemClick = useCallback(
({ index }) => {
if (index === tab) return;
setTab(index);
},
[tab]
);
const handleTabOnClick = () => {
setSideOpen((prev) => !prev);
};
const isActive = useMemo(() => { const isActive = useMemo(() => {
return playListInfo; return playListInfo;
}, [playListInfo]); }, [playListInfo]);
@@ -158,26 +124,6 @@ const PlayerPanel = ({
videoPlayer.current = ref; videoPlayer.current = ref;
}, []); }, []);
const onSpotlightBackBtn = () => {
const timer = setTimeout(() => {
Spotlight.focus("videoBackbtn");
});
return () => {
clearTimeout(timer);
};
};
const onSpotlightReduceBtn = () => {
const timer = setTimeout(() => {
Spotlight.focus("videoReduceBtn");
});
return () => {
clearTimeout(timer);
};
};
const toastUnableToPlay = useCallback(() => { const toastUnableToPlay = useCallback(() => {
dispatch(CommonActions.alertToast($L("An unknown error has occured."))); dispatch(CommonActions.alertToast($L("An unknown error has occured.")));
onClickBack(); onClickBack();
@@ -191,11 +137,22 @@ const PlayerPanel = ({
setPlayListInfo(updatedPlayListInfo); setPlayListInfo(updatedPlayListInfo);
}; };
const autoCloseTimeout = useMemo(() => { const autoCloseVideoOverlay = useMemo(() => {
console.log("#sideOpen", sideOpen);
if (!sideOpen && panelInfo.modal === false) { if (!sideOpen && panelInfo.modal === false) {
return 3000; return 3000;
} }
}, [sideOpen, panelInfo]); }, [sideOpen, panelInfo]);
//10초뒤에 사이드 오픈 ( 예외처리 필요 )
useEffect(() => {
const timer = setTimeout(() => {
setSideOpen(false);
}, 10000);
return () => clearTimeout(timer);
}, []);
useEffect(() => { useEffect(() => {
if (panelInfo) { if (panelInfo) {
//console.log("#panelInfo", panelInfo); //console.log("#panelInfo", panelInfo);
@@ -282,7 +239,6 @@ const PlayerPanel = ({
]); ]);
// 일정시간마다 API를 재호출해야하는 기능 테스트기간 동안 주석 // 일정시간마다 API를 재호출해야하는 기능 테스트기간 동안 주석
useEffect(() => { useEffect(() => {
if (panelInfo?.shptmBanrTpNm === "LIVE") { if (panelInfo?.shptmBanrTpNm === "LIVE") {
const interval = setInterval(() => { const interval = setInterval(() => {
@@ -422,7 +378,7 @@ const PlayerPanel = ({
disabled={panelInfo.modal} disabled={panelInfo.modal}
onEnded={onClickBack} // 플레이어가 끝날때 호출 onEnded={onClickBack} // 플레이어가 끝날때 호출
noAutoPlay={cannotPlay} // 오토플레이 noAutoPlay={cannotPlay} // 오토플레이
autoCloseTimeout={autoCloseTimeout} // 컨트롤 버튼 숨기는 시간 autoCloseTimeout={autoCloseVideoOverlay} // 컨트롤 버튼 숨기는 시간
playListInfo={playListInfo && playListInfo} // 비디오 데이터 playListInfo={playListInfo && playListInfo} // 비디오 데이터
onBackButton={onClickBack} // 뒤로가기 버튼 onBackButton={onClickBack} // 뒤로가기 버튼
panelInfo={panelInfo} // 패널정보 (라이브,VOD) panelInfo={panelInfo} // 패널정보 (라이브,VOD)
@@ -445,6 +401,9 @@ const PlayerPanel = ({
)} )}
</VideoPlayer> </VideoPlayer>
)} )}
{/* Overlay Area */}
{playListInfo && playListInfo[selectedIndex]?.orderPhnNo && ( {playListInfo && playListInfo[selectedIndex]?.orderPhnNo && (
<VideoOverlayWithPhoneNumber <VideoOverlayWithPhoneNumber
className={css.videoOverlayWithPhoneNumber} className={css.videoOverlayWithPhoneNumber}
@@ -453,54 +412,17 @@ const PlayerPanel = ({
/> />
)} )}
{playListInfo && chatData && <PlayerOverlayChat />} {playListInfo && chatData && <PlayerOverlayChat />}
{/* <PlayerOverlayQRCode /> */}
{panelInfo?.shptmBanrTpNm !== "MEDIA" && ( {panelInfo?.shptmBanrTpNm !== "MEDIA" && (
<div <PlayerTabButton setSideOpen={setSideOpen} sideOpen={sideOpen} />
className={classNames(
css.arrow,
sideOpen ? css.arrowOpen : css.arrowClose
)}
>
<SpottableBtn
spotlightId={"hotpicks-close-arrow"}
onClick={handleTabOnClick}
className={css.button}
onSpotlightUp={onSpotlightBackBtn}
onSpotlightDown={onSpotlightReduceBtn}
/>
</div>
)} )}
{/* </Container> */}
{sideOpen && panelInfo?.shptmBanrTpNm !== "MEDIA" && ( {sideOpen && panelInfo?.shptmBanrTpNm !== "MEDIA" && (
<Container className={css.tabContainer}> <TabContainer
<TButtonTab panelInfo={panelInfo}
contents={tabList} shopNowInfo={shopNowInfo}
className={css.tTab} playListInfo={playListInfo}
onItemClick={handleItemClick} setSelectedIndex={setSelectedIndex}
selectedIndex={tab} liveChannelInfos={liveChannelInfos || liveShowInfos}
listType={LIST_TYPE.small} />
/>
{tab === 0 && <ShopNowContents shopNowInfo={shopNowInfo} />}
{panelInfo?.shptmBanrTpNm === "VOD" && tab === 1 && (
<FeaturedShowContents
featuredShowsInfos={playListInfo}
setSelectedIndex={setSelectedIndex}
/>
)}
{panelInfo?.shptmBanrTpNm === "LIVE" &&
tab === 1 &&
(liveChannelInfos || liveShowInfos) && (
<LiveChannelContents
setSelectedIndex={setSelectedIndex}
liveInfos={playListInfo}
/>
)}
{shopNowInfo && shopNowInfo.length < 3 && tab === 0 && (
<YouMayLikeContents shopNowInfo={shopNowInfo} />
)}
</Container>
)} )}
</TPanel> </TPanel>
); );

View File

@@ -116,28 +116,6 @@
} }
} }
} }
.tabContainer {
.size(@w:660px, @h:100%);
background: #2c343f;
position: absolute;
right: 0;
top: 0;
padding: 48px 30px 0 30px;
z-index: 999;
.tTab {
border-radius: 12px;
overflow: hidden;
width: auto;
height: auto;
margin-bottom: 24px;
> div {
.size(@w:300px, @h:66px);
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
.videoOverlayWithPhoneNumber { .videoOverlayWithPhoneNumber {
bottom: 210px; bottom: 210px;
@@ -175,7 +153,7 @@
display: none; display: none;
} }
} }
&.hideSubtitle{ &.hideSubtitle {
video::cue { video::cue {
visibility: hidden; visibility: hidden;
} }

View File

@@ -0,0 +1,52 @@
import React from "react";
import classNames from "classnames";
import Spotlight from "@enact/spotlight";
import Spottable from "@enact/spotlight/Spottable";
import css from "./PlayerTabButton.module.less";
const SpottableBtn = Spottable("button");
export default function PlayerTabButton({ sideOpen, setSideOpen }) {
const onSpotlightBackBtn = () => {
const timer = setTimeout(() => {
Spotlight.focus("videoBackbtn");
});
return () => {
clearTimeout(timer);
};
};
const onSpotlightReduceBtn = () => {
const timer = setTimeout(() => {
Spotlight.focus("videoReduceBtn");
});
return () => {
clearTimeout(timer);
};
};
const handleTabOnClick = () => {
setSideOpen((prev) => !prev);
};
return (
<div
className={classNames(
css.arrow,
sideOpen ? css.arrowOpen : css.arrowClose
)}
>
<SpottableBtn
spotlightId={"hotpicks-close-arrow"}
onClick={handleTabOnClick}
className={css.button}
onSpotlightUp={onSpotlightBackBtn}
onSpotlightDown={onSpotlightReduceBtn}
/>
</div>
);
}

View File

@@ -0,0 +1,76 @@
@import "../../../../style/utils.module.less";
.arrow {
.size(@w: 48px, @h: 144px);
text-align: center;
position: absolute;
top: 468px;
z-index: 2;
> button {
.size(@w: 48px, @h: 144px);
background-size: 48px 144px;
background-repeat: no-repeat;
font-size: 0;
line-height: 0;
display: inline-block;
cursor: pointer;
}
&.arrowClose {
right: -2px;
> button {
&.button {
background-image: url(../../../../../assets/images/btn/btn-toopen-nor.svg);
&:focus {
background-image: url(../../../../../assets/images/btn/btn-toopen-foc.svg);
}
}
}
}
&.arrowOpen {
right: 658px;
z-index: 4;
> button {
position: relative;
z-index: 5;
&.button {
background-image: url(../../../../../assets/images/btn/btn-toclose-nor.svg);
&:focus {
background-image: url(../../../../../assets/images/btn/btn-toclose-foc.svg);
}
}
&:before,
&:after {
width: 1920px;
height: 50%;
position: fixed;
left: 0;
content: "";
z-index: 4;
}
&:before {
bottom: 0;
background: linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, transparent 50%);
}
&:after {
top: 0;
background: linear-gradient(
180deg,
rgba(0, 0, 0, 1) 0%,
transparent 50%
);
}
}
&:after {
width: 1920px;
height: 1080px;
position: fixed;
left: 0;
content: "";
z-index: 4;
top: 0;
background-color: rgba(0, 0, 0, 0.3);
cursor: auto;
}
}
}

View File

@@ -0,0 +1,71 @@
import React, { useCallback, useState } from "react";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import TButtonTab, {
LIST_TYPE,
} from "../../../components/TButtonTab/TButtonTab";
import { $L } from "../../../utils/helperMethods";
import css from "./TabContainer.module.less";
import FeaturedShowContents from "./TabContents/FeaturedShowContents";
import LiveChannelContents from "./TabContents/LiveChannelContents";
import ShopNowContents from "./TabContents/ShopNowContents";
import YouMayLikeContents from "./TabContents/YouMayLikeContents";
const Container = SpotlightContainerDecorator(
{ enterTo: "default-element" },
"div"
);
export default function TabContainer({
panelInfo,
playListInfo,
shopNowInfo,
setSelectedIndex,
liveChannelInfos,
}) {
const [tab, setTab] = useState(0);
const tabList = [
$L("SHOP NOW"),
$L(panelInfo?.shptmBanrTpNm === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
];
const handleItemClick = useCallback(
({ index }) => {
if (index === tab) return;
setTab(index);
},
[tab]
);
return (
<Container className={css.tabContainer}>
<TButtonTab
contents={tabList}
className={css.tTab}
onItemClick={handleItemClick}
selectedIndex={tab}
listType={LIST_TYPE.small}
/>
{tab === 0 && <ShopNowContents shopNowInfo={shopNowInfo} />}
{panelInfo?.shptmBanrTpNm === "VOD" && tab === 1 && (
<FeaturedShowContents
featuredShowsInfos={playListInfo}
setSelectedIndex={setSelectedIndex}
/>
)}
{panelInfo?.shptmBanrTpNm === "LIVE" && tab === 1 && liveChannelInfos && (
<LiveChannelContents
setSelectedIndex={setSelectedIndex}
liveInfos={playListInfo}
/>
)}
{shopNowInfo && shopNowInfo.length < 3 && tab === 0 && (
<YouMayLikeContents shopNowInfo={shopNowInfo} />
)}
</Container>
);
}

View File

@@ -0,0 +1,25 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.tabContainer {
.size(@w:660px, @h:100%);
background: #2c343f;
position: absolute;
right: 0;
top: 0;
padding: 48px 30px 0 30px;
z-index: 999;
.tTab {
border-radius: 12px;
overflow: hidden;
width: auto;
height: auto;
margin-bottom: 24px;
> div {
.size(@w:300px, @h:66px);
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}

View File

@@ -2,10 +2,10 @@ import React, { useCallback, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { pushPanel, updatePanel } from "../../../actions/panelActions"; import { pushPanel, updatePanel } from "../../../../actions/panelActions";
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../../utils/Config";
import PlayerItemCard, { TYPES } from "../PlayerItemCard/PlayerItemCard"; import PlayerItemCard, { TYPES } from "../../PlayerItemCard/PlayerItemCard";
import css from "./LiveChannelContents.module.less"; import css from "./LiveChannelContents.module.less";
import PlayerTabLoading from "./PlayerTabLoading"; import PlayerTabLoading from "./PlayerTabLoading";

View File

@@ -1,4 +1,4 @@
@import "../../../style/utils.module.less"; @import "../../../../style/utils.module.less";
.container { .container {
height: 956px; height: 956px;

View File

@@ -2,10 +2,10 @@ import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { pushPanel, updatePanel } from "../../../actions/panelActions"; import { pushPanel, updatePanel } from "../../../../actions/panelActions";
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../../utils/Config";
import PlayerItemCard, { TYPES } from "../PlayerItemCard/PlayerItemCard"; import PlayerItemCard, { TYPES } from "../../PlayerItemCard/PlayerItemCard";
import css from "./LiveChannelContents.module.less"; import css from "./LiveChannelContents.module.less";
import PlayerTabLoading from "./PlayerTabLoading"; import PlayerTabLoading from "./PlayerTabLoading";

View File

@@ -1,4 +1,4 @@
@import "../../../style/utils.module.less"; @import "../../../../style/utils.module.less";
.container { .container {
height: 956px; height: 956px;

View File

@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import loading from "../../../../assets/images/img-contents-loading@3x.png"; import loading from "../../../../../assets/images/img-contents-loading@3x.png";
import { $L } from "../../../utils/helperMethods"; import { $L } from "../../../../utils/helperMethods";
import css from "./PlayerTabLoading.module.less"; import css from "./PlayerTabLoading.module.less";
export default function PlayerTabLoading() { export default function PlayerTabLoading() {

View File

@@ -1,4 +1,5 @@
@import "../../../style/utils.module.less"; @import "../../../../style/utils.module.less";
.loadingContainer { .loadingContainer {
height: 250px; height: 250px;
display: flex; display: flex;

View File

@@ -4,10 +4,10 @@ import { useDispatch, useSelector } from "react-redux";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { pushPanel, updatePanel } from "../../../actions/panelActions"; import { pushPanel, updatePanel } from "../../../../actions/panelActions";
import TItemCard, { TYPES } from "../../../components/TItemCard/TItemCard"; import TItemCard, { TYPES } from "../../../../components/TItemCard/TItemCard";
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../../utils/Config";
import PlayerTabLoading from "./PlayerTabLoading"; import PlayerTabLoading from "./PlayerTabLoading";
import css from "./ShopNowContents.module.less"; import css from "./ShopNowContents.module.less";
@@ -41,7 +41,7 @@ export default function ShopNowContents({ shopNowInfo }) {
panelInfo: { panelInfo: {
patnrId, patnrId,
prdtId, prdtId,
launchedFromPlayer: true launchedFromPlayer: true,
}, },
}) })
); );

View File

@@ -1,4 +1,4 @@
@import "../../../style/utils.module.less"; @import "../../../../style/utils.module.less";
.container { .container {
overflow: hidden; overflow: hidden;

View File

@@ -2,11 +2,11 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { pushPanel } from "../../../actions/panelActions"; import { pushPanel } from "../../../../actions/panelActions";
import TItemCard, { TYPES } from "../../../components/TItemCard/TItemCard"; import TItemCard, { TYPES } from "../../../../components/TItemCard/TItemCard";
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../../utils/Config";
import { $L } from "../../../utils/helperMethods"; import { $L } from "../../../../utils/helperMethods";
import PlayerTabLoading from "./PlayerTabLoading"; import PlayerTabLoading from "./PlayerTabLoading";
import css from "./YouMayLikeContents.module.less"; import css from "./YouMayLikeContents.module.less";

View File

@@ -1,5 +1,5 @@
@import "../../../style/CommonStyle.module.less"; @import "../../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less"; @import "../../../../style/utils.module.less";
.title { .title {
color: #ffffff; color: #ffffff;
font-size: 36px; font-size: 36px;