[PlayerPanel] 비디오 관련 Js 파일 커스텀 , 큐레이션 아이디 추가 , live API 추가

This commit is contained in:
고동영
2024-04-05 10:17:17 +09:00
parent b762bf7492
commit afa7635dbc
25 changed files with 568 additions and 391 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

View File

@@ -67,6 +67,7 @@ export const types = {
SET_MAIN_LIKE_CATEGORY: "SET_MAIN_LIKE_CATEGORY", SET_MAIN_LIKE_CATEGORY: "SET_MAIN_LIKE_CATEGORY",
SET_MAIN_LIVE_UPCOMING_ALARM: "SET_MAIN_LIVE_UPCOMING_ALARM", SET_MAIN_LIVE_UPCOMING_ALARM: "SET_MAIN_LIVE_UPCOMING_ALARM",
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "GET_MAIN_LIVE_SHOW_NOW_PRODUCT", GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "GET_MAIN_LIVE_SHOW_NOW_PRODUCT",
GET_MAIN_LIVE_SHOW: "GET_MAIN_LIVE_SHOW",
GET_MAIN_CATEGORY_SHOW_DETAIL: "GET_MAIN_CATEGORY_SHOW_DETAIL", GET_MAIN_CATEGORY_SHOW_DETAIL: "GET_MAIN_CATEGORY_SHOW_DETAIL",
// myPage actions // myPage actions

View File

@@ -6,6 +6,31 @@ import * as HelperMethods from '../utils/helperMethods';
import { types } from './actionTypes'; import { types } from './actionTypes';
import { fetchingController } from './commonActions'; import { fetchingController } from './commonActions';
export const getMainLiveShow = (props) => (dispatch, getState) => {
const onSuccess = (response) => {
console.log("@@ getMainLiveShow onSuccess", response.data);
dispatch({
type: types.GET_MAIN_LIVE_SHOW,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("@@ getMainLiveShow onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_MAIN_LIVE_SHOW,
{},
{},
onSuccess,
onFail
);
};
// Live 알람 설정/해제 IF-LGSP-012 // Live 알람 설정/해제 IF-LGSP-012
export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => { export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
const { alamDispFlag, endDt, patnrId, showId, strtDt } = props; const { alamDispFlag, endDt, patnrId, showId, strtDt } = props;
@@ -60,7 +85,7 @@ export const getMainCategoryDetail = (props) => (dispatch, getState) => {
// 영상 상세 보기 조회 LF-LGSP-047 // 영상 상세 보기 조회 LF-LGSP-047
export const getMainCategoryShowDetail = (props) => (dispatch, getState) => { export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
const { patnrId, showId } = props; const { patnrId, showId, curationId } = props;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getMainCategoryShowDetail onSuccess ", response.data); console.log("getMainCategoryShowDetail onSuccess ", response.data);
@@ -79,7 +104,7 @@ export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
getState, getState,
"get", "get",
URLS.GET_MAIN_CATEGORY_SHOW_DETAIL, URLS.GET_MAIN_CATEGORY_SHOW_DETAIL,
{ patnrId, showId }, { patnrId, showId, curationId },
{}, {},
onSuccess, onSuccess,
onFail onFail

View File

@@ -33,9 +33,8 @@ export const getChatLog =
// VOD 자막 가져오기 IF-LGSP-072 // VOD 자막 가져오기 IF-LGSP-072
export const getSubTitle = export const getSubTitle =
({ patnrId, showId }) => ({ showSubtitleUrl }) =>
(dispatch, getState) => { (dispatch, getState) => {
console.log("#patnrId, showId ", patnrId, showId);
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getSubTitle onSuccess", response.data); console.log("getSubTitle onSuccess", response.data);
@@ -54,7 +53,7 @@ export const getSubTitle =
getState, getState,
"get", "get",
URLS.SUBTITLE, URLS.SUBTITLE,
{ patnrId, showId }, { showSubtitleUrl },
{}, {},
onSuccess, onSuccess,
onFail onFail

View File

@@ -81,6 +81,7 @@ export const URLS = {
SET_MAIN_LIVE_UPCOMING_ALARM: "/lgsp/v1/main/live/upcoming/alarm.lge", SET_MAIN_LIVE_UPCOMING_ALARM: "/lgsp/v1/main/live/upcoming/alarm.lge",
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "/lgsp/v1/main/live/show/nowproduct.lge", GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "/lgsp/v1/main/live/show/nowproduct.lge",
GET_MAIN_CATEGORY_SHOW_DETAIL: "/lgsp/v1/main/category/show/detail.lge", GET_MAIN_CATEGORY_SHOW_DETAIL: "/lgsp/v1/main/category/show/detail.lge",
GET_MAIN_LIVE_SHOW: "/lgsp/v1/main/live/show.lge",
//event controller //event controller
GET_WELCOME_EVENT_INFO: "/lgsp/v1/event/event.lge", GET_WELCOME_EVENT_INFO: "/lgsp/v1/event/event.lge",

View File

@@ -1,31 +1,38 @@
import React from "react"; import React from 'react';
import ReactDOM from "react-dom"; import ReactDOM from 'react-dom';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import onlyUpdateForKeys from "recompose/onlyUpdateForKeys"; import onlyUpdateForKeys from 'recompose/onlyUpdateForKeys';
import { off, on } from "@enact/core/dispatcher"; import {
import { forward } from "@enact/core/handle"; off,
import hoc from "@enact/core/hoc"; on,
import ApiDecorator from "@enact/core/internal/ApiDecorator"; } from '@enact/core/dispatcher';
import { is } from "@enact/core/keymap"; import { forward } from '@enact/core/handle';
import kind from "@enact/core/kind"; import hoc from '@enact/core/hoc';
import { Job } from "@enact/core/util"; import ApiDecorator from '@enact/core/internal/ApiDecorator';
import ActionGuide from "@enact/sandstone/ActionGuide"; import { is } from '@enact/core/keymap';
import Button from "@enact/sandstone/Button"; import kind from '@enact/core/kind';
import $L from "@enact/sandstone/internal/$L"; import { Job } from '@enact/core/util';
import { compareChildren } from "@enact/sandstone/internal/util"; import ActionGuide from '@enact/sandstone/ActionGuide';
import Spotlight from "@enact/spotlight"; import Button from '@enact/sandstone/Button';
import Pause from "@enact/spotlight/Pause"; import $L from '@enact/sandstone/internal/$L';
import { compareChildren } from '@enact/sandstone/internal/util';
import Spotlight from '@enact/spotlight';
import Pause from '@enact/spotlight/Pause';
import { import {
SpotlightContainerDecorator, SpotlightContainerDecorator,
spotlightDefaultClass, spotlightDefaultClass,
} from "@enact/spotlight/SpotlightContainerDecorator"; } from '@enact/spotlight/SpotlightContainerDecorator';
import Cancelable from "@enact/ui/Cancelable"; import Cancelable from '@enact/ui/Cancelable';
import Slottable from "@enact/ui/Slottable"; import Slottable from '@enact/ui/Slottable';
import css from "./MediaControls.module.less"; import ShopTimePlayIcon
import { countReactChildren } from "./util"; from '../../../assets/images/btn/btn-video-play-nor@3x.png';
import ShopTimePauseIcon
from '../../../assets/images/btn/btn-voc-pause-nor@3x.png';
import css from './MediaControls.module.less';
import { countReactChildren } from './util';
const OuterContainer = SpotlightContainerDecorator( const OuterContainer = SpotlightContainerDecorator(
{ {
@@ -353,7 +360,7 @@ const MediaControlsBase = kind({
backgroundOpacity="transparent" backgroundOpacity="transparent"
css={css} css={css}
disabled={mediaDisabled || playPauseButtonDisabled} disabled={mediaDisabled || playPauseButtonDisabled}
icon={paused ? playIcon : pauseIcon} icon={paused ? ShopTimePlayIcon : ShopTimePauseIcon}
onClick={onPlayButtonClick} onClick={onPlayButtonClick}
size="large" size="large"
spotlightDisabled={spotlightDisabled} spotlightDisabled={spotlightDisabled}

View File

@@ -3,67 +3,93 @@
@import "~@enact/sandstone/styles/skin.less"; @import "~@enact/sandstone/styles/skin.less";
.controlsFrame { .controlsFrame {
position: relative; position: relative;
display: block; display: block;
bottom: 142px;
left: 47px;
&.hidden { &.hidden {
will-change: opacity; will-change: opacity;
opacity: 0; opacity: 0;
} }
.mediaControls { .mediaControls {
text-align: center; > *:first-child {
direction: ltr; margin-inline-start: 0;
white-space: nowrap; }
}
> *:first-child { .actionGuide {
margin-inline-start: 0; padding-top: 39px;
} transition: opacity @sand-mediaplayer-controls-actionguide-time linear;
} &.hidden {
opacity: 0;
}
}
.actionGuide { .moreComponents {
padding-top: 39px; position: absolute;
transition: opacity @sand-mediaplayer-controls-actionguide-time linear; left: 0;
&.hidden { right: 0;
opacity: 0; height: 0px;
} opacity: 0;
}
.moreComponents { .moreButtonsComponents {
position: absolute; > * {
left: 0; margin: 0;
right: 0; margin-inline-start: 114px;
height: 0px;
opacity: 0;
.moreButtonsComponents { &:first-child {
> * { margin-inline-start: 0;
margin: 0; }
margin-inline-start: 114px; }
}
&:first-child { > :first-child {
margin-inline-start: 0; margin-top: 21px;
} }
} }
}
> :first-child { .button {
margin-top: 21px; height: 78px;
} width: 78px;
} margin: 0;
margin-inline-start: 45px;
padding: 0 !important;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
&:focus {
// border-radius:50%;
// > div:nth-child(1) {
// display: none;
.bg {
width: 78px;
height: 78px;
border-radius: 50%;
transform: none;
background-color: #c70850 !important;
opacity: 0.5;
filter: none !important;
-webkit-filter: none !important;
}
// }
}
.button { .client {
height: 90px; width: 60px;
min-width: 90px; height: 60px;
margin: 0; padding: 0;
margin-inline-start: 45px; display: inline-block;
vertical-align: top;
.client { line-height: 0;
padding: 0 9px; > div:nth-child(1) {
} width: 60px;
height: 60px;
.bg { background-size: 60px 60px;
border-radius: 48px; background-position: center center;
} }
} }
}
} }

View File

@@ -9,32 +9,38 @@
@sand-video-player-padding-side: 42px; @sand-video-player-padding-side: 42px;
.sliderFrame { .sliderFrame {
@knob-transform-active: @sand-translate-center scale(1); @knob-transform-active: @sand-translate-center scale(1);
@knob-transform-resting: @sand-translate-center scale(@sand-mediaplayer-slider-knob-resting-state-scale); @knob-transform-resting: @sand-translate-center
@slider-padding-v: ((@sand-mediaplayer-slider-tap-area - @sand-mediaplayer-slider-height) / 2); scale(@sand-mediaplayer-slider-knob-resting-state-scale);
@slider-padding-h: @sand-mediaplayer-slider-knob-size; @slider-padding-v: (
margin-left: 130px; (@sand-mediaplayer-slider-tap-area - @sand-mediaplayer-slider-height) / 2
margin-right: 130px; );
flex: 1 0 auto; @slider-padding-h: @sand-mediaplayer-slider-knob-size;
margin-left: 130px;
margin-right: 130px;
flex: 1 0 auto;
width: 1540px;
height: 6px;
&.hidden { &.hidden {
will-change: opacity; will-change: opacity;
opacity: 0; opacity: 0;
} }
.mediaSlider { .mediaSlider {
margin: 0 @slider-padding-h; margin: 0 @slider-padding-h;
padding: @slider-padding-v 0; padding: @slider-padding-v 0;
height: @sand-mediaplayer-slider-height; height: @sand-mediaplayer-slider-height;
// Add a tap area that extends to the edges of the screen, to make the slider more accessible right: 154px;
&::before { // Add a tap area that extends to the edges of the screen, to make the slider more accessible
content: ""; &::before {
position: absolute; content: "";
.position(0, -(@sand-video-player-padding-side)); position: absolute;
} .position(0, -(@sand-video-player-padding-side));
}
// Grow the knob when the Slider gets spotted // Grow the knob when the Slider gets spotted
.focus({ .focus({
&.active, &.active,
&.pressed { &.pressed {
.knob::before { .knob::before {
@@ -44,7 +50,7 @@
} }
}); });
.spottable({ .spottable({
&.pressed { &.pressed {
.knob::before { .knob::before {
transform: @knob-transform-active; transform: @knob-transform-active;
@@ -52,50 +58,50 @@
} }
} }
}); });
} }
// Knob // Knob
.knob { .knob {
@activate-transition-function: cubic-bezier(0.15, 0.85, 0.6, 1.65); @activate-transition-function: cubic-bezier(0.15, 0.85, 0.6, 1.65);
//@slide-transition-function: cubic-bezier(0.15, 0.85, 0.53, 1.09); //@slide-transition-function: cubic-bezier(0.15, 0.85, 0.53, 1.09);
//-webkit-transition: -webkit-transform @slide-transition-function 0.2s; //-webkit-transition: -webkit-transform @slide-transition-function 0.2s;
//transition: transform @slide-transition-function 0.2s; //transition: transform @slide-transition-function 0.2s;
&::before { &::before {
width: @sand-mediaplayer-slider-knob-size; width: @sand-mediaplayer-slider-knob-size;
height: @sand-mediaplayer-slider-knob-size; height: @sand-mediaplayer-slider-knob-size;
border-width: 0; border-width: 0;
border-radius: @sand-mediaplayer-slider-knob-size; border-radius: 50%;
transform: @knob-transform-resting; transform: @knob-transform-resting;
opacity: 0; // opacity: 0;
will-change: transform, opacity; will-change: transform, opacity;
-webkit-transition: -webkit-transform @activate-transition-function 0.2s, opacity ease 0.2s; -webkit-transition: -webkit-transform @activate-transition-function 0.2s,
transition: transform @activate-transition-function 0.2s, opacity ease 0.2s; opacity ease 0.2s;
} transition: transform @activate-transition-function 0.2s,
} opacity ease 0.2s;
}
&.scrubbing { }
.knob {
display: block;
}
}
} }
.applySkins({ .applySkins({
.sliderFrame { .sliderFrame {
.slider { .slider {
.bar { .bar {
background-color: @sand-mediaslider-bar-bg-color; background-color: #fff;
} }
.fill { .fill {
background-color: @sand-mediaslider-fill-bg-color; background-color: #c70850;
} }
.knob { .knob {
&::before { &::before {
background-color: @sand-mediaplayer-slider-knob-color; width: 24px;
height: 24px;
background-color: #fff;
} }
} }

View File

@@ -1,10 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import onlyUpdateForKeys from 'recompose/onlyUpdateForKeys'; import onlyUpdateForKeys from 'recompose/onlyUpdateForKeys';
import kind from '@enact/core/kind'; import kind from '@enact/core/kind';
import React from 'react';
import {secondsToPeriod, secondsToTime} from './util';
import css from './Times.module.less'; import css from './Times.module.less';
import {
secondsToPeriod,
secondsToTime,
} from './util';
/** /**
* Sandstone-styled formatted time component. * Sandstone-styled formatted time component.
@@ -15,98 +20,108 @@ import css from './Times.module.less';
* @public * @public
*/ */
const TimesBase = kind({ const TimesBase = kind({
name: 'Times', name: "Times",
propTypes: /** @lends sandstone/MediaPlayer.Times.prototype */ { propTypes: /** @lends sandstone/MediaPlayer.Times.prototype */ {
/** /**
* An instance of a Duration Formatter from i18n. * An instance of a Duration Formatter from i18n.
* *
* Must has a `format()` method that returns a string. * Must has a `format()` method that returns a string.
* *
* @type {Object} * @type {Object}
* @required * @required
* @public * @public
*/ */
formatter: PropTypes.object.isRequired, formatter: PropTypes.object.isRequired,
/** /**
* The current time in seconds of the video source. * The current time in seconds of the video source.
* *
* @type {Number} * @type {Number}
* @default 0 * @default 0
* @public * @public
*/ */
current: PropTypes.number, current: PropTypes.number,
/** /**
* Removes the current time. * Removes the current time.
* *
* @type {Boolean} * @type {Boolean}
* @public * @public
*/ */
noCurrentTime: PropTypes.bool, noCurrentTime: PropTypes.bool,
/** /**
* Removes the total time. * Removes the total time.
* *
* @type {Boolean} * @type {Boolean}
* @public * @public
*/ */
noTotalTime: PropTypes.bool, noTotalTime: PropTypes.bool,
/** /**
* The total time (duration) in seconds of the loaded video source. * The total time (duration) in seconds of the loaded video source.
* *
* @type {Number} * @type {Number}
* @default 0 * @default 0
* @public * @public
*/ */
total: PropTypes.number total: PropTypes.number,
}, },
defaultProps: { defaultProps: {
current: 0, current: 0,
total: 0 total: 0,
}, },
styles: { styles: {
css, css,
className: 'times' className: "times",
}, },
computed: { computed: {
currentPeriod: ({current}) => secondsToPeriod(current), currentPeriod: ({ current }) => secondsToPeriod(current),
currentReadable: ({current, formatter}) => secondsToTime(current, formatter), currentReadable: ({ current, formatter }) =>
noSeparator: ({noCurrentTime, noTotalTime}) => noCurrentTime || noTotalTime, secondsToTime(current, formatter),
totalPeriod: ({total}) => secondsToPeriod(total), noSeparator: ({ noCurrentTime, noTotalTime }) =>
totalReadable: ({total, formatter}) => secondsToTime(total, formatter) noCurrentTime || noTotalTime,
}, totalPeriod: ({ total }) => secondsToPeriod(total),
totalReadable: ({ total, formatter }) => secondsToTime(total, formatter),
},
render: ({currentPeriod, currentReadable, noCurrentTime, noSeparator, noTotalTime, totalPeriod, totalReadable, ...rest}) => { render: ({
delete rest.current; currentPeriod,
delete rest.formatter; currentReadable,
delete rest.total; noCurrentTime,
noSeparator,
noTotalTime,
totalPeriod,
totalReadable,
...rest
}) => {
delete rest.current;
delete rest.formatter;
delete rest.total;
return ( return (
<div {...rest}> <div {...rest}>
{noCurrentTime ? {noCurrentTime ? null : (
null : <time className={css.currentTime} dateTime={currentPeriod}>
<time className={css.currentTime} dateTime={currentPeriod}>{currentReadable}</time> {currentReadable} <span className={css.separator}>/</span>
} </time>
{noSeparator ? )}
null :
<span className={css.separator}>/</span> {noTotalTime ? null : (
} <time className={css.totalTime} dateTime={totalPeriod}>
{noTotalTime ? {totalReadable}
null : </time>
<time className={css.totalTime} dateTime={totalPeriod}>{totalReadable}</time> )}
} </div>
</div> );
); },
}
}); });
const Times = onlyUpdateForKeys(['current', 'formatter', 'total'])(TimesBase); const Times = onlyUpdateForKeys(["current", "formatter", "total"])(TimesBase);
export default Times; export default Times;
export {Times, TimesBase}; export { Times, TimesBase };

View File

@@ -4,25 +4,32 @@
@import "~@enact/sandstone/styles/mixins.less"; @import "~@enact/sandstone/styles/mixins.less";
.times { .times {
position: absolute; position: absolute;
font-family: "LG SmartFont SemiBold"; font-family: "LGSmartUI";
width: 100%; width: 100%;
top: 19px; top: 22px;
font-size: 30px; font-size: 24px;
font-weight: bold; font-weight: bold;
letter-spacing: -1.4px; line-height: 30px;
line-height: 30px; white-space: nowrap;
white-space: nowrap; text-align: right;
letter-spacing: 1.2px;
> * { .currentTime {
display: inline-block; // width: 225px;
} padding-right: 140px;
}
> * {
display: inline-block;
}
.separator { .separator {
padding: 0 1ex; position: absolute;
} top: 0;
right: 116px;
}
.enact-locale-rtl({ .enact-locale-rtl({
direction: ltr; direction: ltr;
}); });
} }

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
// MediaPlayer utils.js // MediaPlayer utils.js
// //
@@ -12,15 +13,15 @@ import React from 'react';
* @private * @private
*/ */
const parseTime = (value) => { const parseTime = (value) => {
value = parseFloat(value); value = parseFloat(value);
const time = {}; const time = {};
const hour = Math.floor(value / (60 * 60)); const hour = Math.floor(value / (60 * 60));
time.minute = Math.floor((value / 60) % 60); time.minute = Math.floor((value / 60) % 60);
time.second = Math.floor(value % 60); time.second = Math.floor(value % 60);
if (hour) { if (hour) {
time.hour = hour; time.hour = hour;
} }
return time; return time;
}; };
/** /**
@@ -32,7 +33,7 @@ const parseTime = (value) => {
* @private * @private
*/ */
const secondsToPeriod = (seconds) => { const secondsToPeriod = (seconds) => {
return 'P' + seconds + 'S'; return "P" + seconds + "S";
}; };
/** /**
@@ -49,20 +50,20 @@ const secondsToPeriod = (seconds) => {
* @public * @public
*/ */
const secondsToTime = (seconds, durfmt, config) => { const secondsToTime = (seconds, durfmt, config) => {
const includeHour = config && config.includeHour; const includeHour = config && config.includeHour;
if (durfmt) { if (durfmt) {
const parsedTime = parseTime(seconds); const parsedTime = parseTime(seconds);
const timeString = durfmt.format(parsedTime).toString(); const timeString = durfmt.format(parsedTime).toString();
if (includeHour && !parsedTime.hour) { if (includeHour && !parsedTime.hour) {
return '00:' + timeString; return "00:" + timeString;
} else { } else {
return timeString; return "00:" + timeString;
} }
} }
// includeHour ? '00:00:00' : '00:00';
return includeHour ? '00:00:00' : '00:00'; return includeHour ? "00:00:00" : "00:00:00";
}; };
/** /**
@@ -73,11 +74,7 @@ const secondsToTime = (seconds, durfmt, config) => {
* @returns {Number} Number of children nodes * @returns {Number} Number of children nodes
* @private * @private
*/ */
const countReactChildren = (children) => React.Children.toArray(children).filter(n => n != null).length; const countReactChildren = (children) =>
React.Children.toArray(children).filter((n) => n != null).length;
export { export { countReactChildren, parseTime, secondsToPeriod, secondsToTime };
countReactChildren,
parseTime,
secondsToPeriod,
secondsToTime
};

View File

@@ -7,14 +7,17 @@
* @exports VideoPlayerBase * @exports VideoPlayerBase
*/ */
import React from "react"; import React from 'react';
import ReactDOM from "react-dom"; import ReactDOM from 'react-dom';
import DurationFmt from "ilib/lib/DurationFmt"; import DurationFmt from 'ilib/lib/DurationFmt';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import shallowEqual from "recompose/shallowEqual"; import shallowEqual from 'recompose/shallowEqual';
import { off, on } from "@enact/core/dispatcher"; import {
off,
on,
} from '@enact/core/dispatcher';
import { import {
adaptEvent, adaptEvent,
call, call,
@@ -25,43 +28,56 @@ import {
preventDefault, preventDefault,
returnsTrue, returnsTrue,
stopImmediate, stopImmediate,
} from "@enact/core/handle"; } from '@enact/core/handle';
import ApiDecorator from "@enact/core/internal/ApiDecorator"; import ApiDecorator from '@enact/core/internal/ApiDecorator';
import EnactPropTypes from "@enact/core/internal/prop-types"; import EnactPropTypes from '@enact/core/internal/prop-types';
import { is } from "@enact/core/keymap"; import { is } from '@enact/core/keymap';
import { platform } from "@enact/core/platform"; import { platform } from '@enact/core/platform';
import { Job, memoize, perfNow } from "@enact/core/util"; import {
import { I18nContextDecorator } from "@enact/i18n/I18nDecorator"; Job,
import { toUpperCase } from "@enact/i18n/util"; memoize,
import Skinnable from "@enact/sandstone/Skinnable"; perfNow,
import { getDirection, Spotlight } from "@enact/spotlight"; } from '@enact/core/util';
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator"; import { I18nContextDecorator } from '@enact/i18n/I18nDecorator';
import { Spottable } from "@enact/spotlight/Spottable"; import { toUpperCase } from '@enact/i18n/util';
import Announce from "@enact/ui/AnnounceDecorator/Announce"; import Skinnable from '@enact/sandstone/Skinnable';
import ComponentOverride from "@enact/ui/ComponentOverride"; import {
import { FloatingLayerDecorator } from "@enact/ui/FloatingLayer"; getDirection,
import { FloatingLayerContext } from "@enact/ui/FloatingLayer/FloatingLayerDecorator"; Spotlight,
import Media from "@enact/ui/Media"; } from '@enact/spotlight';
import Slottable from "@enact/ui/Slottable"; import {
import Touchable from "@enact/ui/Touchable"; SpotlightContainerDecorator,
} from '@enact/spotlight/SpotlightContainerDecorator';
import { Spottable } from '@enact/spotlight/Spottable';
import Announce from '@enact/ui/AnnounceDecorator/Announce';
import ComponentOverride from '@enact/ui/ComponentOverride';
import { FloatingLayerDecorator } from '@enact/ui/FloatingLayer';
import {
FloatingLayerContext,
} from '@enact/ui/FloatingLayer/FloatingLayerDecorator';
import Media from '@enact/ui/Media';
import Slottable from '@enact/ui/Slottable';
import Touchable from '@enact/ui/Touchable';
import * as Config from "../../utils/Config"; import * as Config from '../../utils/Config';
import { $L } from "../../utils/helperMethods"; import { $L } from '../../utils/helperMethods';
//import SpotlightIds from '../../utils/SpotlightIds'; //import SpotlightIds from '../../utils/SpotlightIds';
import { SpotlightIds } from "../../utils/SpotlightIds"; import { SpotlightIds } from '../../utils/SpotlightIds';
import PlayerOverlayHeader
from '../../views/PlayerPanel/PlayerOverlay/PlayerOverlayHeader';
import { import {
MediaControls, MediaControls,
MediaSlider, MediaSlider,
secondsToTime, secondsToTime,
Times, Times,
} from "../MediaPlayer"; } from '../MediaPlayer';
import TPlayerFeedBackBtn from "../TPlayerFeedBackBtn"; import TPlayerFeedBackBtn from '../TPlayerFeedBackBtn';
import FeedbackContent from "./FeedbackContent"; import FeedbackContent from './FeedbackContent';
import FeedbackTooltip from "./FeedbackTooltip"; import FeedbackTooltip from './FeedbackTooltip';
import MediaTitle from "./MediaTitle"; import MediaTitle from './MediaTitle';
import Overlay from "./Overlay"; import Overlay from './Overlay';
import Video from "./Video"; import Video from './Video';
import css from "./VideoPlayer.module.less"; import css from './VideoPlayer.module.less';
const isEnter = is("enter"); const isEnter = is("enter");
const isLeft = is("left"); const isLeft = is("left");
@@ -2027,6 +2043,7 @@ const VideoPlayerBase = class extends React.Component {
no5WayJump, no5WayJump,
noAutoPlay, noAutoPlay,
noMiniFeedback, noMiniFeedback,
playListInfo,
noSlider, noSlider,
noSpinner, noSpinner,
selection, selection,
@@ -2041,6 +2058,8 @@ const VideoPlayerBase = class extends React.Component {
onIntroDisabled, onIntroDisabled,
videoComponent: VideoComponent, videoComponent: VideoComponent,
cameraSettingsButton, cameraSettingsButton,
onBackButton,
panelInfo,
...mediaProps ...mediaProps
} = this.props; } = this.props;
@@ -2134,23 +2153,11 @@ const VideoPlayerBase = class extends React.Component {
(this.state.infoVisible ? " " + css.lift : "") (this.state.infoVisible ? " " + css.lift : "")
} }
> >
{/* <TPlayerFeedBackBtn <PlayerOverlayHeader
spotlightId={"jumpleft"} playListInfo={playListInfo}
onClick={this.onClickLeftJump} onClick={onBackButton}
onSpotlightRight={this.SpotToRight} panelInfo={panelInfo}
onSpotlightDown={this.SpotToTitle} />
>
{$L("10 sec")}
</TPlayerFeedBackBtn>
<TPlayerFeedBackBtn
type={"right"}
spotlightId={"jumpright"}
onClick={this.onClickRightJump}
onSpotlightLeft={this.SpotToLeft}
onSpotlightDown={this.SpotToTitle2}
>
{$L("10 sec")}
</TPlayerFeedBackBtn> */}
</div> </div>
)} )}
</Overlay> </Overlay>
@@ -2205,13 +2212,13 @@ const VideoPlayerBase = class extends React.Component {
> >
{infoComponents} {infoComponents}
</MediaTitle> </MediaTitle>
{noSlider ? ( {/* {noSlider ? (
<Times <Times
current={this.state.currentTime} current={this.state.currentTime}
total={this.state.duration} total={this.state.duration}
formatter={durFmt} formatter={durFmt}
/> />
) : null} ) : null} */}
</div> </div>
) : null} ) : null}
{noSlider ? null : ( {noSlider ? null : (
@@ -2223,6 +2230,7 @@ const VideoPlayerBase = class extends React.Component {
formatter={durFmt} formatter={durFmt}
/> />
) : null} ) : null}
{this.state.mediaSliderVisible ? ( {this.state.mediaSliderVisible ? (
<Times <Times
noTotalTime noTotalTime

View File

@@ -68,7 +68,7 @@
.controlFeedbackBtnLayer { .controlFeedbackBtnLayer {
position: absolute; position: absolute;
z-index: 50; z-index: 50;
top: 506px; top: 0;
left: 0; left: 0;
padding: 0; padding: 0;
width: 100%; width: 100%;
@@ -95,7 +95,7 @@
.bottom { .bottom {
position: absolute; position: absolute;
z-index: 100; // Value assigned as part of the VideoPlayer API so layers may be inserted in-between z-index: 100; // Value assigned as part of the VideoPlayer API so layers may be inserted in-between
bottom: 10px; bottom: -18px;
left: 0; left: 0;
right: 0; right: 0;
// left: @sand-video-player-padding-side; // left: @sand-video-player-padding-side;
@@ -125,8 +125,8 @@
// display: flex; // display: flex;
position: relative; position: relative;
align-items: center; align-items: center;
margin-left: 90px; margin-left: 60px;
margin-right: 90px; margin-right: 59px;
height: 70px; height: 70px;
> *:first-child { > *:first-child {
text-align: right; text-align: right;

View File

@@ -87,6 +87,13 @@ export const mainReducer = (state = initialState, action) => {
}; };
} }
case types.GET_MAIN_LIVE_SHOW: {
return {
...state,
liveShowInfos: action.payload.showInfos,
};
}
default: default:
return state; return state;
} }

View File

@@ -1,15 +1,16 @@
import React, { useCallback } from "react"; import React, { useCallback } from 'react';
import classNames from "classnames"; import classNames from 'classnames';
import { useDispatch } from "react-redux"; import { useDispatch } from 'react-redux';
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator
import Spottable from "@enact/spotlight/Spottable"; from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import { pushPanel } from "../../../../actions/panelActions"; import { pushPanel } from '../../../../actions/panelActions';
import TVideoPlayer from "../../../../components/TVideoPlayer/TVideoPlayer"; import TVideoPlayer from '../../../../components/TVideoPlayer/TVideoPlayer';
import { panel_names } from "../../../../utils/Config"; import { panel_names } from '../../../../utils/Config';
import css from "./TCFV_3.module.less"; import css from './TCFV_3.module.less';
const SpottableComponent = Spottable("li"); const SpottableComponent = Spottable("li");
const SpottableComponentDiv = Spottable("div"); const SpottableComponentDiv = Spottable("div");
@@ -65,7 +66,7 @@ export default function TCFV_3({
dispatch( dispatch(
pushPanel({ pushPanel({
name: panel_names.PLAYER_PANEL, name: panel_names.PLAYER_PANEL,
playInfo: { panelInfo: {
patnrId: data[0].patnrId, patnrId: data[0].patnrId,
showId: data[0].showId, showId: data[0].showId,
shptmBanrTpNm: "VOD", shptmBanrTpNm: "VOD",
@@ -137,7 +138,6 @@ export default function TCFV_3({
showUrl={showUrl} showUrl={showUrl}
width={1400} width={1400}
height={630} height={630}
videoIsPlaying={false}
thumbNail={bgImgPath} thumbNail={bgImgPath}
className={css.video} className={css.video}
videoIsPlaying videoIsPlaying

View File

@@ -14,6 +14,7 @@ export default function PlayerOverlayHeader({
selectedIndex, selectedIndex,
onClick, onClick,
}) { }) {
console.log("#playListInfo", playListInfo);
const onClickBack = () => { const onClickBack = () => {
if (onClick) { if (onClick) {
onClick(); onClick();
@@ -29,7 +30,7 @@ export default function PlayerOverlayHeader({
<img <img
src={ src={
playListInfo playListInfo
? playListInfo[selectedIndex]?.patncLogoPath ? playListInfo?.patncLogoPath
: panelInfo?.patncLogoPath : panelInfo?.patncLogoPath
} }
alt="" alt=""
@@ -38,14 +39,10 @@ export default function PlayerOverlayHeader({
<> <>
<h2 className={css.patnerName}> <h2 className={css.patnerName}>
{playListInfo {playListInfo ? playListInfo?.patncNm : panelInfo?.patncNm}
? playListInfo[selectedIndex]?.patncNm
: panelInfo?.patncNm}
</h2> </h2>
<h3 className={css.title}> <h3 className={css.title}>
{playListInfo {playListInfo ? playListInfo?.showNm : panelInfo?.showNm}
? playListInfo[selectedIndex]?.showNm
: panelInfo?.showNm}
</h3> </h3>
</> </>
</div> </div>

View File

@@ -3,7 +3,7 @@
.overIcon { .overIcon {
position: absolute; position: absolute;
z-index: 2; z-index: 3;
&.backLiveicon { &.backLiveicon {
display: flex; display: flex;

View File

@@ -2,6 +2,7 @@ import React, {
useCallback, useCallback,
useEffect, useEffect,
useMemo, useMemo,
useRef,
useState, useState,
} from 'react'; } from 'react';
@@ -18,14 +19,19 @@ import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator'; from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable'; import Spottable from '@enact/spotlight/Spottable';
import playButton from '../../../assets/images/btn/btn-video-play-nor@3x.png';
import * as CommonActions from '../../actions/commonActions'; import * as CommonActions from '../../actions/commonActions';
import { import {
getHomeFullVideoInfo, getHomeFullVideoInfo,
getMainCategoryShowDetail, getMainCategoryShowDetail,
getMainLiveShow,
getMainLiveShowNowProduct, getMainLiveShowNowProduct,
} from '../../actions/mainActions'; } from '../../actions/mainActions';
import * as PanelActions from '../../actions/panelActions'; import * as PanelActions from '../../actions/panelActions';
import { getChatLog } from '../../actions/playActions'; import {
getChatLog,
getSubTitle,
} from '../../actions/playActions';
import { MediaControls } from '../../components/MediaPlayer'; import { MediaControls } from '../../components/MediaPlayer';
import TButton from '../../components/TButton/TButton'; import TButton from '../../components/TButton/TButton';
import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab'; import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab';
@@ -55,32 +61,33 @@ const unableToPlay = new Job((callback) => {
const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => { const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const videoPlayer = useRef(null);
const [playListInfo, setPlayListInfo] = useState(""); const [playListInfo, setPlayListInfo] = useState("");
const [shopNowInfo, setShopNowInfo] = useState(); const [shopNowInfo, setShopNowInfo] = useState();
const [panelInfo, setPaneInfo] = useState([]); const [panelInfo, setPaneInfo] = useState([]);
const [tab, setTab] = useState(0); const [tab, setTab] = useState(0);
const [isPlay, setIsPlay] = useState(false);
const [sideOpen, setSideOpen] = useState(true); const [sideOpen, setSideOpen] = useState(true);
const [selectedIndex, setSelectedIndex] = useState(0); const [selectedIndex, setSelectedIndex] = useState(0);
const [isHide, setIsHide] = useState(true); const [isHide, setIsHide] = useState(true);
const panels = useSelector((state) => state.panels.panels); const panels = useSelector((state) => state.panels.panels);
const chatData = useSelector((state) => state.play.chatData); const chatData = useSelector((state) => state.play.chatData);
//VOD const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
const showDetailInfo = useSelector((state) => state.main.showDetailInfo); const showDetailInfo = useSelector((state) => state.main.showDetailInfo);
const featuredShowsInfos = useSelector( const featuredShowsInfos = useSelector(
(state) => state.main.featuredShowsInfos (state) => state.main.featuredShowsInfos
); );
//라이브
const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos); const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos);
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 tabList = [ const tabList = [
$L("SHOP NOW"), $L("SHOP NOW"),
$L(panelInfo?.shptmBanrTpNm === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"), $L(panelInfo?.shptmBanrTpNm === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
]; ];
console.log("#showDetailInfo", showDetailInfo);
// 패널 정보 받기 // 패널 정보 받기
const getPanelInfo = useCallback(() => { const getPanelInfo = useCallback(() => {
if (panels) { if (panels) {
@@ -94,6 +101,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
const onClickBack = useCallback( const onClickBack = useCallback(
(ev) => { (ev) => {
console.log("#####################");
dispatch(PanelActions.popPanel()); dispatch(PanelActions.popPanel());
}, },
[dispatch] [dispatch]
@@ -117,17 +125,24 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
setSideOpen((prev) => !prev); setSideOpen((prev) => !prev);
}; };
const backButton = useCallback(() => { const getPlayer = useCallback((ref) => {
return ( videoPlayer.current = ref;
<TButton console.log("#getPlayer ", ref);
className={css.backBtn} }, []);
spotlightId={"BACK_BUTTON"}
onClick={onClickBack} // const onPlay = useCallback(() => {
onSpotlightDown={SpotToSlider} // setIsPlay((prev) => !prev);
size={"small"} // videoPlayer.current.play();
/> // }, [isPlay]);
); // const playButton = useCallback(() => {
}, [onClickBack, SpotToSlider]); // console.log("#isPlay", isPlay);
// return (
// <SpottableBtn
// className={classNames(isPlay ? css.pauseButton : css.playButton)}
// onClick={onPlay}
// ></SpottableBtn>
// );
// }, [onPlay, isPlay]);
const isActive = useMemo(() => { const isActive = useMemo(() => {
return playListInfo; return playListInfo;
@@ -150,7 +165,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
} }
setSelectedIndex((prev) => prev + 1); setSelectedIndex((prev) => prev + 1);
}; };
console.log("#playListInfo", playListInfo);
const addPanelInfoToPlayList = (featuredShowsInfos) => { const addPanelInfoToPlayList = (featuredShowsInfos) => {
const updatedPlayListInfo = [ const updatedPlayListInfo = [
{ ...showDetailInfo[0] }, { ...showDetailInfo[0] },
@@ -169,6 +184,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
getMainCategoryShowDetail({ getMainCategoryShowDetail({
patnrId: panelInfo.patnrId, patnrId: panelInfo.patnrId,
showId: panelInfo.showId, showId: panelInfo.showId,
curationId: panelInfo.curationId,
}) })
); );
@@ -187,9 +203,18 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
dispatch( dispatch(
getChatLog({ patnrId: panelInfo.patnrId, showId: panelInfo.showId }) getChatLog({ patnrId: panelInfo.patnrId, showId: panelInfo.showId })
); );
dispatch(getMainLiveShow());
} }
}, [dispatch, panelInfo, selectedIndex]); }, [dispatch, panelInfo, selectedIndex]);
useEffect(() => {
if (playListInfo && playListInfo.length > 0) {
dispatch(
getSubTitle({ showSubtitleUrl: playListInfo[0].showSubtitlUrl })
);
}
}, [dispatch, playListInfo]);
// 10초후 탭 닫기 // 10초후 탭 닫기
useEffect(() => { useEffect(() => {
let timer = setTimeout(() => { let timer = setTimeout(() => {
@@ -223,7 +248,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
setShopNowInfo(showDetailInfo[0].productInfos); setShopNowInfo(showDetailInfo[0].productInfos);
} }
if (panelInfo?.shptmBanrTpNm === "LIVE") { if (panelInfo?.shptmBanrTpNm === "LIVE") {
setPlayListInfo(liveChannelInfos); setPlayListInfo(liveChannelInfos ? liveChannelInfos : liveShowInfos);
setShopNowInfo(showNowProduct); setShopNowInfo(showNowProduct);
} }
}, [panelInfo, showDetailInfo, liveChannelInfos, showNowProduct, dispatch]); }, [panelInfo, showDetailInfo, liveChannelInfos, showNowProduct, dispatch]);
@@ -265,18 +290,17 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
delete props.panelInfo; delete props.panelInfo;
// console.log("#showUrl", playListInfo[selectedIndex]);
//TAB
return ( return (
<TPanel isTabActivated={false} {...props} className={css.videoContainer}> <TPanel isTabActivated={false} {...props} className={css.videoContainer}>
{typeof window !== "object" ? ( {typeof window !== "object" ? (
<VideoPlayer <VideoPlayer
className={css.backBtn} setApiProvider={getPlayer}
onEnded={onClickBack} // 플레이어가 끝날때 호출 onEnded={onClickBack} // 플레이어가 끝날때 호출
title={"동영상 타이틀 테스트 테스트"} // 동영상 플레이어
noAutoPlay={false} // 오토플레이 noAutoPlay={false} // 오토플레이
backButton={backButton()} // 뒤로가기 버튼 autoCloseTimeout={100000000000000} // 컨트롤 버튼 숨기는 시간
playListInfo={playListInfo && playListInfo[selectedIndex]} // 비디오 데이터
onBackButton={onClickBack} // 뒤로가기 버튼
panelInfo={panelInfo} // 패널정보 (라이브,VOD)
> >
<source <source
src={ src={
@@ -287,7 +311,13 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
type="type=application/mpegurl" type="type=application/mpegurl"
/> />
<MediaControls></MediaControls> {/* 테스트 */}
{/* <source
src={
" https://d130labfjte6iy.cloudfront.net/vod/1e62b39b-4301-4fe5-a16e-bebebef4e1c6/3e72500af7fc4d9d800e7a9533a29a36.mp4"
}
type="video/mp4"
/> */}
</VideoPlayer> </VideoPlayer>
) : ( ) : (
<ReactPlayer <ReactPlayer
@@ -305,16 +335,20 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
onEnded={onClickBack} // 플레이어가 끝날때 호출 onEnded={onClickBack} // 플레이어가 끝날때 호출
/> />
)} )}
{/* 백버튼, 로고 , 타이틀 */} {/* 리액트 플레이어 테스트용 */}
{isHide && ( {typeof window !== "object" ? (
""
) : (
<PlayerOverlayHeader <PlayerOverlayHeader
selectedIndex={selectedIndex} selectedIndex={selectedIndex}
panelInfo={panelInfo} panelInfo={panelInfo}
playListInfo={playListInfo} playListInfo={playListInfo && playListInfo[selectedIndex]}
onClick={onClickBack} onClick={onClickBack}
/> />
)} )}
<div>
<SpottableBtn className={css.videoReduce} onClick={onClickBack} />
</div>
{/* 인디게이터 버튼 */} {/* 인디게이터 버튼 */}
<div className={classNames(css.overIcon, css.topIcon)}> <div className={classNames(css.overIcon, css.topIcon)}>
<SpottableBtn onClick={handleUpClick} /> <SpottableBtn onClick={handleUpClick} />
@@ -363,11 +397,14 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
/> />
)} )}
{panelInfo?.shptmBanrTpNm === "LIVE" && tab === 1 && ( {panelInfo?.shptmBanrTpNm === "LIVE" && tab === 1 && (
<LiveChannelContents /> <LiveChannelContents
setSelectedIndex={setSelectedIndex}
liveInfos={playListInfo}
/>
)} )}
{shopNowInfo !== "undefined" && {shopNowInfo !== "undefined" &&
shopNowInfo && youmaylikeInfos &&
shopNowInfo.length < 3 && shopNowInfo.length < 3 &&
tab === 0 && <YouMayLikeContents shopNowInfo={shopNowInfo} />} tab === 0 && <YouMayLikeContents shopNowInfo={shopNowInfo} />}
</Container> </Container>

View File

@@ -1,8 +1,34 @@
@import "../../style/CommonStyle.module.less"; @import "../../style/CommonStyle.module.less";
@import "../../style/utils.module.less"; @import "../../style/utils.module.less";
.videoContainer { .videoContainer {
position: relative; position: relative;
.playButton {
.size(@w: 60px, @h: 60px);
background-image: url("../../../assets/images/btn/btn-video-play-nor@3x.png");
background-size: cover;
&:focus {
.size(@w: 60px, @h: 60px);
border-radius: 50%;
background-color: #c70850;
opacity: 0.5;
}
}
.pauseButton {
.size(@w: 60px, @h: 60px);
background-image: url("../../../assets/images/btn/btn-voc-pause-nor@3x.png");
background-size: cover;
&:focus {
.size(@w: 60px, @h: 60px);
border-radius: 50%;
background-color: #c70850;
opacity: 0.5;
}
}
.toOpenBtn { .toOpenBtn {
.size(@w: 147px, @h: 243px); .size(@w: 147px, @h: 243px);
min-width: 60px !important; min-width: 60px !important;
@@ -49,7 +75,7 @@
} }
} }
.tabContainer { .tabContainer {
.size(@w:660px, 100%); .size(@w:660px, @h:100%);
background: #2c343f; background: #2c343f;
position: absolute; position: absolute;
right: 0; right: 0;
@@ -75,6 +101,15 @@
bottom: 210px; bottom: 210px;
left: 60px; left: 60px;
} }
.videoReduce {
.size(@w:60px, @h:60px);
background-image: url("../../../assets/images/btn/btn-video-min-nor@3x.png");
background-size: cover;
position: absolute;
right: 60px;
bottom: 150px;
z-index: 100;
}
.overIcon { .overIcon {
position: absolute; position: absolute;

View File

@@ -1,20 +1,25 @@
import React, { useCallback, useEffect, useState } from "react"; import React, {
useCallback,
useEffect,
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 TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList
import { panel_names } from "../../../utils/Config"; from '../../../components/TVirtualGridList/TVirtualGridList';
import PlayerItemCard, { TYPES } from "../PlayerItemCard/PlayerItemCard"; import { panel_names } from '../../../utils/Config';
import css from "./LiveChannelContents.module.less"; import PlayerItemCard, { TYPES } from '../PlayerItemCard/PlayerItemCard';
import PlayerTabLoading from "./PlayerTabLoading"; import css from './LiveChannelContents.module.less';
import PlayerTabLoading from './PlayerTabLoading';
export default function LiveChannelContents() { export default function LiveChannelContents({ liveInfos }) {
const dispatch = useDispatch();
const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos); const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos);
console.log("#liveChannelInfos", liveChannelInfos);
const renderItem = useCallback( const renderItem = useCallback(
({ index, ...rest }) => { ({ index, ...rest }) => {
const { const {
@@ -26,9 +31,11 @@ export default function LiveChannelContents() {
strtDt, strtDt,
endDt, endDt,
timezone, timezone,
} = liveChannelInfos[index]; } = liveInfos[index];
const handleItemClick = () => {}; const handleItemClick = () => {
setSelectedIndex(index);
};
return ( return (
<PlayerItemCard <PlayerItemCard
@@ -47,14 +54,14 @@ export default function LiveChannelContents() {
/> />
); );
}, },
[liveChannelInfos] [liveInfos]
); );
return ( return (
<> <>
<div className={css.container}> <div className={css.container}>
{liveChannelInfos && liveChannelInfos.length > 0 ? ( {liveInfos && liveInfos.length > 0 ? (
<TVirtualGridList <TVirtualGridList
dataSize={liveChannelInfos.length} dataSize={liveInfos.length}
direction="vertical" direction="vertical"
renderItem={renderItem} renderItem={renderItem}
itemWidth={600} itemWidth={600}

View File

@@ -10,7 +10,10 @@ import {
useSelector, useSelector,
} from 'react-redux'; } from 'react-redux';
import { pushPanel } 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 import TVirtualGridList
from '../../../components/TVirtualGridList/TVirtualGridList'; from '../../../components/TVirtualGridList/TVirtualGridList';

View File

@@ -23,7 +23,6 @@ export default function YouMayLikeContents({ shopNowInfo }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [height, setHeight] = useState(236); const [height, setHeight] = useState(236);
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos); const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
const showNowProduct = useSelector((state) => state.main.showNowProduct);
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]); const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);