@scaleflex/widget-media-player 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7420 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/lib/components/AudioPlayer.js +21 -0
- package/lib/components/MediaControls.js +324 -0
- package/lib/components/MediaPlayer.styled.js +95 -0
- package/lib/components/PlaybackSpeedMenu.js +25 -0
- package/lib/components/Timelapse.js +17 -0
- package/lib/components/VideoPlayer/VideoPlayer.constants.js +28 -0
- package/lib/components/VideoPlayer/VideoPlayer.styled.js +32 -0
- package/lib/components/VideoPlayer/VideoPlayer.utils.js +36 -0
- package/lib/components/VideoPlayer/VideoPlayerQualityLevels.js +141 -0
- package/lib/components/VideoPlayer/index.js +142 -0
- package/lib/components/VolumeControl.js +49 -0
- package/lib/defaultLocale.js +4 -0
- package/lib/index.js +92 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 scaleflex
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# `@scaleflex/widget-media-player`
|
|
2
|
+
|
|
3
|
+
[![Plugins][plugins-image]](#plugins)
|
|
4
|
+
[![Website][filerobot-image]][sfx-url]
|
|
5
|
+
[![Version][filerobot-version]][version-url]
|
|
6
|
+
[![Scaleflex team][made-by-image]][sfx-url]
|
|
7
|
+
[![License][license-image]][license-url]
|
|
8
|
+
[![CodeSandbox][codeSandbox-image]][codeSandbox-url]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
<div align='center'>
|
|
12
|
+
<img title="Scaleflex Widget logo" alt="Scaleflex Widget logo" src="https://cdn.scaleflex.com/plugins/filerobot-widget/assets/filerobot_widget_logo_with_fire.png?vh=b2ff09" width="140"/>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
The media-player plugin provides player controls to audio/video files in [Scaleflex Media Asset Widget](https://www.npmjs.com/package/@scaleflex/widget-core).
|
|
16
|
+
> Note: The supported playback audio/video formats are `audio/mpeg, audio/ogg, audio/wav, video/mp4, video/quicktime, video/3gpp, video/x-msvideo, video/webm, video/x-matroska`
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### NPM
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install --save @scaleflex/widget-media-player
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### YARN
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yarn add @scaleflex/widget-media-player
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
then
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import MediaPlayer from '@scaleflex/widget-media-player
|
|
37
|
+
...
|
|
38
|
+
...
|
|
39
|
+
...
|
|
40
|
+
scaleflexWidget.use(MediaPlayer)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### CDN
|
|
44
|
+
|
|
45
|
+
The plugin from CDN is found inside `Scaleflex` global object `Scaleflex.MediaPlayer`
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const MediaPlayer = window.ScaleflexWidget.MediaPlayer
|
|
49
|
+
...
|
|
50
|
+
...
|
|
51
|
+
...
|
|
52
|
+
scaleflexWidget.use(MediaPlayer)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
<!-- Variables -->
|
|
56
|
+
|
|
57
|
+
[npm-url]: https://www.npmjs.com/package/@scaleflex/widget-media-player
|
|
58
|
+
[license-url]: https://opensource.org/licenses/MIT
|
|
59
|
+
[sfx-url]: https://www.scaleflex.com/
|
|
60
|
+
[version-url]: https://www.npmjs.com/package/@scaleflex/widget-media-player
|
|
61
|
+
[codeSandbox-url]: https://codesandbox.io/s/filerobot-widget-v3-c5l9th
|
|
62
|
+
|
|
63
|
+
[npm-image]: https://img.shields.io/npm/v/@telus/remark-config.svg?style=for-the-badge&logo=npm
|
|
64
|
+
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge
|
|
65
|
+
[made-by-image]: https://img.shields.io/badge/%3C%2F%3E%20with%20%E2%99%A5%20by-the%20Scaleflex%20team-6986fa.svg?style=for-the-badge
|
|
66
|
+
[plugins-image]: https://img.shields.io/static/v1?label=Scaleflex&message=Plugins&color=yellow&style=for-the-badge
|
|
67
|
+
[filerobot-image]: https://img.shields.io/static/v1?label=Scaleflex&message=website&color=orange&style=for-the-badge
|
|
68
|
+
[filerobot-version]: https://img.shields.io/npm/v/@scaleflex/widget-media-player?label=Version&style=for-the-badge&logo=npm
|
|
69
|
+
[codeSandbox-image]: https://img.shields.io/badge/CodeSandbox-black?style=for-the-badge&logo=CodeSandbox
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import MediaControls from './MediaControls';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
var AudioPlayer = function AudioPlayer(_ref) {
|
|
5
|
+
var mediaOptions = _ref.mediaOptions;
|
|
6
|
+
var _ref2 = mediaOptions || {},
|
|
7
|
+
audioPath = _ref2.audioPath;
|
|
8
|
+
var audioRef = useMemo(function () {
|
|
9
|
+
return {
|
|
10
|
+
current: new Audio(audioPath)
|
|
11
|
+
};
|
|
12
|
+
}, [audioPath]);
|
|
13
|
+
if (!audioPath) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return /*#__PURE__*/_jsx(MediaControls, {
|
|
17
|
+
mediaRef: audioRef,
|
|
18
|
+
isPlayerReady: true
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
export default AudioPlayer;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
4
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
|
+
import { useRef, useState, useEffect } from 'react';
|
|
8
|
+
import { Play, Pause } from '@scaleflex/icons';
|
|
9
|
+
import TimeLapse from './Timelapse';
|
|
10
|
+
import PlaybackSpeedMenu from './PlaybackSpeedMenu';
|
|
11
|
+
import Styled from './MediaPlayer.styled';
|
|
12
|
+
import VolumeControl from './VolumeControl';
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
var MediaControls = function MediaControls(_ref) {
|
|
15
|
+
var extraControllers = _ref.extraControllers,
|
|
16
|
+
mediaRef = _ref.mediaRef,
|
|
17
|
+
isPlayerReady = _ref.isPlayerReady,
|
|
18
|
+
_ref$dismissInitialLo = _ref.dismissInitialLoad,
|
|
19
|
+
dismissInitialLoad = _ref$dismissInitialLo === void 0 ? false : _ref$dismissInitialLo,
|
|
20
|
+
onKeyboardFullscreenKeyDown = _ref.onKeyboardFullscreenKeyDown,
|
|
21
|
+
mediaPlayerRef = _ref.mediaPlayerRef;
|
|
22
|
+
var _useState = useState(0),
|
|
23
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
24
|
+
trackProgress = _useState2[0],
|
|
25
|
+
setTrackProgress = _useState2[1];
|
|
26
|
+
var _useState3 = useState(false),
|
|
27
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
28
|
+
isPlaying = _useState4[0],
|
|
29
|
+
setIsPlaying = _useState4[1];
|
|
30
|
+
var _useState5 = useState(false),
|
|
31
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
32
|
+
trackEnded = _useState6[0],
|
|
33
|
+
setTrackEnded = _useState6[1];
|
|
34
|
+
var _useState7 = useState(0),
|
|
35
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
36
|
+
duration = _useState8[0],
|
|
37
|
+
setDuration = _useState8[1];
|
|
38
|
+
var _useState9 = useState(1),
|
|
39
|
+
_useState10 = _slicedToArray(_useState9, 2),
|
|
40
|
+
playbackSpeed = _useState10[0],
|
|
41
|
+
setPlaybackSpeed = _useState10[1];
|
|
42
|
+
var _useState11 = useState(),
|
|
43
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
44
|
+
playbackMenuAnchor = _useState12[0],
|
|
45
|
+
setPlaybackMenuAnchor = _useState12[1];
|
|
46
|
+
var _useState13 = useState(1),
|
|
47
|
+
_useState14 = _slicedToArray(_useState13, 2),
|
|
48
|
+
volumeLevel = _useState14[0],
|
|
49
|
+
setVolumeLevel = _useState14[1];
|
|
50
|
+
var _useState15 = useState(0),
|
|
51
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
52
|
+
beforeMutedVolumeLevel = _useState16[0],
|
|
53
|
+
setBeforeMutedVolumeLevel = _useState16[1];
|
|
54
|
+
var _useState17 = useState(false),
|
|
55
|
+
_useState18 = _slicedToArray(_useState17, 2),
|
|
56
|
+
isSeeking = _useState18[0],
|
|
57
|
+
setIsSeeking = _useState18[1];
|
|
58
|
+
var _useState19 = useState(false),
|
|
59
|
+
_useState20 = _slicedToArray(_useState19, 2),
|
|
60
|
+
isAudioSliderOpen = _useState20[0],
|
|
61
|
+
setIsAudioSliderOpen = _useState20[1];
|
|
62
|
+
var _useState21 = useState(false),
|
|
63
|
+
_useState22 = _slicedToArray(_useState21, 2),
|
|
64
|
+
isMuted = _useState22[0],
|
|
65
|
+
setIsMuted = _useState22[1];
|
|
66
|
+
var controlsContainerRef = useRef();
|
|
67
|
+
var intervalRef = useRef();
|
|
68
|
+
var audioSliderTimerRef = useRef();
|
|
69
|
+
var isReadyRef = useRef(false);
|
|
70
|
+
var containerRef = mediaPlayerRef !== null && mediaPlayerRef !== void 0 && mediaPlayerRef.current ? mediaPlayerRef : controlsContainerRef;
|
|
71
|
+
var resetControls = function resetControls() {
|
|
72
|
+
setVolumeLevel(1);
|
|
73
|
+
setPlaybackSpeed(1);
|
|
74
|
+
setTrackProgress(0);
|
|
75
|
+
};
|
|
76
|
+
var handleTogglePlaybackMenu = function handleTogglePlaybackMenu(event) {
|
|
77
|
+
if (!playbackMenuAnchor) {
|
|
78
|
+
setPlaybackMenuAnchor(event.currentTarget);
|
|
79
|
+
} else {
|
|
80
|
+
setPlaybackMenuAnchor();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var handleChangePlaybackSpeed = function handleChangePlaybackSpeed(value) {
|
|
84
|
+
return function () {
|
|
85
|
+
setPlaybackSpeed(value);
|
|
86
|
+
handleTogglePlaybackMenu();
|
|
87
|
+
mediaRef.current.playbackRate = value;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
var startTimer = function startTimer() {
|
|
91
|
+
// Clear any timers already running
|
|
92
|
+
clearInterval(intervalRef.current);
|
|
93
|
+
intervalRef.current = setInterval(function () {
|
|
94
|
+
if (mediaRef.current.ended) {
|
|
95
|
+
setTrackEnded(true);
|
|
96
|
+
setIsPlaying(false);
|
|
97
|
+
} else {
|
|
98
|
+
setTrackProgress(mediaRef.current.currentTime);
|
|
99
|
+
}
|
|
100
|
+
}, [1000]);
|
|
101
|
+
};
|
|
102
|
+
var onScrub = function onScrub(_, value) {
|
|
103
|
+
// Clear any timers already running
|
|
104
|
+
clearInterval(intervalRef.current);
|
|
105
|
+
mediaRef.current.currentTime = value;
|
|
106
|
+
setIsSeeking(true);
|
|
107
|
+
setIsPlaying(false);
|
|
108
|
+
setTrackProgress(mediaRef.current.currentTime);
|
|
109
|
+
};
|
|
110
|
+
var onScrubEnd = function onScrubEnd() {
|
|
111
|
+
// If not already playing, start
|
|
112
|
+
if (!isPlaying) {
|
|
113
|
+
setIsPlaying(true);
|
|
114
|
+
}
|
|
115
|
+
setIsSeeking(false);
|
|
116
|
+
startTimer();
|
|
117
|
+
};
|
|
118
|
+
var checkAndSetIsMutedBySlider = function checkAndSetIsMutedBySlider(value) {
|
|
119
|
+
setIsMuted(value === 0);
|
|
120
|
+
};
|
|
121
|
+
var handleChangeVolumeLevel = function handleChangeVolumeLevel(value) {
|
|
122
|
+
var adaptedValue = Math.min(Math.max(value, 0), 1);
|
|
123
|
+
if (!isFinite(adaptedValue)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
setVolumeLevel(adaptedValue);
|
|
127
|
+
mediaRef.current.volume = adaptedValue;
|
|
128
|
+
};
|
|
129
|
+
var handleToggleMute = function handleToggleMute() {
|
|
130
|
+
var nextIsMuted;
|
|
131
|
+
setIsMuted(function (prevIsMuted) {
|
|
132
|
+
nextIsMuted = !prevIsMuted;
|
|
133
|
+
return nextIsMuted;
|
|
134
|
+
});
|
|
135
|
+
var nextVolumeLevel = 0;
|
|
136
|
+
if (nextIsMuted) {
|
|
137
|
+
setBeforeMutedVolumeLevel(volumeLevel);
|
|
138
|
+
nextVolumeLevel = 0;
|
|
139
|
+
} else if (volumeLevel > 0.1) {
|
|
140
|
+
nextVolumeLevel = volumeLevel;
|
|
141
|
+
} else {
|
|
142
|
+
nextVolumeLevel = beforeMutedVolumeLevel;
|
|
143
|
+
}
|
|
144
|
+
handleChangeVolumeLevel(nextVolumeLevel);
|
|
145
|
+
};
|
|
146
|
+
var closeAudioSlider = function closeAudioSlider() {
|
|
147
|
+
setIsAudioSliderOpen(true);
|
|
148
|
+
clearTimeout(audioSliderTimerRef.current);
|
|
149
|
+
audioSliderTimerRef.current = setTimeout(function () {
|
|
150
|
+
setIsAudioSliderOpen(false);
|
|
151
|
+
}, [1000]);
|
|
152
|
+
};
|
|
153
|
+
var handleVolumeUp = function handleVolumeUp() {
|
|
154
|
+
setIsMuted(false);
|
|
155
|
+
handleChangeVolumeLevel((mediaRef.current.volume || 0) + 0.2);
|
|
156
|
+
closeAudioSlider();
|
|
157
|
+
};
|
|
158
|
+
var handleVolumeDown = function handleVolumeDown() {
|
|
159
|
+
var nextValue = (mediaRef.current.volume || 0) - 0.2;
|
|
160
|
+
handleChangeVolumeLevel(nextValue);
|
|
161
|
+
closeAudioSlider();
|
|
162
|
+
};
|
|
163
|
+
var handleSeek = function handleSeek(value) {
|
|
164
|
+
clearInterval(intervalRef.current);
|
|
165
|
+
var newTime = mediaRef.current.currentTime + value;
|
|
166
|
+
if (!isFinite(newTime)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
mediaRef.current.currentTime = newTime;
|
|
170
|
+
setTrackProgress(mediaRef.current.currentTime);
|
|
171
|
+
startTimer();
|
|
172
|
+
};
|
|
173
|
+
var handleCanPlay = function handleCanPlay() {
|
|
174
|
+
isReadyRef.current = true;
|
|
175
|
+
setDuration(mediaRef.current.duration);
|
|
176
|
+
handlePlay();
|
|
177
|
+
};
|
|
178
|
+
var handleKeyboardControls = function handleKeyboardControls(event) {
|
|
179
|
+
var keyCode = event.keyCode;
|
|
180
|
+
switch (keyCode) {
|
|
181
|
+
case 32: // space
|
|
182
|
+
case 75:
|
|
183
|
+
// 'k'
|
|
184
|
+
event.preventDefault();
|
|
185
|
+
return handlePlayPause();
|
|
186
|
+
case 39:
|
|
187
|
+
// arrowRight
|
|
188
|
+
event.preventDefault();
|
|
189
|
+
return handleSeek(5);
|
|
190
|
+
case 37:
|
|
191
|
+
// arrowLeft
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
return handleSeek(-5);
|
|
194
|
+
case 38:
|
|
195
|
+
// arrowUp
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
return handleVolumeUp();
|
|
198
|
+
case 40:
|
|
199
|
+
// arrowDown
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
return handleVolumeDown();
|
|
202
|
+
case 70:
|
|
203
|
+
// 'f'
|
|
204
|
+
if (typeof onKeyboardFullscreenKeyDown === 'function') {
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
onKeyboardFullscreenKeyDown();
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
case 77:
|
|
210
|
+
// 'm'
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
return handleToggleMute();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
var handlePlay = function handlePlay() {
|
|
216
|
+
if (!isReadyRef.current) return;
|
|
217
|
+
mediaRef.current.play();
|
|
218
|
+
};
|
|
219
|
+
var handlePause = function handlePause() {
|
|
220
|
+
if (!isReadyRef.current) return;
|
|
221
|
+
mediaRef.current.pause();
|
|
222
|
+
};
|
|
223
|
+
var onPlay = function onPlay() {
|
|
224
|
+
setIsPlaying(true);
|
|
225
|
+
startTimer();
|
|
226
|
+
};
|
|
227
|
+
var onPause = function onPause() {
|
|
228
|
+
setIsPlaying(false);
|
|
229
|
+
clearInterval(intervalRef.current);
|
|
230
|
+
};
|
|
231
|
+
var handlePlayPause = function handlePlayPause() {
|
|
232
|
+
if (mediaRef.current.paused) {
|
|
233
|
+
handlePlay();
|
|
234
|
+
} else {
|
|
235
|
+
handlePause();
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
useEffect(function () {
|
|
239
|
+
if (isPlayerReady && (mediaRef === null || mediaRef === void 0 ? void 0 : mediaRef.current) !== null) {
|
|
240
|
+
var _containerRef$current;
|
|
241
|
+
if (!dismissInitialLoad) {
|
|
242
|
+
mediaRef.current.load();
|
|
243
|
+
}
|
|
244
|
+
mediaRef.current.addEventListener('canplaythrough', handleCanPlay);
|
|
245
|
+
mediaRef.current.addEventListener('play', onPlay);
|
|
246
|
+
mediaRef.current.addEventListener('pause', onPause);
|
|
247
|
+
(_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.addEventListener('keydown', handleKeyboardControls);
|
|
248
|
+
|
|
249
|
+
// Pause and clean up on unmount
|
|
250
|
+
return function () {
|
|
251
|
+
var _containerRef$current2;
|
|
252
|
+
if (mediaRef.current) {
|
|
253
|
+
mediaRef.current.pause();
|
|
254
|
+
mediaRef.current.removeEventListener('canplaythrough', handleCanPlay);
|
|
255
|
+
mediaRef.current.removeEventListener('play', onPlay);
|
|
256
|
+
mediaRef.current.removeEventListener('pause', onPause);
|
|
257
|
+
}
|
|
258
|
+
(_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.removeEventListener('keydown', handleKeyboardControls);
|
|
259
|
+
resetControls();
|
|
260
|
+
clearInterval(intervalRef.current);
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}, [isPlayerReady, mediaRef]);
|
|
264
|
+
useEffect(function () {
|
|
265
|
+
checkAndSetIsMutedBySlider(volumeLevel);
|
|
266
|
+
}, [volumeLevel]);
|
|
267
|
+
return /*#__PURE__*/_jsxs(Styled.MediaControls, {
|
|
268
|
+
ref: controlsContainerRef,
|
|
269
|
+
children: [/*#__PURE__*/_jsx(Styled.SeekSlider, {
|
|
270
|
+
value: trackProgress || 0,
|
|
271
|
+
step: 1,
|
|
272
|
+
min: 0,
|
|
273
|
+
hideAnnotation: true,
|
|
274
|
+
labelTooltip: "off",
|
|
275
|
+
max: duration || 0,
|
|
276
|
+
$forceShow: trackEnded || !isPlaying || isSeeking,
|
|
277
|
+
onChange: onScrub,
|
|
278
|
+
onMouseUp: onScrubEnd
|
|
279
|
+
}), /*#__PURE__*/_jsxs(Styled.ControlsWrapper, {
|
|
280
|
+
children: [/*#__PURE__*/_jsxs(Styled.PlayButton, {
|
|
281
|
+
color: "basic",
|
|
282
|
+
size: "lg",
|
|
283
|
+
disabled: !isPlaying && !isReadyRef.current,
|
|
284
|
+
$disableHover: !isReadyRef.current,
|
|
285
|
+
onClick: handlePlayPause,
|
|
286
|
+
children: [/*#__PURE__*/_jsx(Styled.LoadingIcon, {
|
|
287
|
+
$hidden: isReadyRef.current,
|
|
288
|
+
size: 40
|
|
289
|
+
}), /*#__PURE__*/_jsx(Styled.Icon, {
|
|
290
|
+
$hidden: isPlaying,
|
|
291
|
+
icon: /*#__PURE__*/_jsx(Play, {
|
|
292
|
+
size: 18
|
|
293
|
+
})
|
|
294
|
+
}), /*#__PURE__*/_jsx(Styled.Icon, {
|
|
295
|
+
$hidden: !isPlaying,
|
|
296
|
+
icon: /*#__PURE__*/_jsx(Pause, {
|
|
297
|
+
size: 18
|
|
298
|
+
})
|
|
299
|
+
})]
|
|
300
|
+
}), /*#__PURE__*/_jsx(Styled.PlaybackButton, {
|
|
301
|
+
color: "basic",
|
|
302
|
+
onClick: handleTogglePlaybackMenu,
|
|
303
|
+
children: "".concat(playbackSpeed, "x")
|
|
304
|
+
}), /*#__PURE__*/_jsx(VolumeControl, {
|
|
305
|
+
value: volumeLevel,
|
|
306
|
+
onChange: handleChangeVolumeLevel,
|
|
307
|
+
isAudioSliderOpen: isAudioSliderOpen,
|
|
308
|
+
setIsAudioSliderOpen: setIsAudioSliderOpen,
|
|
309
|
+
isMuted: isMuted,
|
|
310
|
+
toggleMute: handleToggleMute,
|
|
311
|
+
closeAudioSlider: closeAudioSlider
|
|
312
|
+
}), /*#__PURE__*/_jsx(TimeLapse, {
|
|
313
|
+
trackProgress: trackProgress,
|
|
314
|
+
duration: duration
|
|
315
|
+
}), typeof extraControllers === 'function' && extraControllers()]
|
|
316
|
+
}), /*#__PURE__*/_jsx(PlaybackSpeedMenu, {
|
|
317
|
+
value: playbackSpeed,
|
|
318
|
+
onClose: handleTogglePlaybackMenu,
|
|
319
|
+
onClick: handleChangePlaybackSpeed,
|
|
320
|
+
anchor: playbackMenuAnchor
|
|
321
|
+
})]
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
export default MediaControls;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
var _excluded = ["icon"];
|
|
2
|
+
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13, _templateObject14, _templateObject15, _templateObject16, _templateObject17, _templateObject18;
|
|
3
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
4
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
5
|
+
function _taggedTemplateLiteral(e, t) { return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); }
|
|
6
|
+
import { cloneElement } from 'react';
|
|
7
|
+
import { FV, PC } from '@scaleflex/widget-common';
|
|
8
|
+
import styled, { css } from 'styled-components';
|
|
9
|
+
import { Slider as SfxSlider, Menu as SfxMenu, IconButton, Button } from '@scaleflex/ui/core';
|
|
10
|
+
import { Loading } from '@scaleflex/icons';
|
|
11
|
+
var MediaControls = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n display: flex;\n flex-direction: column;\n margin-top: -14px;\n"])));
|
|
12
|
+
var SeekSlider = styled(SfxSlider)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n appearance: none;\n height: 4px;\n border: 0;\n padding: 0;\n border-radius: 0;\n transition: height 150ms linear;\n\n .SfxSlider-rail {\n background: ", ";\n border: inherit;\n border-radius: inherit;\n }\n\n .SfxSlider-Track {\n background: ", ";\n border: inherit;\n border-radius: inherit;\n transition: height 100ms linear;\n }\n\n .SfxSlider-thumb {\n background: ", ";\n width: 0;\n height: 0;\n transition: width 150ms linear, height 150ms linear;\n transform: translate(0, -50%);\n }\n\n ", "\n\n &:hover {\n height: 6px;\n\n .SfxSlider-thumb {\n width: 15px;\n height: 15px;\n }\n\n .SfxSlider-Track {\n background: ", ";\n }\n }\n"])), function (_ref) {
|
|
13
|
+
var palette = _ref.theme.palette;
|
|
14
|
+
return palette[PC.IconsPlaceholder];
|
|
15
|
+
}, function (_ref2) {
|
|
16
|
+
var palette = _ref2.theme.palette;
|
|
17
|
+
return palette[PC.IconsMuted];
|
|
18
|
+
}, function (_ref3) {
|
|
19
|
+
var palette = _ref3.theme.palette;
|
|
20
|
+
return palette[PC.AccentStateless];
|
|
21
|
+
}, function (_ref4) {
|
|
22
|
+
var $forceShow = _ref4.$forceShow;
|
|
23
|
+
return $forceShow && css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n height: 6px;\n\n .SfxSlider-thumb {\n width: 15px;\n height: 15px;\n }\n\n .SfxSlider-Track {\n background: ", ";\n }\n "])), function (_ref5) {
|
|
24
|
+
var palette = _ref5.theme.palette;
|
|
25
|
+
return palette[PC.AccentStateless];
|
|
26
|
+
});
|
|
27
|
+
}, function (_ref6) {
|
|
28
|
+
var palette = _ref6.theme.palette;
|
|
29
|
+
return palette[PC.AccentStateless];
|
|
30
|
+
});
|
|
31
|
+
var ControlsWrapper = styled.div(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n width: 100%;\n display: flex;\n align-items: center;\n column-gap: 12px;\n padding: 10px calc(24px - 6px);\n"])));
|
|
32
|
+
var TimeLapse = styled.p(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n margin: 0;\n color: ", ";\n ", ";\n"])), function (_ref7) {
|
|
33
|
+
var palette = _ref7.theme.palette;
|
|
34
|
+
return palette[PC.TextSecondary];
|
|
35
|
+
}, function (_ref8) {
|
|
36
|
+
var typography = _ref8.theme.typography;
|
|
37
|
+
return typography.font[FV.LabelLargeEmphasis];
|
|
38
|
+
});
|
|
39
|
+
var Menu = styled(SfxMenu)(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n transition: all 200ms ease-out;\n margin-bottom: 5px;\n ", "\n"])), function (_ref9) {
|
|
40
|
+
var $isOpen = _ref9.$isOpen;
|
|
41
|
+
return !$isOpen && css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n opacity: 0;\n "])));
|
|
42
|
+
});
|
|
43
|
+
var VolumeSlider = styled(SfxSlider)(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n border: 0;\n width: 0;\n border-radius: 4px;\n height: 2px;\n transition: margin .2s cubic-bezier(0.4,0,1,1), width .2s cubic-bezier(0.4,0,1,1);\n\n .SfxSlider-rail {\n background: ", ";\n border: inherit;\n border-radius: inherit;\n }\n\n .SfxSlider-Track {\n background: ", ";\n border: inherit;\n transition: height 100ms linear;\n }\n\n .SfxSlider-thumb {\n background: ", ";\n transition: width 150ms linear, height 150ms linear;\n width: 8px;\n height: 8px;\n opacity: 0;\n transition: opacity 100ms ease-out;\n }\n"])), function (_ref10) {
|
|
44
|
+
var palette = _ref10.theme.palette;
|
|
45
|
+
return palette[PC.BorderPrimaryStateless];
|
|
46
|
+
}, function (_ref11) {
|
|
47
|
+
var palette = _ref11.theme.palette;
|
|
48
|
+
return palette[PC.IconsPrimary];
|
|
49
|
+
}, function (_ref12) {
|
|
50
|
+
var palette = _ref12.theme.palette;
|
|
51
|
+
return palette[PC.IconsPrimary];
|
|
52
|
+
});
|
|
53
|
+
var PlayButton = styled(IconButton)(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n position: relative;\n\n &:active, &:focus {\n background-color: transparent;\n }\n\n &:hover {\n background-color: transparent;\n\n ", "\n }\n"])), function (_ref13) {
|
|
54
|
+
var $disableHover = _ref13.$disableHover;
|
|
55
|
+
return $disableHover && css(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n background-color: transparent;\n "])));
|
|
56
|
+
});
|
|
57
|
+
var PlaybackButton = styled(Button)(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["\n border: 0;\n min-width: 40px;\n"])));
|
|
58
|
+
var LoadingIcon = styled(Loading)(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["\n position: absolute;\n animation: spinner 2s linear infinite;\n top: calc(50% - 20.5px);\n left: calc(50% - 20.5px);\n transition: opacity 100ms ease-in-out;\n color: ", ";\n\n ", "\n"])), function (_ref14) {
|
|
59
|
+
var palette = _ref14.theme.palette;
|
|
60
|
+
return palette[PC.AccentStateless];
|
|
61
|
+
}, function (_ref15) {
|
|
62
|
+
var $hidden = _ref15.$hidden;
|
|
63
|
+
return $hidden && css(_templateObject13 || (_templateObject13 = _taggedTemplateLiteral(["\n opacity: 0;\n visibility: hidden;\n "])));
|
|
64
|
+
});
|
|
65
|
+
var VolumeControlWrapper = styled.div(_templateObject14 || (_templateObject14 = _taggedTemplateLiteral(["\n display: flex;\n align-items: center;\n column-gap: 10px;\n\n", "\n\n &:hover ", " {\n width: 56px;\n\n .SfxSlider-thumb {\n opacity: 1;\n }\n }\n "])), function (_ref16) {
|
|
66
|
+
var $shown = _ref16.$shown;
|
|
67
|
+
return $shown && css(_templateObject15 || (_templateObject15 = _taggedTemplateLiteral(["\n ", " {\n width: 56px;\n\n .SfxSlider-thumb {\n opacity: 1;\n }\n }\n "])), VolumeSlider);
|
|
68
|
+
}, VolumeSlider);
|
|
69
|
+
var VolumeIconButton = styled(IconButton)(_templateObject16 || (_templateObject16 = _taggedTemplateLiteral(["\n position: relative;\n width: 40px;\n height: 40px;\n\n &:hover, &:active, &:focus {\n background-color: transparent;\n }\n"])));
|
|
70
|
+
var Icon = styled(function (_ref17) {
|
|
71
|
+
var icon = _ref17.icon,
|
|
72
|
+
props = _objectWithoutProperties(_ref17, _excluded);
|
|
73
|
+
return /*#__PURE__*/cloneElement(icon, props);
|
|
74
|
+
})(_templateObject17 || (_templateObject17 = _taggedTemplateLiteral(["\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transition: all 150ms ease-out;\n color: ", ";\n background: transparent;\n\n ", "\n"])), function (_ref18) {
|
|
75
|
+
var palette = _ref18.theme.palette;
|
|
76
|
+
return palette[PC.IconsPrimary];
|
|
77
|
+
}, function (_ref19) {
|
|
78
|
+
var $hidden = _ref19.$hidden;
|
|
79
|
+
return $hidden && css(_templateObject18 || (_templateObject18 = _taggedTemplateLiteral(["\n opacity: 0;\n visibility: hidden;\n "])));
|
|
80
|
+
});
|
|
81
|
+
var Styled = {
|
|
82
|
+
MediaControls: MediaControls,
|
|
83
|
+
ControlsWrapper: ControlsWrapper,
|
|
84
|
+
PlayButton: PlayButton,
|
|
85
|
+
PlaybackButton: PlaybackButton,
|
|
86
|
+
LoadingIcon: LoadingIcon,
|
|
87
|
+
SeekSlider: SeekSlider,
|
|
88
|
+
TimeLapse: TimeLapse,
|
|
89
|
+
Menu: Menu,
|
|
90
|
+
VolumeControlWrapper: VolumeControlWrapper,
|
|
91
|
+
VolumeSlider: VolumeSlider,
|
|
92
|
+
VolumeIconButton: VolumeIconButton,
|
|
93
|
+
Icon: Icon
|
|
94
|
+
};
|
|
95
|
+
export default Styled;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MenuItem } from '@scaleflex/ui/core';
|
|
2
|
+
import Styled from './MediaPlayer.styled';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
var PLAYBACK_OPTIONS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
5
|
+
var PlaybackSpeedMenu = function PlaybackSpeedMenu(_ref) {
|
|
6
|
+
var value = _ref.value,
|
|
7
|
+
anchor = _ref.anchor,
|
|
8
|
+
onClose = _ref.onClose,
|
|
9
|
+
onClick = _ref.onClick;
|
|
10
|
+
return /*#__PURE__*/_jsx(Styled.Menu, {
|
|
11
|
+
open: Boolean(anchor),
|
|
12
|
+
onClose: onClose,
|
|
13
|
+
anchorEl: anchor,
|
|
14
|
+
value: value,
|
|
15
|
+
position: "top-end",
|
|
16
|
+
$isOpen: Boolean(anchor),
|
|
17
|
+
children: PLAYBACK_OPTIONS.map(function (option) {
|
|
18
|
+
return /*#__PURE__*/_jsx(MenuItem, {
|
|
19
|
+
onClick: onClick(option),
|
|
20
|
+
children: option
|
|
21
|
+
}, option);
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
export default PlaybackSpeedMenu;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import formatSeconds from '@scaleflex/widget-utils/lib/formatSeconds';
|
|
2
|
+
import Styled from './MediaPlayer.styled';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
var formatSecondsToDuration = function formatSecondsToDuration(seconds) {
|
|
5
|
+
if (!seconds || !Number.isFinite(seconds)) return '00:00';
|
|
6
|
+
return formatSeconds(seconds);
|
|
7
|
+
};
|
|
8
|
+
var TimeLapse = function TimeLapse(_ref) {
|
|
9
|
+
var trackProgress = _ref.trackProgress,
|
|
10
|
+
duration = _ref.duration;
|
|
11
|
+
var formattedProgress = formatSecondsToDuration(trackProgress);
|
|
12
|
+
var formattedDuration = formatSecondsToDuration(duration);
|
|
13
|
+
return /*#__PURE__*/_jsx(Styled.TimeLapse, {
|
|
14
|
+
children: "".concat(formattedProgress, " / ").concat(formattedDuration)
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
export default TimeLapse;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export var defaultVideoPlayerOptions = {
|
|
2
|
+
responsive: false,
|
|
3
|
+
controls: false,
|
|
4
|
+
children: [],
|
|
5
|
+
userActions: {},
|
|
6
|
+
autoplay: true,
|
|
7
|
+
html5: {
|
|
8
|
+
nativeControlsForTouch: false,
|
|
9
|
+
vhs: {
|
|
10
|
+
overrideNative: true,
|
|
11
|
+
maxPlaylistRetries: 11,
|
|
12
|
+
// 11 is a random number for max retries not expected to have more than such a number?
|
|
13
|
+
limitRenditionByPlayerDimensions: true,
|
|
14
|
+
useDevicePixelRatio: true,
|
|
15
|
+
enableLowInitialPlaylist: false,
|
|
16
|
+
bandwidth: 10500000
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export var VIDEO_PLAYER_AUTO_QUALITY_ID = 'auto';
|
|
21
|
+
export var qualityLevelPixelToResolution = {
|
|
22
|
+
'480p': 'SD',
|
|
23
|
+
'720p': 'HD',
|
|
24
|
+
'1080p': 'FHD',
|
|
25
|
+
'1440p': '2K / QHD',
|
|
26
|
+
'2160p': '4K / UHD',
|
|
27
|
+
'4320p': '8K / FUHD'
|
|
28
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7;
|
|
2
|
+
function _taggedTemplateLiteral(e, t) { return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); }
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { PC, FV } from '@scaleflex/widget-common';
|
|
5
|
+
import { IconButton, Menu, MenuItem } from '@scaleflex/ui/core';
|
|
6
|
+
import StyledFileWindowPreviewBody from '@scaleflex/widget-explorer/lib/components/FileWindowPanel/Body/Body.styled';
|
|
7
|
+
var ExtraControllers = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n flex: 1;\n justify-content: flex-end;\n gap: 12px;\n"])));
|
|
8
|
+
var ExtraControllerBtn = styled(IconButton)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n display: inline-flex;\n"])));
|
|
9
|
+
var VideoPlayerWrapper = styled.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n flex-direction: column;\n"])));
|
|
10
|
+
var VideoNodeWrapper = styled.div(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n flex-grow: 1;\n height: 75%;\n width: 100%;\n position: relative;\n\n div[id^=\"vjs_video\"] {\n width: 100%;\n height: 100%;\n }\n\n video {\n width: 100%;\n height: 100%;\n object-fit: contain;\n outline: none;\n }\n"])));
|
|
11
|
+
var VideoPlayerControls = styled(StyledFileWindowPreviewBody.Footer)(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n background: ", ";\n padding: 0;\n"])), function (_ref) {
|
|
12
|
+
var theme = _ref.theme;
|
|
13
|
+
return theme.palette[PC.BackgroundStateless];
|
|
14
|
+
});
|
|
15
|
+
var QualityLevelsMenu = styled(Menu)(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n width: auto;\n"])));
|
|
16
|
+
var QualityLevelsMenuLabel = styled(MenuItem)(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n text-align: center;\n justify-content: center;\n color: ", ";\n ", ";\n"])), function (_ref2) {
|
|
17
|
+
var theme = _ref2.theme;
|
|
18
|
+
return theme.palette[PC.TextSecondary];
|
|
19
|
+
}, function (_ref3) {
|
|
20
|
+
var theme = _ref3.theme;
|
|
21
|
+
return theme.typography.font[FV.LabelMedium];
|
|
22
|
+
});
|
|
23
|
+
var Styled = {
|
|
24
|
+
ExtraControllers: ExtraControllers,
|
|
25
|
+
ExtraControllerBtn: ExtraControllerBtn,
|
|
26
|
+
VideoPlayerWrapper: VideoPlayerWrapper,
|
|
27
|
+
VideoNodeWrapper: VideoNodeWrapper,
|
|
28
|
+
VideoPlayerControls: VideoPlayerControls,
|
|
29
|
+
QualityLevelsMenu: QualityLevelsMenu,
|
|
30
|
+
QualityLevelsMenuLabel: QualityLevelsMenuLabel
|
|
31
|
+
};
|
|
32
|
+
export default Styled;
|