Skip to content

Commit 2a0a998

Browse files
refactor: 调整代码结构
1 parent 07c2a34 commit 2a0a998

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+7542
-0
lines changed

package.json

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "reactjs-player",
3+
"version": "1.2.1",
4+
"description": "基于 react hooks 的 video 播放组件,结构简单,代码简洁,扩展方便。",
5+
"keywords": [
6+
"react",
7+
"media",
8+
"player",
9+
"video",
10+
"hls.js",
11+
"flv.js",
12+
"react-hooks"
13+
],
14+
"author": "xiaosong <[email protected]>",
15+
"homepage": "https://github.com/goblin-laboratory/reactjs-player/blob/master/packages/reactjs-player/README.md",
16+
"license": "MIT",
17+
"browser": "dist/index.umd.js",
18+
"repository": {
19+
"type": "git",
20+
"url": "git+https://github.com/goblin-laboratory/reactjs-player.git"
21+
},
22+
"scripts": {
23+
"lint": "eslint .",
24+
"start": "rollup -c ./scripts/rollup.config.dev.js -w",
25+
"build": "rollup -c ./scripts/rollup.config.prod.js",
26+
"predeploy": "cd example && yarn install && yarn run build",
27+
"deploy": "gh-pages -d example/build",
28+
"nrm": "nrm use taobao"
29+
},
30+
"devDependencies": {
31+
"@babel/core": "^7.15.8",
32+
"@rollup/plugin-babel": "^5.3.0",
33+
"@rollup/plugin-commonjs": "^21.0.0",
34+
"@rollup/plugin-node-resolve": "^13.0.5",
35+
"@rollup/plugin-url": "^6.1.0",
36+
"@svgr/rollup": "^5.5.0",
37+
"gh-pages": "^3.2.3",
38+
"less": "^4.1.2",
39+
"postcss": "^8.3.9",
40+
"rollup": "^2.58.0",
41+
"rollup-plugin-filesize": "^9.1.1",
42+
"rollup-plugin-peer-deps-external": "^2.2.4",
43+
"rollup-plugin-postcss": "^4.0.1",
44+
"rollup-plugin-uglify": "^6.0.4"
45+
},
46+
"peerDependencies": {
47+
"@ant-design/icons": "^4.7.0",
48+
"antd": "^4.16.13",
49+
"fbemitter": "^3.0.0",
50+
"numeral": "^2.0.6",
51+
"prop-types": "^15.7.2",
52+
"react": "^17.0.2",
53+
"react-swf": "^1.0.7"
54+
}
55+
}

scripts/rollup.config.dev.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import config from './rollup.config';
2+
3+
process.env.NODE_ENV = 'development';
4+
5+
export default config;

scripts/rollup.config.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// import resolve from '@rollup/plugin-node-resolve';
2+
import { nodeResolve } from "@rollup/plugin-node-resolve";
3+
import commonjs from "@rollup/plugin-commonjs";
4+
import { babel } from "@rollup/plugin-babel";
5+
import external from "rollup-plugin-peer-deps-external";
6+
import postcss from "rollup-plugin-postcss";
7+
import url from "@rollup/plugin-url";
8+
import svgr from "@svgr/rollup";
9+
import filesize from "rollup-plugin-filesize";
10+
11+
import pkg from "../package.json";
12+
13+
export default {
14+
input: "src/index.js",
15+
output: [
16+
{
17+
file: pkg.browser,
18+
name: pkg.name,
19+
format: "umd",
20+
sourcemap: true,
21+
globals: {
22+
react: "React",
23+
"prop-types": "PropTypes",
24+
"numeral": "numeral",
25+
"antd": "antd",
26+
"@ant-design/icons": "@ant-design/icons",
27+
"react-swf": "ReactSWF",
28+
"fbemitter": "fbemitter",
29+
},
30+
},
31+
],
32+
plugins: [
33+
external(),
34+
postcss({
35+
modules: true,
36+
}),
37+
url(),
38+
url({
39+
limit: 0,
40+
include: ["**/*.swf"],
41+
emitFiles: true,
42+
fileName: "[name][extname]",
43+
}),
44+
svgr(),
45+
babel({
46+
babelrc: false,
47+
exclude: "node_modules/**",
48+
babelHelpers: "bundled",
49+
presets: [
50+
[
51+
"@babel/preset-env",
52+
{
53+
modules: false,
54+
},
55+
],
56+
"@babel/preset-react",
57+
],
58+
}),
59+
nodeResolve(),
60+
commonjs(),
61+
filesize(),
62+
],
63+
};

scripts/rollup.config.prod.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import config from './rollup.config';
2+
3+
process.env.NODE_ENV = 'production';
4+
5+
export default config;

src/Flvjs/index.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import useFlvjs from '../hooks/useFlvjs';
4+
5+
const Flvjs = (props) => {
6+
useFlvjs(props);
7+
return null;
8+
};
9+
10+
Flvjs.propTypes = {
11+
getVideoElement: PropTypes.func.isRequired,
12+
src: PropTypes.string,
13+
config: PropTypes.object,
14+
onMsgChange: PropTypes.func.isRequired,
15+
};
16+
17+
Flvjs.defaultProps = {
18+
src: '',
19+
config: null,
20+
};
21+
22+
export default React.memo(Flvjs);

src/GrindPlayer/GrindPlayer.js

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { EventEmitter } from 'fbemitter';
2+
3+
let emitter = null;
4+
let index = 0;
5+
6+
class GrindPlayer {
7+
/**
8+
* 创建 GrindPlayer 实例
9+
*/
10+
constructor(id) {
11+
this.id = id;
12+
this.el = null;
13+
this.emitter = new EventEmitter();
14+
this.tokenList = [];
15+
this.eventMap = [];
16+
17+
this.addListener();
18+
}
19+
20+
addListener() {
21+
if (!emitter) {
22+
emitter = new EventEmitter();
23+
}
24+
25+
this.tokenList = [
26+
emitter.addListener(`${this.id}.onJavaScriptBridgeCreated`, () => {
27+
this.el = document.getElementById(this.id);
28+
// this.el.addEventListener('mediaError', () => );
29+
}),
30+
emitter.addListener(`${this.id}.mediaSize`, data => {
31+
if (0 === data.videoHeight && 0 === data.videoWidth) {
32+
this.emitter.emit('canplay');
33+
} else {
34+
this.emitter.emit('canplaythrough');
35+
}
36+
}),
37+
emitter.addListener(`${this.id}.paused`, () => this.emitter.emit('pause')),
38+
emitter.addListener(`${this.id}.playing`, () => this.emitter.emit('playing')),
39+
emitter.addListener(`${this.id}.seeking`, () => this.emitter.emit('seeking')),
40+
emitter.addListener(`${this.id}.seeked`, () => this.emitter.emit('seeked')),
41+
emitter.addListener(`${this.id}.complete`, () => this.emitter.emit('ended')),
42+
emitter.addListener(`${this.id}.buffering`, () => this.emitter.emit('waiting')),
43+
44+
emitter.addListener(`${this.id}.durationChange`, e => this.emitter.emit('durationchange', e)),
45+
emitter.addListener(`${this.id}.timeChange`, e => this.emitter.emit('timeupdate', e)),
46+
emitter.addListener(`${this.id}.progress`, e => this.emitter.emit('progress', e)),
47+
48+
emitter.addListener(`${this.id}.volumeChange`, e => this.emitter.emit('volumechange', e)),
49+
];
50+
}
51+
52+
invoker(methodName, ...args) {
53+
if (!this.el) {
54+
return;
55+
}
56+
this.el[methodName](...args);
57+
}
58+
59+
addEventListener(event, fn) {
60+
if (!this.eventMap) {
61+
return;
62+
}
63+
const token = this.emitter.addListener(event, fn);
64+
this.eventMap.push({ token, event, fn });
65+
}
66+
67+
removeEventListener(event, fn) {
68+
if (!this.eventMap) {
69+
return;
70+
}
71+
this.eventMap = this.eventMap.filter(it => {
72+
if (it.event !== event) {
73+
return true;
74+
}
75+
if (!fn && it.fn !== fn) {
76+
return true;
77+
}
78+
it.token.remove();
79+
return false;
80+
});
81+
}
82+
83+
destroy() {
84+
if (this.eventMap) {
85+
this.eventMap.map(it => it.token.remove());
86+
delete this.eventMap;
87+
}
88+
89+
if (this.tokenList) {
90+
this.tokenList.map(it => it.remove());
91+
delete this.tokenList;
92+
}
93+
94+
if (this.emitter) {
95+
this.emitter.removeAllListeners();
96+
}
97+
delete this.emitter;
98+
99+
delete this.id;
100+
delete this.el;
101+
}
102+
}
103+
104+
const onJSBridge = (playerId, event, data) => {
105+
if (!emitter) {
106+
emitter = new EventEmitter();
107+
}
108+
console.log(`${event}: ${JSON.stringify(data)}`);
109+
emitter.emit(`${playerId}.${event}`, data);
110+
};
111+
112+
export default {
113+
getPlayerId: () => `grindPlayer${index++}`,
114+
115+
getGrindPlayer: (id, javascriptCallbackFunction) => {
116+
if (!global[javascriptCallbackFunction]) {
117+
global[javascriptCallbackFunction] = onJSBridge;
118+
}
119+
return new GrindPlayer(id);
120+
},
121+
};

src/GrindPlayer/GrindPlayer.swf

999 KB
Binary file not shown.
1000 KB
Binary file not shown.

src/GrindPlayer/flashlsOSMF.swf

88.7 KB
Binary file not shown.

src/GrindPlayer/index.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import ReactSWF from 'react-swf';
4+
import './GrindPlayer.swf';
5+
import './flashlsOSMF.swf';
6+
import ReactPlayerContext from '../ReactPlayerContext';
7+
import useGrindPlayer from './useGrindPlayer';
8+
import useState from './useState';
9+
import useTime from './useTime';
10+
import useVolume from './useVolume';
11+
import styles from './index.module.less';
12+
13+
const GrindPlayer = ({ live, src, type, grindPlayerSwf, flashlsOSMFSwf }) => {
14+
const { ref, dispatch, id, javascriptCallbackFunction, ...state } = useGrindPlayer({ src });
15+
16+
const stateProps = useState({ ref, dispatch });
17+
const timeProps = useTime({ ref, dispatch });
18+
const volumeProps = useVolume({ ref, dispatch });
19+
20+
return (
21+
<div className={styles.grindPlayer}>
22+
{src && (
23+
<ReactSWF
24+
id={id}
25+
src={grindPlayerSwf}
26+
width="100%"
27+
height="100%"
28+
wmode="opaque"
29+
allowFullScreen
30+
allowScriptAccess="always"
31+
bgcolor="#000000"
32+
flashVars={{
33+
src,
34+
autoPlay: true,
35+
bufferTime: 0.5,
36+
streamType: live ? 'live' : 'recorded',
37+
plugin_hls: 'application/x-mpegURL' === type ? flashlsOSMFSwf : undefined,
38+
javascriptCallbackFunction,
39+
}}
40+
/>
41+
)}
42+
<ReactPlayerContext.Provider
43+
value={{
44+
live,
45+
src,
46+
...state,
47+
...stateProps,
48+
...timeProps,
49+
...volumeProps,
50+
}}
51+
/>
52+
</div>
53+
);
54+
};
55+
56+
GrindPlayer.propTypes = {
57+
live: PropTypes.bool,
58+
src: PropTypes.string.isRequired,
59+
type: PropTypes.string.isRequired,
60+
grindPlayerSwf: PropTypes.string,
61+
flashlsOSMFSwf: PropTypes.string,
62+
};
63+
64+
GrindPlayer.defaultProps = {
65+
live: true,
66+
grindPlayerSwf: 'http://unpkg.com/reactjs-player/dist/GrindPlayer.swf',
67+
flashlsOSMFSwf: 'http://unpkg.com/reactjs-player/dist/flashlsOSMF.swf',
68+
};
69+
70+
export default React.memo(GrindPlayer);

src/GrindPlayer/index.module.less

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.grindPlayer {
2+
position: absolute;
3+
top: 0;
4+
left: 0;
5+
height: 100%;
6+
width: 100%;
7+
min-width: 400px;
8+
min-height: 300px;
9+
overflow: hidden;
10+
background: #000;
11+
}

0 commit comments

Comments
 (0)