video caption track
This commit is contained in:
@@ -79,3 +79,7 @@ SubCategory.jsx 참고(Home)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# 자막영상
|
||||
|
||||
ontv4u 검색 후 첫 영상
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
changeAppStatus,
|
||||
getDeviceId,
|
||||
getHttpHeaderForServiceRequest,
|
||||
getSystemSettings,
|
||||
} from "../actions/commonActions";
|
||||
import { getAuthenticationCode } from "../actions/deviceActions";
|
||||
import {
|
||||
@@ -131,10 +132,7 @@ function AppBase(props) {
|
||||
}
|
||||
dispatch(getDeviceId());
|
||||
dispatch(getHttpHeaderForServiceRequest());
|
||||
//todo subscribe
|
||||
// dispatch(getSystemSettings());
|
||||
// //get captionEnable
|
||||
// dispatch(getSystemSettings2());
|
||||
dispatch(getSystemSettings());
|
||||
// dispatch(getSystemInfo());
|
||||
document.addEventListener("visibilitychange", visibilityChanged);
|
||||
document.addEventListener("webOSRelaunch", handleRelaunchEvent);
|
||||
|
||||
@@ -57,6 +57,26 @@ export const alertToast = (payload) => (dispatch, getState) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getSystemSettings =
|
||||
() => (dispatch, getState) => {
|
||||
console.log("getSystemSettings ");
|
||||
lunaSend.getSystemSettings({"category":"caption", "keys": ["captionEnable"]},{
|
||||
onSuccess: (res) => {
|
||||
},
|
||||
onFailure: (err) => {
|
||||
|
||||
},
|
||||
onComplete: (res) => {
|
||||
console.log("getSystemSettings onComplete",res);
|
||||
if(res && res.settings){
|
||||
if(typeof res.settings.captionEnable !== 'undefined'){
|
||||
dispatch(changeAppStatus({captionEnable: res.settings.captionEnable}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getHttpHeaderForServiceRequest =
|
||||
(onComplete) => (dispatch, getState) => {
|
||||
console.log("getHttpHeaderForServiceRequest ");
|
||||
|
||||
@@ -99,14 +99,19 @@ export const getSubTitle =
|
||||
|
||||
dispatch({
|
||||
type: types.GET_SUBTITLE,
|
||||
payload: response.data.data,
|
||||
payload: {url: showSubtitleUrl, data: response.data.data},
|
||||
});
|
||||
};
|
||||
|
||||
const onFail = (error) => {
|
||||
console.error("getSubTitle onFail", error);
|
||||
dispatch({
|
||||
type: types.GET_SUBTITLE,
|
||||
payload: {url: showSubtitleUrl, data: "Error"},
|
||||
});
|
||||
};
|
||||
|
||||
if(!getState().play.subTitleBlobs[showSubtitleUrl]){
|
||||
TAxios(
|
||||
dispatch,
|
||||
getState,
|
||||
@@ -117,4 +122,8 @@ export const getSubTitle =
|
||||
onSuccess,
|
||||
onFail
|
||||
);
|
||||
}else{
|
||||
console.log("playActions getSubTitle no Nothing it's exist", showSubtitleUrl);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
391
com.twin.app.shoptime/src/components/VideoPlayer/Media.js
Normal file
391
com.twin.app.shoptime/src/components/VideoPlayer/Media.js
Normal file
@@ -0,0 +1,391 @@
|
||||
"use strict";
|
||||
/* eslint-disable */
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Media = exports.handledMediaEventsMap = exports.getKeyFromSource = exports["default"] = void 0;
|
||||
|
||||
var _dispatcher = require("@enact/core/dispatcher");
|
||||
|
||||
var _handle = require("@enact/core/handle");
|
||||
|
||||
var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));
|
||||
|
||||
var _propTypes2 = _interopRequireDefault(require("prop-types"));
|
||||
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||||
|
||||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
||||
|
||||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||||
|
||||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||||
|
||||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
||||
|
||||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
||||
|
||||
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
||||
|
||||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
||||
|
||||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
||||
|
||||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
||||
|
||||
/**
|
||||
* Generates a key representing the source node or nodes provided
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* getKeyFromSource('path/file.mp4'); // 'path/file.mp4'
|
||||
* getKeyFromSource(
|
||||
* <source src="path/file.mp4" type="video/mp4" />
|
||||
* ); // 'path/file.mp4'
|
||||
* getKeyFromSource([
|
||||
* <source src="path/file.mp4" type="video/mp4" />,
|
||||
* <source src="path/file.ogg" type="video/ogg" />,
|
||||
* ]); // 'path/file.mp4+path/file.ogg'
|
||||
* ```
|
||||
*
|
||||
* @function
|
||||
* @param {String|Element|Element[]} source URI for a source, `<source>` node, or array of
|
||||
* `<source>` nodes
|
||||
* @returns {String} Key representing sources
|
||||
* @memberof ui/Media
|
||||
* @public
|
||||
*/
|
||||
var getKeyFromSource = function getKeyFromSource() {
|
||||
var source = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
|
||||
if ( /*#__PURE__*/_react["default"].isValidElement(source)) {
|
||||
return _react["default"].Children.toArray(source).filter(function (s) {
|
||||
return !!s;
|
||||
}).map(function (s) {
|
||||
return s.props.src;
|
||||
}).join('+');
|
||||
}
|
||||
|
||||
return String(source);
|
||||
};
|
||||
/**
|
||||
* Maps standard media event `type` values to React-style callback prop names
|
||||
*
|
||||
* See https://reactjs.org/docs/events.html#media-events
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* abort : 'onAbort',
|
||||
* canplay : 'onCanPlay',
|
||||
* canplaythrough : 'onCanPlayThrough',
|
||||
* durationchange : 'onDurationChange',
|
||||
* emptied : 'onEmptied',
|
||||
* encrypted : 'onEncrypted',
|
||||
* ended : 'onEnded',
|
||||
* error : 'onError',
|
||||
* loadeddata : 'onLoadedData',
|
||||
* loadedmetadata : 'onLoadedMetadata',
|
||||
* loadstart : 'onLoadStart',
|
||||
* pause : 'onPause',
|
||||
* play : 'onPlay',
|
||||
* playing : 'onPlaying',
|
||||
* progress : 'onProgress',
|
||||
* ratechange : 'onRateChange',
|
||||
* seeked : 'onSeeked',
|
||||
* seeking : 'onSeeking',
|
||||
* stalled : 'onStalled',
|
||||
* suspend : 'onSuspend',
|
||||
* timeupdate : 'onTimeUpdate',
|
||||
* volumechange : 'onVolumeChange',
|
||||
* waiting : 'onWaiting'
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @typedef {Object} handledMediaEventsMap
|
||||
* @memberof ui/Media
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
exports.getKeyFromSource = getKeyFromSource;
|
||||
var handledMediaEventsMap = {
|
||||
abort: 'onAbort',
|
||||
canplay: 'onCanPlay',
|
||||
canplaythrough: 'onCanPlayThrough',
|
||||
durationchange: 'onDurationChange',
|
||||
emptied: 'onEmptied',
|
||||
encrypted: 'onEncrypted',
|
||||
ended: 'onEnded',
|
||||
error: 'onError',
|
||||
loadeddata: 'onLoadedData',
|
||||
loadedmetadata: 'onLoadedMetadata',
|
||||
loadstart: 'onLoadStart',
|
||||
pause: 'onPause',
|
||||
play: 'onPlay',
|
||||
playing: 'onPlaying',
|
||||
progress: 'onProgress',
|
||||
ratechange: 'onRateChange',
|
||||
seeked: 'onSeeked',
|
||||
seeking: 'onSeeking',
|
||||
stalled: 'onStalled',
|
||||
suspend: 'onSuspend',
|
||||
timeupdate: 'onTimeUpdate',
|
||||
volumechange: 'onVolumeChange',
|
||||
waiting: 'onWaiting'
|
||||
};
|
||||
/**
|
||||
* A component representation of HTMLMediaElement.
|
||||
*
|
||||
* @class Media
|
||||
* @memberof ui/Media
|
||||
* @ui
|
||||
* @public
|
||||
*/
|
||||
|
||||
exports.handledMediaEventsMap = handledMediaEventsMap;
|
||||
|
||||
var Media = /*#__PURE__*/function (_React$Component) {
|
||||
_inherits(Media, _React$Component);
|
||||
|
||||
var _super = _createSuper(Media);
|
||||
|
||||
function Media(props) {
|
||||
var _this;
|
||||
|
||||
_classCallCheck(this, Media);
|
||||
|
||||
_this = _super.call(this, props);
|
||||
|
||||
_this.attachCustomMediaEvents = function () {
|
||||
for (var eventName in _this.handledCustomMediaForwards) {
|
||||
(0, _dispatcher.on)(eventName, _this.handledCustomMediaForwards[eventName], _this.media);
|
||||
}
|
||||
};
|
||||
|
||||
_this.detachCustomMediaEvents = function () {
|
||||
for (var eventName in _this.handledCustomMediaForwards) {
|
||||
(0, _dispatcher.off)(eventName, _this.handledCustomMediaForwards[eventName], _this.media);
|
||||
}
|
||||
};
|
||||
|
||||
_this.handleEvent = function (ev) {
|
||||
(0, _handle.forward)('onUpdate', {
|
||||
type: 'onUpdate'
|
||||
}, _this.props); // fetch the forward() we generated earlier, using the event type as a key to find the real event name.
|
||||
|
||||
var fwd = _this.handledMediaForwards[handledMediaEventsMap[ev.type]];
|
||||
|
||||
if (fwd) {
|
||||
fwd(ev, _this.props);
|
||||
}
|
||||
};
|
||||
|
||||
_this.mediaRef = function (node) {
|
||||
_this.media = node;
|
||||
};
|
||||
|
||||
_this.media = null;
|
||||
_this.handledMediaForwards = {};
|
||||
_this.handledMediaEvents = {};
|
||||
_this.handledCustomMediaForwards = {}; // Generate event handling forwarders and a smooth block to pass to <Video>
|
||||
|
||||
for (var key in props.mediaEventsMap) {
|
||||
var eventName = props.mediaEventsMap[key];
|
||||
_this.handledMediaForwards[eventName] = (0, _handle.forward)(eventName);
|
||||
_this.handledMediaEvents[eventName] = _this.handleEvent;
|
||||
} // Generate event handling forwarders for the custom events too
|
||||
|
||||
|
||||
var _loop = function _loop(_eventName) {
|
||||
var propName = props.customMediaEventsMap[_eventName];
|
||||
var forwardEvent = (0, _handle.forward)(propName);
|
||||
|
||||
_this.handledCustomMediaForwards[_eventName] = function (ev) {
|
||||
return forwardEvent(ev, _this.props);
|
||||
};
|
||||
};
|
||||
|
||||
for (var _eventName in props.customMediaEventsMap) {
|
||||
_loop(_eventName);
|
||||
}
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
_createClass(Media, [{
|
||||
key: "componentDidMount",
|
||||
value: function componentDidMount() {
|
||||
this.attachCustomMediaEvents();
|
||||
}
|
||||
}, {
|
||||
key: "componentDidUpdate",
|
||||
value: function componentDidUpdate(_ref) {
|
||||
var prevSource = _ref.source;
|
||||
var source = this.props.source;
|
||||
|
||||
if (getKeyFromSource(source) !== getKeyFromSource(prevSource)) {
|
||||
this.load();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "componentWillUnmount",
|
||||
value: function componentWillUnmount() {
|
||||
this.detachCustomMediaEvents();
|
||||
}
|
||||
}, {
|
||||
key: "play",
|
||||
value: function play() {
|
||||
return this.media.play();
|
||||
}
|
||||
}, {
|
||||
key: "pause",
|
||||
value: function pause() {
|
||||
this.media.pause();
|
||||
}
|
||||
}, {
|
||||
key: "load",
|
||||
value: function load() {
|
||||
this.media.load();
|
||||
}
|
||||
}, {
|
||||
key: "render",
|
||||
value: function render() {
|
||||
var _this$props = this.props,
|
||||
customMediaEventsMap = _this$props.customMediaEventsMap,
|
||||
Component = _this$props.mediaComponent,
|
||||
source = _this$props.source,
|
||||
track = _this$props.track,
|
||||
rest = _objectWithoutProperties(_this$props, ["customMediaEventsMap", "mediaComponent", "source", "track"]);
|
||||
|
||||
delete rest.mediaEventsMap;
|
||||
delete rest.onUpdate; // Remove the events we manually added so they aren't added twice or fail.
|
||||
|
||||
for (var eventName in customMediaEventsMap) {
|
||||
delete rest[customMediaEventsMap[eventName]];
|
||||
}
|
||||
|
||||
return /*#__PURE__*/_react["default"].createElement(Component, Object.assign({}, rest, this.handledMediaEvents, {
|
||||
ref: this.mediaRef
|
||||
}), source, track);
|
||||
}
|
||||
}, {
|
||||
key: "currentTime",
|
||||
get: function get() {
|
||||
return this.media.currentTime;
|
||||
},
|
||||
set: function set(currentTime) {
|
||||
this.media.currentTime = currentTime;
|
||||
}
|
||||
}, {
|
||||
key: "duration",
|
||||
get: function get() {
|
||||
return this.media.duration;
|
||||
}
|
||||
}, {
|
||||
key: "error",
|
||||
get: function get() {
|
||||
return this.media.networkState === this.media.NETWORK_NO_SOURCE;
|
||||
}
|
||||
}, {
|
||||
key: "loading",
|
||||
get: function get() {
|
||||
return this.media.readyState < this.media.HAVE_ENOUGH_DATA;
|
||||
}
|
||||
}, {
|
||||
key: "paused",
|
||||
get: function get() {
|
||||
return this.media.paused;
|
||||
}
|
||||
}, {
|
||||
key: "playbackRate",
|
||||
get: function get() {
|
||||
return this.media.playbackRate;
|
||||
},
|
||||
set: function set(playbackRate) {
|
||||
this.media.playbackRate = playbackRate;
|
||||
}
|
||||
}, {
|
||||
key: "proportionLoaded",
|
||||
get: function get() {
|
||||
return this.media.buffered.length && this.media.buffered.end(this.media.buffered.length - 1) / this.media.duration;
|
||||
}
|
||||
}, {
|
||||
key: "proportionPlayed",
|
||||
get: function get() {
|
||||
return this.media.currentTime / this.media.duration;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Media;
|
||||
}(_react["default"].Component);
|
||||
|
||||
exports.Media = Media;
|
||||
Media.propTypes =
|
||||
/** @lends ui/Media.Media.prototype */
|
||||
{
|
||||
/**
|
||||
* A type of media component.
|
||||
*
|
||||
* @type {String|Component}
|
||||
* @required
|
||||
* @public
|
||||
*/
|
||||
mediaComponent: _propTypes["default"].renderable.isRequired,
|
||||
|
||||
/**
|
||||
* An event map object for custom media events.
|
||||
*
|
||||
* List custom events that aren't standard to React. These will be directly added to the media
|
||||
* element and props matching their name will be executed as callback functions when the event fires.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* {'umsmediainfo': 'onUMSMediaInfo'} // `onUMSMediaInfo` prop function will execute when the `umsmediainfo` event happens
|
||||
* ```
|
||||
*
|
||||
* @type {Object}
|
||||
* @public
|
||||
*/
|
||||
customMediaEventsMap: _propTypes2["default"].object,
|
||||
|
||||
/**
|
||||
* A event map object for media events.
|
||||
*
|
||||
* @type {Object}
|
||||
* @default {@link ui/Media.handledMediaEventsMap}
|
||||
* @public
|
||||
*/
|
||||
mediaEventsMap: _propTypes2["default"].object,
|
||||
|
||||
/**
|
||||
* A function to be run when media updates.
|
||||
*
|
||||
* @type {Function}
|
||||
* @public
|
||||
*/
|
||||
onUpdate: _propTypes2["default"].func,
|
||||
|
||||
/**
|
||||
* Media sources passed as children to `mediaComponent`
|
||||
*
|
||||
* See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source
|
||||
*
|
||||
* @type {*}
|
||||
* @public
|
||||
*/
|
||||
source: _propTypes2["default"].any,
|
||||
track: _propTypes2["default"].any //yhcho
|
||||
};
|
||||
Media.defaultProps = {
|
||||
mediaEventsMap: handledMediaEventsMap
|
||||
};
|
||||
var _default = Media;
|
||||
exports["default"] = _default;
|
||||
@@ -42,7 +42,7 @@ 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 Media from "./Media";
|
||||
import Slottable from "@enact/ui/Slottable";
|
||||
import Touchable from "@enact/ui/Touchable";
|
||||
|
||||
@@ -719,6 +719,7 @@ const VideoPlayerBase = class extends React.Component {
|
||||
onIntroDisabled: PropTypes.func,
|
||||
modalClassName: PropTypes.any,
|
||||
src: PropTypes.string, //for ReactPlayer
|
||||
reactPlayerConfig: PropTypes.string, //for ReactPlayer
|
||||
};
|
||||
|
||||
static contextType = FloatingLayerContext;
|
||||
@@ -2063,6 +2064,7 @@ const VideoPlayerBase = class extends React.Component {
|
||||
src,
|
||||
width,
|
||||
height,
|
||||
reactPlayerConfig,
|
||||
...mediaProps
|
||||
} = this.props;
|
||||
|
||||
@@ -2108,6 +2110,7 @@ const VideoPlayerBase = class extends React.Component {
|
||||
mediaProps.width = width;
|
||||
mediaProps.height = height;
|
||||
mediaProps.videoRef = this.setVideoRef;
|
||||
mediaProps.config = reactPlayerConfig;
|
||||
}
|
||||
|
||||
const controlsAriaProps = this.getControlsAriaProps();
|
||||
|
||||
@@ -2,41 +2,6 @@ import appinfo from '../../webos-meta/appinfo.json';
|
||||
import * as Config from '../utils/Config';
|
||||
import LS2Request from './LS2Request';
|
||||
|
||||
export const getSystemSettings = (
|
||||
parameters,
|
||||
{ onSuccess, onFailure, onComplete }
|
||||
) => {
|
||||
if (typeof window === "object" && window.PalmSystem) {
|
||||
if (process.env.REACT_APP_MODE === "DEBUG") {
|
||||
console.log("LUNA SEND getSystemSettings");
|
||||
return "Some Hard Coded Mock Data";
|
||||
} else {
|
||||
return new LS2Request().send({
|
||||
service: "luna://com.webos.settingsservice",
|
||||
method: "getSystemSettings",
|
||||
subscribe: true,
|
||||
parameters: parameters,
|
||||
onSuccess,
|
||||
onFailure,
|
||||
onComplete,
|
||||
});
|
||||
}
|
||||
} else if (typeof window === "object") {
|
||||
const language =
|
||||
typeof window.navigator === "object"
|
||||
? window.navigator.language || window.navigator.userLanguage
|
||||
: "en-US";
|
||||
const res = {
|
||||
settings: {
|
||||
smartServiceCountryCode2: language.split("-")[1],
|
||||
captionEnable: true,
|
||||
},
|
||||
returnValue: true,
|
||||
};
|
||||
onSuccess(res);
|
||||
onComplete(res);
|
||||
}
|
||||
};
|
||||
export const getSystemInfo = (
|
||||
parameters,
|
||||
{ onSuccess, onFailure, onComplete }
|
||||
|
||||
@@ -87,3 +87,39 @@ export const getHttpHeaderForServiceRequest = ({
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const getSystemSettings = (
|
||||
parameters,
|
||||
{ onSuccess, onFailure, onComplete }
|
||||
) => {
|
||||
if (typeof window === "object" && window.PalmSystem) {
|
||||
if (process.env.REACT_APP_MODE === "DEBUG") {
|
||||
console.log("LUNA SEND getSystemSettings");
|
||||
return "Some Hard Coded Mock Data";
|
||||
} else {
|
||||
return new LS2Request().send({
|
||||
service: "luna://com.webos.settingsservice",
|
||||
method: "getSystemSettings",
|
||||
subscribe: true,
|
||||
parameters: parameters,
|
||||
onSuccess,
|
||||
onFailure,
|
||||
onComplete,
|
||||
});
|
||||
}
|
||||
} else if (typeof window === "object") {
|
||||
const language =
|
||||
typeof window.navigator === "object"
|
||||
? window.navigator.language || window.navigator.userLanguage
|
||||
: "en-US";
|
||||
const res = {
|
||||
settings: {
|
||||
smartServiceCountryCode2: language.split("-")[1],
|
||||
captionEnable: true,
|
||||
},
|
||||
returnValue: true,
|
||||
};
|
||||
onSuccess(res);
|
||||
onComplete(res);
|
||||
}
|
||||
};
|
||||
@@ -12,6 +12,7 @@ const initialState = {
|
||||
loginUserData: {},
|
||||
toast: false,
|
||||
toastText: null,
|
||||
captionEnable: false
|
||||
},
|
||||
httpHeader: null,
|
||||
isGnbOpened: false,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { types } from '../actions/actionTypes';
|
||||
|
||||
const initialState = {};
|
||||
const initialState = {
|
||||
subTitleBlobs: {},
|
||||
};
|
||||
|
||||
export const playReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
@@ -10,8 +12,13 @@ export const playReducer = (state = initialState, action) => {
|
||||
chatData: action.payload.text,
|
||||
};
|
||||
case types.GET_SUBTITLE: {
|
||||
let srtText = action.payload.text;
|
||||
|
||||
let srtText = action.payload.data?.text;
|
||||
if(!srtText){
|
||||
return {
|
||||
...state,
|
||||
subTitleBlobs: { ...state.subTitleBlobs, [action.payload.url]: "Error" },
|
||||
};
|
||||
}
|
||||
var srtRegex =
|
||||
/(.*\n)?(\d\d:\d\d:\d\d),(\d\d\d --> \d\d:\d\d:\d\d),(\d\d\d)/g;
|
||||
var vttText = "WEBVTT\n\n" + srtText.replace(srtRegex, "$1$2.$3.$4");
|
||||
@@ -20,7 +27,7 @@ export const playReducer = (state = initialState, action) => {
|
||||
|
||||
return {
|
||||
...state,
|
||||
subTitle: blobUrl,
|
||||
subTitleBlobs: { ...state.subTitleBlobs, [action.payload.url]: blobUrl },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export const ACTIVE_POPUP = {
|
||||
alarmOffPopup: "alarmOffPopup",
|
||||
qrPopup: "qrPopup",
|
||||
};
|
||||
|
||||
export const DEBUG_VIDEO_SUBTITLE_TEST = false;
|
||||
export const AUTO_SCROLL_DELAY = 600;
|
||||
export const AUTO_SCROLL_GAP = 20;
|
||||
export const SINGLE = "SINGLE";
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
getSubTitle,
|
||||
startVideoPlayer,
|
||||
} from "../../actions/playActions";
|
||||
import * as Config from "../../utils/Config";
|
||||
import { MediaControls } from "../../components/MediaPlayer";
|
||||
import TButton from "../../components/TButton/TButton";
|
||||
import TButtonTab, { LIST_TYPE } from "../../components/TButtonTab/TButtonTab";
|
||||
@@ -46,6 +47,7 @@ import FeaturedShowContents from "./PlayerTabContents/FeaturedShowContents";
|
||||
import LiveChannelContents from "./PlayerTabContents/LiveChannelContents";
|
||||
import ShopNowContents from "./PlayerTabContents/ShopNowContents";
|
||||
import YouMayLikeContents from "./PlayerTabContents/YouMayLikeContents";
|
||||
import dummyVtt from "../../../assets/mock/video.vtt";
|
||||
|
||||
const SpottableBtn = Spottable("button");
|
||||
const Container = SpotlightContainerDecorator(
|
||||
@@ -78,6 +80,7 @@ const PlayerPanel = ({
|
||||
const chatData = useSelector((state) => state.play.chatData);
|
||||
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
|
||||
const showDetailInfo = useSelector((state) => state.main.showDetailInfo);
|
||||
const captionEnable = useSelector((state) => state.common.appStatus.captionEnable);
|
||||
const featuredShowsInfos = useSelector(
|
||||
(state) => state.main.featuredShowsInfos
|
||||
);
|
||||
@@ -86,7 +89,8 @@ const PlayerPanel = ({
|
||||
const showNowInfos = useSelector((state) => state.main.showNowInfo);
|
||||
const showNowProduct = useSelector((state) => state.main.showNowProduct);
|
||||
const liveShowInfos = useSelector((state) => state.main.liveShowInfos);
|
||||
const vodSubtitleData = useSelector((state) => state.play.subTitle);
|
||||
//getSubTitle
|
||||
const vodSubtitleData = useSelector((state) => state.play.subTitleBlobs);
|
||||
const tabList = [
|
||||
$L("SHOP NOW"),
|
||||
$L(panelInfo?.shptmBanrTpNm === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
|
||||
@@ -234,18 +238,6 @@ const PlayerPanel = ({
|
||||
}
|
||||
}, [panelInfo, playListInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
playListInfo &&
|
||||
playListInfo.length > 0 &&
|
||||
playListInfo[0].showSubtitlUrl
|
||||
) {
|
||||
dispatch(
|
||||
getSubTitle({ showSubtitleUrl: playListInfo[0].showSubtitlUrl })
|
||||
);
|
||||
}
|
||||
}, [dispatch, playListInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!panelInfo) return;
|
||||
|
||||
@@ -357,6 +349,52 @@ const PlayerPanel = ({
|
||||
}, [panelInfo, isOnTop]);
|
||||
|
||||
delete props.panelInfo;
|
||||
|
||||
const currentSubtTitleUrl = useMemo(()=>{
|
||||
return playListInfo && playListInfo[selectedIndex]?.showSubtitlUrl;
|
||||
},[playListInfo, selectedIndex]);
|
||||
|
||||
const currentPlayingUrl = useMemo(()=>{
|
||||
// return "https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4";
|
||||
return playListInfo && playListInfo[selectedIndex]?.showUrl;
|
||||
},[playListInfo, selectedIndex]);
|
||||
|
||||
const currentSubtitleBlob = useMemo(()=>{
|
||||
if(Config.DEBUG_VIDEO_SUBTITLE_TEST){
|
||||
return dummyVtt;
|
||||
}
|
||||
return vodSubtitleData[currentSubtTitleUrl];
|
||||
},[vodSubtitleData, currentSubtTitleUrl]);
|
||||
|
||||
const isReadyToPlay = useMemo(()=>{
|
||||
if(!currentPlayingUrl){
|
||||
return false;
|
||||
}
|
||||
if(!Config.DEBUG_VIDEO_SUBTITLE_TEST && currentSubtTitleUrl && !currentSubtitleBlob){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},[currentPlayingUrl, currentSubtTitleUrl, currentSubtitleBlob]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentSubtTitleUrl) {
|
||||
dispatch(getSubTitle({ showSubtitleUrl: currentSubtTitleUrl }));
|
||||
}
|
||||
}, [currentSubtTitleUrl]);
|
||||
|
||||
const reactPlayerSubtitleConfig = useMemo(() => {
|
||||
if(currentSubtitleBlob){
|
||||
return {file: {
|
||||
attributes: {
|
||||
crossOrigin: "true",
|
||||
},
|
||||
tracks: [{kind: 'subtitles', src: currentSubtitleBlob, default: true}],
|
||||
}};
|
||||
}else{
|
||||
return undefined;
|
||||
}
|
||||
},[currentSubtitleBlob]);
|
||||
|
||||
return (
|
||||
<TPanel
|
||||
isTabActivated={false}
|
||||
@@ -364,10 +402,12 @@ const PlayerPanel = ({
|
||||
className={classNames(
|
||||
css.videoContainer,
|
||||
panelInfo.modal && css.modal,
|
||||
!isOnTop && css.background
|
||||
!isOnTop && css.background,
|
||||
!captionEnable && css.hideSubtitle
|
||||
)}
|
||||
handleCancel={onClickBack}
|
||||
>
|
||||
{isReadyToPlay &&
|
||||
<VideoPlayer
|
||||
setApiProvider={getPlayer}
|
||||
disabled={panelInfo.modal}
|
||||
@@ -380,15 +420,23 @@ const PlayerPanel = ({
|
||||
setSelectedIndex={setSelectedIndex} // 선택한 인덱스 Set
|
||||
selectedIndex={selectedIndex} // 선택한 인덱스
|
||||
spotlightDisabled={sideOpen || panelInfo.modal}
|
||||
src={playListInfo && playListInfo[selectedIndex]?.showUrl}
|
||||
src={currentPlayingUrl}
|
||||
style={panelInfo.modal ? modalStyle : {}}
|
||||
modalClassName={panelInfo.modal && panelInfo.modalClassName}
|
||||
reactPlayerConfig={reactPlayerSubtitleConfig}
|
||||
>
|
||||
{
|
||||
typeof window === "object" && window.PalmSystem &&
|
||||
<source
|
||||
src={playListInfo && playListInfo[selectedIndex]?.showUrl}
|
||||
src={currentPlayingUrl}
|
||||
type="application/mpegurl"
|
||||
/>
|
||||
}
|
||||
{ typeof window === "object" && window.PalmSystem && currentSubtitleBlob &&
|
||||
<track kind="subtitles" src={currentSubtitleBlob} default/>
|
||||
}
|
||||
</VideoPlayer>
|
||||
}
|
||||
{playListInfo && playListInfo[selectedIndex]?.orderPhnNo && (
|
||||
<VideoOverlayWithPhoneNumber
|
||||
className={css.videoOverlayWithPhoneNumber}
|
||||
|
||||
@@ -175,4 +175,9 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.hideSubtitle{
|
||||
video::cue {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user