@scaleflex/widget-screen-capture 4.8.11 → 4.8.12
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/dist/style.css +155 -0
- package/dist/style.min.css +1 -0
- package/lib/CaptureScreen.js +77 -0
- package/lib/RecordButton.js +55 -0
- package/lib/ScreenRecIcon.js +41 -0
- package/lib/StopWatch.js +105 -0
- package/lib/StreamStatus.js +56 -0
- package/lib/SubmitButton.js +36 -0
- package/lib/common.slice.js +29 -0
- package/lib/defaultLocale.js +9 -0
- package/lib/index.js +438 -0
- package/lib/style.scss +149 -0
- package/package.json +3 -3
package/dist/style.css
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap");
|
|
2
|
+
.filerobot-ScreenCapture-container {
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
display: flex;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
align-items: center;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.filerobot-ScreenCapture-videoContainer {
|
|
12
|
+
width: 100%;
|
|
13
|
+
flex: 1;
|
|
14
|
+
flex-grow: 1;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
background-color: #37414B;
|
|
17
|
+
text-align: center;
|
|
18
|
+
position: relative;
|
|
19
|
+
}
|
|
20
|
+
.filerobot-size--md .filerobot-ScreenCapture-videoContainer {
|
|
21
|
+
max-width: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.filerobot-ScreenCapture-video {
|
|
25
|
+
max-width: 100%;
|
|
26
|
+
max-height: 100%;
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 0;
|
|
29
|
+
right: 0;
|
|
30
|
+
bottom: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
margin: auto;
|
|
33
|
+
outline: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.filerobot-ScreenCapture-buttonContainer {
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 75px;
|
|
39
|
+
border-top: 1px solid #eaeaea;
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
padding: 0 20px;
|
|
44
|
+
background-color: #fff;
|
|
45
|
+
}
|
|
46
|
+
[data-filerobot-theme=dark] .filerobot-ScreenCapture-buttonContainer {
|
|
47
|
+
background-color: #1f1f1f;
|
|
48
|
+
border-top: 1px solid #333;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.filerobot-ScreenCapture-button:focus {
|
|
52
|
+
outline: none;
|
|
53
|
+
}
|
|
54
|
+
.filerobot-ScreenCapture-button::-moz-focus-inner {
|
|
55
|
+
border: 0;
|
|
56
|
+
}
|
|
57
|
+
.filerobot-ScreenCapture-button:focus {
|
|
58
|
+
box-shadow: 0 0 0 3px rgba(82, 130, 219, 0.5);
|
|
59
|
+
}
|
|
60
|
+
.filerobot-ScreenCapture-button {
|
|
61
|
+
width: 45px;
|
|
62
|
+
height: 45px;
|
|
63
|
+
border-radius: 50%;
|
|
64
|
+
color: #fff;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
transition: all 0.3s;
|
|
67
|
+
}
|
|
68
|
+
[data-filerobot-theme=dark] .filerobot-ScreenCapture-button:focus {
|
|
69
|
+
outline: none;
|
|
70
|
+
}
|
|
71
|
+
[data-filerobot-theme=dark] .filerobot-ScreenCapture-button::-moz-focus-inner {
|
|
72
|
+
border: 0;
|
|
73
|
+
}
|
|
74
|
+
[data-filerobot-theme=dark] .filerobot-ScreenCapture-button:focus {
|
|
75
|
+
box-shadow: 0 0 0 2px rgba(170, 225, 255, 0.85);
|
|
76
|
+
}
|
|
77
|
+
.filerobot-size--md .filerobot-ScreenCapture-button {
|
|
78
|
+
width: 60px;
|
|
79
|
+
height: 60px;
|
|
80
|
+
}
|
|
81
|
+
.filerobot-ScreenCapture-button:hover {
|
|
82
|
+
background-color: rgb(210.5769230769, 26.9230769231, 45.1923076923);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.filerobot-ScreenCapture-button svg {
|
|
86
|
+
width: 30px;
|
|
87
|
+
height: 30px;
|
|
88
|
+
max-width: 100%;
|
|
89
|
+
max-height: 100%;
|
|
90
|
+
display: inline-block;
|
|
91
|
+
vertical-align: text-top;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
fill: currentColor;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.filerobot-ScreenCapture-button--submit {
|
|
97
|
+
background-color: #5282DB;
|
|
98
|
+
margin-left: 12px;
|
|
99
|
+
}
|
|
100
|
+
.filerobot-ScreenCapture-button--submit:hover {
|
|
101
|
+
background-color: rgb(60.8923444976, 114.7488038278, 214.6076555024);
|
|
102
|
+
}
|
|
103
|
+
.filerobot-ScreenCapture-button--submit:disabled {
|
|
104
|
+
background-color: #939393;
|
|
105
|
+
cursor: default;
|
|
106
|
+
}
|
|
107
|
+
.filerobot-ScreenCapture-button--submit:disabled:hover {
|
|
108
|
+
background-color: #eaeaea;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.filerobot-ScreenCapture-title {
|
|
112
|
+
font-size: 22px;
|
|
113
|
+
line-height: 1.35;
|
|
114
|
+
font-weight: 400;
|
|
115
|
+
margin: 0;
|
|
116
|
+
margin-bottom: 5px;
|
|
117
|
+
padding: 0 15px;
|
|
118
|
+
max-width: 500px;
|
|
119
|
+
text-align: center;
|
|
120
|
+
color: #333;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.filerobot-ScreenCapture-icon--stream {
|
|
124
|
+
position: absolute;
|
|
125
|
+
right: 0;
|
|
126
|
+
top: 0;
|
|
127
|
+
margin: 1rem;
|
|
128
|
+
z-index: 1;
|
|
129
|
+
}
|
|
130
|
+
.filerobot-ScreenCapture-icon--stream svg {
|
|
131
|
+
fill: #939393;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.filerobot-ScreenCapture-icon--streamActive svg {
|
|
135
|
+
animation: filerobot-ScreenCapture-icon--blink 1s cubic-bezier(0.47, 0, 0.75, 0.72) infinite;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@keyframes filerobot-ScreenCapture-icon--blink {
|
|
139
|
+
0% {
|
|
140
|
+
fill: #5282DB;
|
|
141
|
+
}
|
|
142
|
+
50% {
|
|
143
|
+
fill: #939393;
|
|
144
|
+
}
|
|
145
|
+
100% {
|
|
146
|
+
fill: #5282DB;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
.filerobot-ScreenCapture-button--video {
|
|
150
|
+
color: #fff;
|
|
151
|
+
background: #e32437;
|
|
152
|
+
}
|
|
153
|
+
.filerobot-ScreenCapture-button--video:hover {
|
|
154
|
+
background-color: rgb(187.967611336, 24.032388664, 40.3400809717);
|
|
155
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap");.filerobot-ScreenCapture-container{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;width:100%}.filerobot-ScreenCapture-videoContainer{background-color:#37414b;flex:1;flex-grow:1;overflow:hidden;position:relative;text-align:center;width:100%}.filerobot-size--md .filerobot-ScreenCapture-videoContainer{max-width:100%}.filerobot-ScreenCapture-video{bottom:0;left:0;margin:auto;max-height:100%;max-width:100%;outline:none;position:absolute;right:0;top:0}.filerobot-ScreenCapture-buttonContainer{align-items:center;background-color:#fff;border-top:1px solid #eaeaea;display:flex;height:75px;justify-content:center;padding:0 20px;width:100%}[data-filerobot-theme=dark] .filerobot-ScreenCapture-buttonContainer{background-color:#1f1f1f;border-top:1px solid #333}.filerobot-ScreenCapture-button:focus{outline:none}.filerobot-ScreenCapture-button::-moz-focus-inner{border:0}.filerobot-ScreenCapture-button:focus{box-shadow:0 0 0 3px rgba(82,130,219,.5)}.filerobot-ScreenCapture-button{border-radius:50%;color:#fff;cursor:pointer;height:45px;transition:all .3s;width:45px}[data-filerobot-theme=dark] .filerobot-ScreenCapture-button:focus{outline:none}[data-filerobot-theme=dark] .filerobot-ScreenCapture-button::-moz-focus-inner{border:0}[data-filerobot-theme=dark] .filerobot-ScreenCapture-button:focus{box-shadow:0 0 0 2px rgba(170,225,255,.85)}.filerobot-size--md .filerobot-ScreenCapture-button{height:60px;width:60px}.filerobot-ScreenCapture-button:hover{background-color:#d31b2d}.filerobot-ScreenCapture-button svg{display:inline-block;height:30px;max-height:100%;max-width:100%;overflow:hidden;vertical-align:text-top;width:30px;fill:currentColor}.filerobot-ScreenCapture-button--submit{background-color:#5282db;margin-left:12px}.filerobot-ScreenCapture-button--submit:hover{background-color:#3d73d7}.filerobot-ScreenCapture-button--submit:disabled{background-color:#939393;cursor:default}.filerobot-ScreenCapture-button--submit:disabled:hover{background-color:#eaeaea}.filerobot-ScreenCapture-title{color:#333;font-size:22px;font-weight:400;line-height:1.35;margin:0 0 5px;max-width:500px;padding:0 15px;text-align:center}.filerobot-ScreenCapture-icon--stream{margin:1rem;position:absolute;right:0;top:0;z-index:1}.filerobot-ScreenCapture-icon--stream svg{fill:#939393}.filerobot-ScreenCapture-icon--streamActive svg{animation:filerobot-ScreenCapture-icon--blink 1s cubic-bezier(.47,0,.75,.72) infinite}@keyframes filerobot-ScreenCapture-icon--blink{0%{fill:#5282db}50%{fill:#939393}to{fill:#5282db}}.filerobot-ScreenCapture-button--video{background:#e32437;color:#fff}.filerobot-ScreenCapture-button--video:hover{background-color:#bc1828}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import RecordButton from './RecordButton';
|
|
3
|
+
import SubmitButton from './SubmitButton';
|
|
4
|
+
import StopWatch from './StopWatch';
|
|
5
|
+
import StreamStatus from './StreamStatus';
|
|
6
|
+
import { useSelector } from 'react-redux';
|
|
7
|
+
import { selectScreenCaptureCommonState } from './common.slice';
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
var RecorderScreen = function RecorderScreen(_ref) {
|
|
10
|
+
var onStartRecording = _ref.onStartRecording,
|
|
11
|
+
onStopRecording = _ref.onStopRecording,
|
|
12
|
+
onStop = _ref.onStop,
|
|
13
|
+
onSubmit = _ref.onSubmit,
|
|
14
|
+
i18n = _ref.i18n,
|
|
15
|
+
videoStream = _ref.stream;
|
|
16
|
+
var recordedVideo = useSelector(function (state) {
|
|
17
|
+
return selectScreenCaptureCommonState(state).recordedVideo;
|
|
18
|
+
});
|
|
19
|
+
var recording = useSelector(function (state) {
|
|
20
|
+
return selectScreenCaptureCommonState(state).recording;
|
|
21
|
+
});
|
|
22
|
+
var videoElementRef = useRef();
|
|
23
|
+
var videoElement = videoElementRef === null || videoElementRef === void 0 ? void 0 : videoElementRef.current;
|
|
24
|
+
useEffect(function () {
|
|
25
|
+
return function () {
|
|
26
|
+
onStop();
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
if (videoElement) {
|
|
30
|
+
// show stream
|
|
31
|
+
if (recording || !recordedVideo && !recording) {
|
|
32
|
+
videoElement.muted = true;
|
|
33
|
+
videoElement.autoPlay = true;
|
|
34
|
+
videoElement.srcObject = videoStream;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// show preview
|
|
38
|
+
if (recordedVideo && !recording) {
|
|
39
|
+
videoElement.muted = false;
|
|
40
|
+
videoElement.controls = true;
|
|
41
|
+
videoElement.src = recordedVideo;
|
|
42
|
+
|
|
43
|
+
// reset srcObject in dom. If not resetted, stream sticks in element
|
|
44
|
+
videoElement.srcObject = undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
48
|
+
className: "filerobot filerobot-ScreenCapture-container",
|
|
49
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
50
|
+
className: "filerobot-ScreenCapture-videoContainer",
|
|
51
|
+
children: [/*#__PURE__*/_jsx(StreamStatus, {
|
|
52
|
+
i18n: i18n
|
|
53
|
+
}), /*#__PURE__*/_jsx("video", {
|
|
54
|
+
ref: videoElementRef,
|
|
55
|
+
className: "filerobot-ScreenCapture-video",
|
|
56
|
+
playsInline: true,
|
|
57
|
+
autoPlay: true
|
|
58
|
+
}), /*#__PURE__*/_jsx(StopWatch, {
|
|
59
|
+
i18n: i18n
|
|
60
|
+
})]
|
|
61
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
62
|
+
className: "filerobot-ScreenCapture-buttonContainer",
|
|
63
|
+
children: [/*#__PURE__*/_jsx(RecordButton, {
|
|
64
|
+
recording: recording,
|
|
65
|
+
onStartRecording: onStartRecording,
|
|
66
|
+
onStopRecording: onStopRecording,
|
|
67
|
+
i18n: i18n
|
|
68
|
+
}), /*#__PURE__*/_jsx(SubmitButton, {
|
|
69
|
+
recording: recording,
|
|
70
|
+
recordedVideo: recordedVideo,
|
|
71
|
+
onSubmit: onSubmit,
|
|
72
|
+
i18n: i18n
|
|
73
|
+
})]
|
|
74
|
+
})]
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
export default RecorderScreen;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Control screen capture recording. Will show record or stop button.
|
|
4
|
+
*/
|
|
5
|
+
export default function RecordButton(_ref) {
|
|
6
|
+
var recording = _ref.recording,
|
|
7
|
+
onStartRecording = _ref.onStartRecording,
|
|
8
|
+
onStopRecording = _ref.onStopRecording,
|
|
9
|
+
i18n = _ref.i18n;
|
|
10
|
+
if (recording) {
|
|
11
|
+
return /*#__PURE__*/_jsx("button", {
|
|
12
|
+
className: "filerobot-u-reset filerobot-c-btn filerobot-ScreenCapture-button filerobot-ScreenCapture-button--video filerobot-ScreenCapture-button--stop-rec",
|
|
13
|
+
type: "button",
|
|
14
|
+
title: i18n('webcamStopRecordingTitle'),
|
|
15
|
+
"aria-label": i18n('webcamStopRecordingTitle'),
|
|
16
|
+
onClick: onStopRecording,
|
|
17
|
+
"data-filerobot-super-focusable": true,
|
|
18
|
+
children: /*#__PURE__*/_jsx("svg", {
|
|
19
|
+
"aria-hidden": "true",
|
|
20
|
+
focusable: "false",
|
|
21
|
+
className: "filerobot-c-icon",
|
|
22
|
+
width: "100",
|
|
23
|
+
height: "100",
|
|
24
|
+
viewBox: "0 0 100 100",
|
|
25
|
+
children: /*#__PURE__*/_jsx("rect", {
|
|
26
|
+
x: "15",
|
|
27
|
+
y: "15",
|
|
28
|
+
width: "70",
|
|
29
|
+
height: "70"
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return /*#__PURE__*/_jsx("button", {
|
|
35
|
+
className: "filerobot-u-reset filerobot-c-btn filerobot-ScreenCapture-button filerobot-ScreenCapture-button--video",
|
|
36
|
+
type: "button",
|
|
37
|
+
title: i18n('screenCaptureStartCapturingTitle'),
|
|
38
|
+
"aria-label": i18n('screenCaptureStopCapturingLabel'),
|
|
39
|
+
onClick: onStartRecording,
|
|
40
|
+
"data-filerobot-super-focusable": true,
|
|
41
|
+
children: /*#__PURE__*/_jsx("svg", {
|
|
42
|
+
"aria-hidden": "true",
|
|
43
|
+
focusable: "false",
|
|
44
|
+
className: "filerobot-c-icon",
|
|
45
|
+
width: "100",
|
|
46
|
+
height: "100",
|
|
47
|
+
viewBox: "0 0 100 100",
|
|
48
|
+
children: /*#__PURE__*/_jsx("circle", {
|
|
49
|
+
cx: "50",
|
|
50
|
+
cy: "50",
|
|
51
|
+
r: "40"
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
function _objectDestructuringEmpty(t) { if (null == t) throw new TypeError("Cannot destructure " + t); }
|
|
9
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
10
|
+
var ScreenRecIcon = function ScreenRecIcon() {
|
|
11
|
+
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
12
|
+
props = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
|
|
13
|
+
return /*#__PURE__*/_jsx("svg", _objectSpread(_objectSpread({
|
|
14
|
+
"aria-hidden": "true",
|
|
15
|
+
focusable: "false",
|
|
16
|
+
width: "32",
|
|
17
|
+
height: "32",
|
|
18
|
+
viewBox: "0 0 32 32"
|
|
19
|
+
}, props), {}, {
|
|
20
|
+
children: /*#__PURE__*/_jsxs("g", {
|
|
21
|
+
fill: "none",
|
|
22
|
+
fillRule: "evenodd",
|
|
23
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
24
|
+
fill: "#2C3E50",
|
|
25
|
+
width: "32",
|
|
26
|
+
height: "32",
|
|
27
|
+
rx: "16"
|
|
28
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
29
|
+
d: "M24.182 9H7.818C6.81 9 6 9.742 6 10.667v10c0 .916.81 1.666 1.818 1.666h4.546V24h7.272v-1.667h4.546c1 0 1.809-.75 1.809-1.666l.009-10C26 9.742 25.182 9 24.182 9zM24 21H8V11h16v10z",
|
|
30
|
+
fill: "#FFF",
|
|
31
|
+
fillRule: "nonzero"
|
|
32
|
+
}), /*#__PURE__*/_jsx("circle", {
|
|
33
|
+
fill: "#FFF",
|
|
34
|
+
cx: "16",
|
|
35
|
+
cy: "16",
|
|
36
|
+
r: "2"
|
|
37
|
+
})]
|
|
38
|
+
})
|
|
39
|
+
}));
|
|
40
|
+
};
|
|
41
|
+
export default ScreenRecIcon;
|
package/lib/StopWatch.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
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 } from 'react';
|
|
8
|
+
import { useSelector } from 'react-redux';
|
|
9
|
+
import { selectScreenCaptureCommonState } from './common.slice';
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
var wrapperStyle = {
|
|
12
|
+
width: '100%',
|
|
13
|
+
height: '100%',
|
|
14
|
+
display: 'flex'
|
|
15
|
+
};
|
|
16
|
+
var overlayStyle = {
|
|
17
|
+
position: 'absolute',
|
|
18
|
+
width: '100%',
|
|
19
|
+
height: '100%',
|
|
20
|
+
background: 'black',
|
|
21
|
+
opacity: 0.7
|
|
22
|
+
};
|
|
23
|
+
var infoContainerStyle = {
|
|
24
|
+
marginLeft: 'auto',
|
|
25
|
+
marginRight: 'auto',
|
|
26
|
+
marginTop: 'auto',
|
|
27
|
+
marginBottom: 'auto',
|
|
28
|
+
zIndex: 1,
|
|
29
|
+
color: 'white'
|
|
30
|
+
};
|
|
31
|
+
var infotextStyle = {
|
|
32
|
+
marginLeft: 'auto',
|
|
33
|
+
marginRight: 'auto',
|
|
34
|
+
marginBottom: '1rem',
|
|
35
|
+
fontSize: '1.5rem'
|
|
36
|
+
};
|
|
37
|
+
var timeStyle = {
|
|
38
|
+
display: 'block',
|
|
39
|
+
fontWeight: 'bold',
|
|
40
|
+
marginLeft: 'auto',
|
|
41
|
+
marginRight: 'auto',
|
|
42
|
+
fontSize: '3rem',
|
|
43
|
+
fontFamily: 'Courier New'
|
|
44
|
+
};
|
|
45
|
+
var StopWatch = function StopWatch(_ref) {
|
|
46
|
+
var i18n = _ref.i18n;
|
|
47
|
+
var recording = useSelector(function (state) {
|
|
48
|
+
return selectScreenCaptureCommonState(state).recording;
|
|
49
|
+
});
|
|
50
|
+
var _useState = useState(0),
|
|
51
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
52
|
+
elapsedTime = _useState2[0],
|
|
53
|
+
setElapsedTime = _useState2[1];
|
|
54
|
+
var timerRef = useRef(null);
|
|
55
|
+
var isTimerRunning = useRef(false);
|
|
56
|
+
var startTimer = function startTimer() {
|
|
57
|
+
_timerTick();
|
|
58
|
+
isTimerRunning.current = true;
|
|
59
|
+
};
|
|
60
|
+
var resetTimer = function resetTimer() {
|
|
61
|
+
clearTimeout(timerRef.current);
|
|
62
|
+
setElapsedTime(0);
|
|
63
|
+
isTimerRunning.current = false;
|
|
64
|
+
};
|
|
65
|
+
var _timerTick = function timerTick() {
|
|
66
|
+
timerRef.current = setTimeout(function () {
|
|
67
|
+
setElapsedTime(function (elapsedTime) {
|
|
68
|
+
return elapsedTime + 1;
|
|
69
|
+
});
|
|
70
|
+
_timerTick();
|
|
71
|
+
}, 1000);
|
|
72
|
+
};
|
|
73
|
+
var fmtMSS = function fmtMSS(s) {
|
|
74
|
+
return (s - (s %= 60)) / 60 + (s > 9 ? ':' : ':0') + s;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// second to minutes and seconds
|
|
78
|
+
var minAndSec = fmtMSS(elapsedTime);
|
|
79
|
+
if (recording && !(isTimerRunning !== null && isTimerRunning !== void 0 && isTimerRunning.current)) {
|
|
80
|
+
startTimer();
|
|
81
|
+
}
|
|
82
|
+
if (!recording && isTimerRunning !== null && isTimerRunning !== void 0 && isTimerRunning.current) {
|
|
83
|
+
resetTimer();
|
|
84
|
+
}
|
|
85
|
+
if (recording) {
|
|
86
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
87
|
+
style: wrapperStyle,
|
|
88
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
89
|
+
style: overlayStyle
|
|
90
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
91
|
+
style: infoContainerStyle,
|
|
92
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
93
|
+
style: infotextStyle,
|
|
94
|
+
children: i18n('screenCaptureRecordingText')
|
|
95
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
96
|
+
style: timeStyle,
|
|
97
|
+
children: minAndSec
|
|
98
|
+
})]
|
|
99
|
+
})]
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
export default StopWatch;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useSelector } from 'react-redux';
|
|
2
|
+
import { selectScreenCaptureCommonState } from './common.slice';
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
export default (function (_ref) {
|
|
5
|
+
var i18n = _ref.i18n;
|
|
6
|
+
var streamActive = useSelector(function (state) {
|
|
7
|
+
return selectScreenCaptureCommonState(state).streamActive;
|
|
8
|
+
});
|
|
9
|
+
if (streamActive) {
|
|
10
|
+
return /*#__PURE__*/_jsx("div", {
|
|
11
|
+
title: i18n('screenCaptureStreamActive'),
|
|
12
|
+
"aria-label": i18n('screenCaptureStreamActive'),
|
|
13
|
+
className: "filerobot-ScreenCapture-icon--stream filerobot-ScreenCapture-icon--streamActive",
|
|
14
|
+
children: /*#__PURE__*/_jsxs("svg", {
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
focusable: "false",
|
|
17
|
+
width: "24",
|
|
18
|
+
height: "24",
|
|
19
|
+
viewBox: "0 0 24 24",
|
|
20
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
21
|
+
d: "M0 0h24v24H0z",
|
|
22
|
+
opacity: ".1",
|
|
23
|
+
fill: "none"
|
|
24
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
25
|
+
d: "M0 0h24v24H0z",
|
|
26
|
+
fill: "none"
|
|
27
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
28
|
+
d: "M1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm18-7H5v1.63c3.96 1.28 7.09 4.41 8.37 8.37H19V7zM1 10v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11zm20-7H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
|
|
29
|
+
})]
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
return /*#__PURE__*/_jsx("div", {
|
|
34
|
+
title: i18n('screenCaptureStreamPassiveTitle'),
|
|
35
|
+
"aria-label": i18n('screenCaptureStreamPassiveTitle'),
|
|
36
|
+
className: "filerobot-ScreenCapture-icon--stream",
|
|
37
|
+
children: /*#__PURE__*/_jsxs("svg", {
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
focusable: "false",
|
|
40
|
+
width: "24",
|
|
41
|
+
height: "24",
|
|
42
|
+
viewBox: "0 0 24 24",
|
|
43
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
44
|
+
d: "M0 0h24v24H0z",
|
|
45
|
+
opacity: ".1",
|
|
46
|
+
fill: "none"
|
|
47
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
48
|
+
d: "M0 0h24v24H0z",
|
|
49
|
+
fill: "none"
|
|
50
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
51
|
+
d: "M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z"
|
|
52
|
+
})]
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Submit recorded video to filerobot. Enabled when file is available
|
|
4
|
+
*/
|
|
5
|
+
export default function SubmitButton(_ref) {
|
|
6
|
+
var recordedVideo = _ref.recordedVideo,
|
|
7
|
+
recording = _ref.recording,
|
|
8
|
+
onSubmit = _ref.onSubmit,
|
|
9
|
+
i18n = _ref.i18n;
|
|
10
|
+
if (recordedVideo && !recording) {
|
|
11
|
+
return /*#__PURE__*/_jsx("button", {
|
|
12
|
+
className: "filerobot-u-reset filerobot-c-btn filerobot-ScreenCapture-button filerobot-ScreenCapture-button--submit",
|
|
13
|
+
type: "button",
|
|
14
|
+
title: i18n('screenCaptureSubmitRecordedFileTitle'),
|
|
15
|
+
"aria-label": i18n('screenCaptureSubmitRecordedFileTitle'),
|
|
16
|
+
onClick: onSubmit,
|
|
17
|
+
"data-filerobot-super-focusable": true,
|
|
18
|
+
children: /*#__PURE__*/_jsxs("svg", {
|
|
19
|
+
"aria-hidden": "true",
|
|
20
|
+
focusable: "false",
|
|
21
|
+
className: "filerobot-c-icon",
|
|
22
|
+
width: "48",
|
|
23
|
+
height: "48",
|
|
24
|
+
viewBox: "0 0 48 48",
|
|
25
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
26
|
+
d: "M0 0h48v48h-48z",
|
|
27
|
+
fill: "none"
|
|
28
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
29
|
+
d: "M38.71 20.07c-1.36-6.88-7.43-12.07-14.71-12.07-5.78 0-10.79 3.28-13.3 8.07-6.01.65-10.7 5.74-10.7 11.93 0 6.63 5.37 12 12 12h26c5.52 0 10-4.48 10-10 0-5.28-4.11-9.56-9.29-9.93zm-10.71 5.93v8h-8v-8h-6l10-10 10 10h-6z"
|
|
30
|
+
})]
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
8
|
+
import { PLUGINS_IDS } from '@scaleflex/widget-utils/lib/constants';
|
|
9
|
+
var initialState = {
|
|
10
|
+
streamActive: false,
|
|
11
|
+
audioStreamActive: false,
|
|
12
|
+
recording: false,
|
|
13
|
+
recordedVideo: null
|
|
14
|
+
};
|
|
15
|
+
var commonSlice = createSlice({
|
|
16
|
+
name: PLUGINS_IDS.SCREEN_CAPTURE,
|
|
17
|
+
initialState: initialState,
|
|
18
|
+
reducers: {
|
|
19
|
+
screenCaptureCommonStateUpdated: function screenCaptureCommonStateUpdated(state, action) {
|
|
20
|
+
return _objectSpread(_objectSpread({}, state), action.payload);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var screenCaptureCommonStateUpdated = commonSlice.actions.screenCaptureCommonStateUpdated;
|
|
25
|
+
export { screenCaptureCommonStateUpdated };
|
|
26
|
+
export var selectScreenCaptureCommonState = function selectScreenCaptureCommonState(state) {
|
|
27
|
+
return state[PLUGINS_IDS.SCREEN_CAPTURE];
|
|
28
|
+
};
|
|
29
|
+
export default commonSlice.reducer;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
screenCaptureStartCapturingTitle: 'Begin screen capturing',
|
|
3
|
+
screenCaptureStopCapturingLabel: 'Stop screen capturing',
|
|
4
|
+
screenCaptureSubmitRecordedFileTitle: 'Submit captured video',
|
|
5
|
+
screenCaptureStreamActive: 'Stream active',
|
|
6
|
+
screenCaptureStreamPassiveTitle: 'Stream passive',
|
|
7
|
+
screenCaptureMicDisabledInfo: 'Microphone access denied by user',
|
|
8
|
+
screenCaptureRecordingText: 'Recording'
|
|
9
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
6
|
+
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
7
|
+
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
8
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
9
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
10
|
+
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
11
|
+
function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
|
|
12
|
+
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
|
|
13
|
+
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
14
|
+
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
|
|
15
|
+
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
|
|
16
|
+
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
|
|
17
|
+
import { createElement } from 'react';
|
|
18
|
+
import { Plugin } from '@scaleflex/widget-core';
|
|
19
|
+
import Explorer from '@scaleflex/widget-explorer';
|
|
20
|
+
import Translator from '@scaleflex/widget-utils/lib/Translator';
|
|
21
|
+
import getFileTypeExtension from '@scaleflex/widget-utils/lib/getFileTypeExtension';
|
|
22
|
+
import { PLUGINS_IDS } from '@scaleflex/widget-utils/lib/constants';
|
|
23
|
+
import defaultLocale from './defaultLocale';
|
|
24
|
+
import ScreenRecIcon from './ScreenRecIcon';
|
|
25
|
+
import CaptureScreen from './CaptureScreen';
|
|
26
|
+
import screenCaptureReducer, { screenCaptureCommonStateUpdated } from './common.slice';
|
|
27
|
+
// TODO: find a way to show version of the current plugin
|
|
28
|
+
// why solution below isn't good?
|
|
29
|
+
// first import doesn't work with webpack 5 as it was deprecated
|
|
30
|
+
// second import fixes webpack 5 issue as it was mentioned in their docs
|
|
31
|
+
// but it exposes our package.json to the client and it is mentioned as security rist in mutiple places
|
|
32
|
+
// https://github.com/axelpale/genversion
|
|
33
|
+
// https://stackoverflow.com/questions/64993118/error-should-not-import-the-named-export-version-imported-as-version
|
|
34
|
+
// https://stackoverflow.com/questions/9153571/is-there-a-way-to-get-version-from-package-json-in-nodejs-code/10855054#10855054
|
|
35
|
+
// import { version } from '../package.json'
|
|
36
|
+
// import packageInfo from '../package.json'
|
|
37
|
+
|
|
38
|
+
// Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
|
39
|
+
function getMediaDevices() {
|
|
40
|
+
// check if screen capturing is supported
|
|
41
|
+
/* eslint-disable */
|
|
42
|
+
if (navigator && navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia && window && window.MediaRecorder) {
|
|
43
|
+
return navigator.mediaDevices;
|
|
44
|
+
}
|
|
45
|
+
/* eslint-enable */
|
|
46
|
+
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Screen capture
|
|
52
|
+
*/
|
|
53
|
+
var ScreenCapture = /*#__PURE__*/function (_Plugin) {
|
|
54
|
+
// static VERSION = packageInfo.version
|
|
55
|
+
|
|
56
|
+
function ScreenCapture(filerobot) {
|
|
57
|
+
var _this;
|
|
58
|
+
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
59
|
+
_classCallCheck(this, ScreenCapture);
|
|
60
|
+
_this = _callSuper(this, ScreenCapture, [filerobot, opts]);
|
|
61
|
+
_this.mediaDevices = getMediaDevices();
|
|
62
|
+
_this.protocol = location.protocol.match(/https/i) ? 'https' : 'http';
|
|
63
|
+
_this.id = PLUGINS_IDS.SCREEN_CAPTURE;
|
|
64
|
+
_this.title = _this.opts.title || 'Screen cast';
|
|
65
|
+
_this.type = 'acquirer';
|
|
66
|
+
_this.icon = ScreenRecIcon;
|
|
67
|
+
_this.defaultLocale = {
|
|
68
|
+
strings: defaultLocale
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// set default options
|
|
72
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints
|
|
73
|
+
var defaultOptions = {
|
|
74
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#Properties_of_shared_screen_tracks
|
|
75
|
+
displayMediaConstraints: {
|
|
76
|
+
video: {
|
|
77
|
+
width: 1280,
|
|
78
|
+
height: 720,
|
|
79
|
+
frameRate: {
|
|
80
|
+
ideal: 3,
|
|
81
|
+
max: 5
|
|
82
|
+
},
|
|
83
|
+
cursor: 'motion',
|
|
84
|
+
displaySurface: 'monitor'
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints/audio
|
|
88
|
+
userMediaConstraints: {
|
|
89
|
+
audio: true
|
|
90
|
+
},
|
|
91
|
+
preferredVideoMimeType: 'video/webm'
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// merge default options with the ones set by user
|
|
95
|
+
_this.opts = _objectSpread(_objectSpread({}, defaultOptions), opts);
|
|
96
|
+
|
|
97
|
+
// i18n
|
|
98
|
+
_this.translator = new Translator([_this.defaultLocale, _this.filerobot.locale, _this.opts.locale]);
|
|
99
|
+
_this.i18n = _this.translator.translate.bind(_this.translator);
|
|
100
|
+
_this.i18nArray = _this.translator.translateArray.bind(_this.translator);
|
|
101
|
+
|
|
102
|
+
// filerobot plugin class related
|
|
103
|
+
_this.install = _this.install.bind(_this);
|
|
104
|
+
_this.render = _this.render.bind(_this);
|
|
105
|
+
|
|
106
|
+
// screen capturer related
|
|
107
|
+
_this.start = _this.start.bind(_this);
|
|
108
|
+
_this.stop = _this.stop.bind(_this);
|
|
109
|
+
_this.startRecording = _this.startRecording.bind(_this);
|
|
110
|
+
_this.stopRecording = _this.stopRecording.bind(_this);
|
|
111
|
+
_this.submit = _this.submit.bind(_this);
|
|
112
|
+
_this.streamInterrupted = _this.streamInactivated.bind(_this);
|
|
113
|
+
|
|
114
|
+
// initialize
|
|
115
|
+
_this.captureActive = false;
|
|
116
|
+
_this.capturedMediaFile = null;
|
|
117
|
+
return _this;
|
|
118
|
+
}
|
|
119
|
+
_inherits(ScreenCapture, _Plugin);
|
|
120
|
+
return _createClass(ScreenCapture, [{
|
|
121
|
+
key: "install",
|
|
122
|
+
value: function install() {
|
|
123
|
+
// Return if browser doesn’t support getDisplayMedia and
|
|
124
|
+
if (!this.mediaDevices) {
|
|
125
|
+
this.filerobot.log('Screen recorder access is not supported', 'error');
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
if (Explorer) {
|
|
129
|
+
this.mount(Explorer, this);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}, {
|
|
133
|
+
key: "uninstall",
|
|
134
|
+
value: function uninstall() {
|
|
135
|
+
if (this.videoStream) {
|
|
136
|
+
this.stop();
|
|
137
|
+
}
|
|
138
|
+
this.unmount();
|
|
139
|
+
}
|
|
140
|
+
}, {
|
|
141
|
+
key: "setPluginCommonState",
|
|
142
|
+
value: function setPluginCommonState(update) {
|
|
143
|
+
this.dispatch(screenCaptureCommonStateUpdated(update));
|
|
144
|
+
}
|
|
145
|
+
}, {
|
|
146
|
+
key: "getPluginReducer",
|
|
147
|
+
value: function getPluginReducer() {
|
|
148
|
+
return screenCaptureReducer;
|
|
149
|
+
}
|
|
150
|
+
}, {
|
|
151
|
+
key: "start",
|
|
152
|
+
value: function start() {
|
|
153
|
+
var _this2 = this;
|
|
154
|
+
if (!this.mediaDevices) {
|
|
155
|
+
return Promise.reject(new Error('Screen recorder access not supported'));
|
|
156
|
+
}
|
|
157
|
+
this.captureActive = true;
|
|
158
|
+
this.selectAudioStreamSource();
|
|
159
|
+
this.selectVideoStreamSource().then(function (res) {
|
|
160
|
+
// something happened in start -> return
|
|
161
|
+
if (res === false) {
|
|
162
|
+
// Close the Explorer panel if plugin is installed
|
|
163
|
+
// into Explorer (could be other parent UI plugin)
|
|
164
|
+
if (_this2.parent && _this2.parent.hideAllPanelsAndShowAddFilesPanel) {
|
|
165
|
+
_this2.parent.hideAllPanelsAndShowAddFilesPanel();
|
|
166
|
+
_this2.captureActive = false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}, {
|
|
172
|
+
key: "selectVideoStreamSource",
|
|
173
|
+
value: function selectVideoStreamSource() {
|
|
174
|
+
var _this3 = this;
|
|
175
|
+
// if active stream available, return it
|
|
176
|
+
if (this.videoStream) {
|
|
177
|
+
return new Promise(function (resolve) {
|
|
178
|
+
return resolve(_this3.videoStream);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ask user to select source to record and get mediastream from that
|
|
183
|
+
return this.mediaDevices.getDisplayMedia(this.opts.displayMediaConstraints).then(function (videoStream) {
|
|
184
|
+
_this3.videoStream = videoStream;
|
|
185
|
+
|
|
186
|
+
// add event listener to stop recording if stream is interrupted
|
|
187
|
+
_this3.videoStream.addEventListener('inactive', function (event) {
|
|
188
|
+
_this3.streamInactivated();
|
|
189
|
+
});
|
|
190
|
+
_this3.setPluginCommonState({
|
|
191
|
+
streamActive: true
|
|
192
|
+
});
|
|
193
|
+
return videoStream;
|
|
194
|
+
})["catch"](function () {
|
|
195
|
+
var err = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
196
|
+
_this3.filerobot.info(err, 'error', 5000);
|
|
197
|
+
_this3.userDenied = true;
|
|
198
|
+
setTimeout(function () {
|
|
199
|
+
_this3.userDenied = false;
|
|
200
|
+
}, 1000);
|
|
201
|
+
return false;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}, {
|
|
205
|
+
key: "selectAudioStreamSource",
|
|
206
|
+
value: function selectAudioStreamSource() {
|
|
207
|
+
var _this4 = this;
|
|
208
|
+
// if active stream available, return it
|
|
209
|
+
if (this.audioStream) {
|
|
210
|
+
return new Promise(function (resolve) {
|
|
211
|
+
return resolve(_this4.audioStream);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ask user to select source to record and get mediastream from that
|
|
216
|
+
return this.mediaDevices.getUserMedia(this.opts.userMediaConstraints).then(function (audioStream) {
|
|
217
|
+
_this4.audioStream = audioStream;
|
|
218
|
+
_this4.setPluginCommonState({
|
|
219
|
+
audioStreamActive: true
|
|
220
|
+
});
|
|
221
|
+
return audioStream;
|
|
222
|
+
})["catch"](function (err) {
|
|
223
|
+
if (err.name === 'NotAllowedError') {
|
|
224
|
+
_this4.filerobot.info(_this4.i18n('screenCaptureMicDisabledInfo'), 'error', 5000);
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}, {
|
|
230
|
+
key: "startRecording",
|
|
231
|
+
value: function startRecording() {
|
|
232
|
+
var _this5 = this;
|
|
233
|
+
var options = {};
|
|
234
|
+
this.capturedMediaFile = null;
|
|
235
|
+
this.recordingChunks = [];
|
|
236
|
+
var preferredVideoMimeType = this.opts.preferredVideoMimeType;
|
|
237
|
+
this.selectVideoStreamSource().then(function (videoStream) {
|
|
238
|
+
// Attempt to use the passed preferredVideoMimeType (if any) during recording.
|
|
239
|
+
// If the browser doesn't support it, we'll fall back to the browser default instead
|
|
240
|
+
if (preferredVideoMimeType && MediaRecorder.isTypeSupported(preferredVideoMimeType) && getFileTypeExtension(preferredVideoMimeType)) {
|
|
241
|
+
options.mimeType = preferredVideoMimeType;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// prepare tracks
|
|
245
|
+
var tracks = [videoStream.getVideoTracks()[0]];
|
|
246
|
+
|
|
247
|
+
// merge audio if exits
|
|
248
|
+
if (_this5.audioStream) {
|
|
249
|
+
tracks.push(_this5.audioStream.getAudioTracks()[0]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// create new stream from video and audio
|
|
253
|
+
_this5.outputStream = new MediaStream(tracks);
|
|
254
|
+
|
|
255
|
+
// initialize mediarecorder
|
|
256
|
+
_this5.recorder = new MediaRecorder(_this5.outputStream, options);
|
|
257
|
+
|
|
258
|
+
// push data to buffer when data available
|
|
259
|
+
_this5.recorder.addEventListener('dataavailable', function (event) {
|
|
260
|
+
_this5.recordingChunks.push(event.data);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// start recording
|
|
264
|
+
_this5.recorder.start();
|
|
265
|
+
|
|
266
|
+
// set plugin state to recording
|
|
267
|
+
_this5.setPluginCommonState({
|
|
268
|
+
recording: true
|
|
269
|
+
});
|
|
270
|
+
})["catch"](function (err) {
|
|
271
|
+
_this5.filerobot.log(err, 'error');
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}, {
|
|
275
|
+
key: "streamInactivated",
|
|
276
|
+
value: function streamInactivated() {
|
|
277
|
+
// get screen recorder state
|
|
278
|
+
var recording = this.getPluginCommonState().recording; // recordedVideo
|
|
279
|
+
|
|
280
|
+
// commented because It is generating this bug https://scaleflexhq.atlassian.net/browse/FRA-1038
|
|
281
|
+
// TODO: delete this comment if a long time passed without issues related to this fix
|
|
282
|
+
// if (!recordedVideo && !recording) {
|
|
283
|
+
// // Close the Explorer panel if plugin is installed
|
|
284
|
+
// // into Explorer (could be other parent UI plugin)
|
|
285
|
+
// if (this.parent && this.parent.hideAllPanelsAndShowAddFilesPanel) {
|
|
286
|
+
// this.parent.hideAllPanelsAndShowAddFilesPanel()
|
|
287
|
+
// }
|
|
288
|
+
// }
|
|
289
|
+
if (recording) {
|
|
290
|
+
// stop recorder if it is active
|
|
291
|
+
this.filerobot.log('Capture stream inactive — stop recording');
|
|
292
|
+
this.stopRecording();
|
|
293
|
+
}
|
|
294
|
+
this.videoStream = null;
|
|
295
|
+
this.audioStream = null;
|
|
296
|
+
this.setPluginCommonState({
|
|
297
|
+
streamActive: false,
|
|
298
|
+
audioStreamActive: false
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}, {
|
|
302
|
+
key: "stopRecording",
|
|
303
|
+
value: function stopRecording() {
|
|
304
|
+
var _this6 = this;
|
|
305
|
+
var stopped = new Promise(function (resolve, reject) {
|
|
306
|
+
_this6.recorder.addEventListener('stop', function () {
|
|
307
|
+
resolve();
|
|
308
|
+
});
|
|
309
|
+
_this6.recorder.stop();
|
|
310
|
+
});
|
|
311
|
+
return stopped.then(function () {
|
|
312
|
+
// recording stopped
|
|
313
|
+
_this6.setPluginCommonState({
|
|
314
|
+
recording: false
|
|
315
|
+
});
|
|
316
|
+
// get video file after recorder stopped
|
|
317
|
+
return _this6.getVideo();
|
|
318
|
+
}).then(function (file) {
|
|
319
|
+
// store media file
|
|
320
|
+
_this6.capturedMediaFile = file;
|
|
321
|
+
|
|
322
|
+
// create object url for capture result preview
|
|
323
|
+
_this6.setPluginCommonState({
|
|
324
|
+
recordedVideo: URL.createObjectURL(file.data)
|
|
325
|
+
});
|
|
326
|
+
}).then(function () {
|
|
327
|
+
_this6.recordingChunks = null;
|
|
328
|
+
_this6.recorder = null;
|
|
329
|
+
}, function (error) {
|
|
330
|
+
_this6.recordingChunks = null;
|
|
331
|
+
_this6.recorder = null;
|
|
332
|
+
throw error;
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}, {
|
|
336
|
+
key: "submit",
|
|
337
|
+
value: function submit() {
|
|
338
|
+
try {
|
|
339
|
+
// add recorded file to filerobot
|
|
340
|
+
if (this.capturedMediaFile) {
|
|
341
|
+
this.filerobot.addFile(this.capturedMediaFile);
|
|
342
|
+
}
|
|
343
|
+
} catch (err) {
|
|
344
|
+
// Logging the error, exept restrictions, which is handled in Core
|
|
345
|
+
if (!err.isRestriction) {
|
|
346
|
+
this.filerobot.log(err, 'error');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}, {
|
|
351
|
+
key: "stop",
|
|
352
|
+
value: function stop() {
|
|
353
|
+
// flush video stream
|
|
354
|
+
if (this.videoStream) {
|
|
355
|
+
this.videoStream.getVideoTracks().forEach(function (track) {
|
|
356
|
+
track.stop();
|
|
357
|
+
});
|
|
358
|
+
this.videoStream.getAudioTracks().forEach(function (track) {
|
|
359
|
+
track.stop();
|
|
360
|
+
});
|
|
361
|
+
this.videoStream = null;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// flush audio stream
|
|
365
|
+
if (this.audioStream) {
|
|
366
|
+
this.audioStream.getAudioTracks().forEach(function (track) {
|
|
367
|
+
track.stop();
|
|
368
|
+
});
|
|
369
|
+
this.audioStream.getVideoTracks().forEach(function (track) {
|
|
370
|
+
track.stop();
|
|
371
|
+
});
|
|
372
|
+
this.audioStream = null;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// flush output stream
|
|
376
|
+
if (this.outputStream) {
|
|
377
|
+
this.outputStream.getAudioTracks().forEach(function (track) {
|
|
378
|
+
track.stop();
|
|
379
|
+
});
|
|
380
|
+
this.outputStream.getVideoTracks().forEach(function (track) {
|
|
381
|
+
track.stop();
|
|
382
|
+
});
|
|
383
|
+
this.outputStream = null;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// remove preview video
|
|
387
|
+
this.setPluginCommonState({
|
|
388
|
+
recordedVideo: null
|
|
389
|
+
});
|
|
390
|
+
if (this.getPluginCommonState().recording) {
|
|
391
|
+
this.setPluginCommonState({
|
|
392
|
+
recording: false
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
this.captureActive = false;
|
|
396
|
+
}
|
|
397
|
+
}, {
|
|
398
|
+
key: "getVideo",
|
|
399
|
+
value: function getVideo() {
|
|
400
|
+
var mimeType = this.recordingChunks[0].type;
|
|
401
|
+
var fileExtension = getFileTypeExtension(mimeType);
|
|
402
|
+
if (!fileExtension) {
|
|
403
|
+
return Promise.reject(new Error("Could not retrieve recording: Unsupported media type \"".concat(mimeType, "\"")));
|
|
404
|
+
}
|
|
405
|
+
var name = "screencap-".concat(Date.now(), ".").concat(fileExtension);
|
|
406
|
+
var blob = new Blob(this.recordingChunks, {
|
|
407
|
+
type: mimeType
|
|
408
|
+
});
|
|
409
|
+
var file = {
|
|
410
|
+
source: this.id,
|
|
411
|
+
name: name,
|
|
412
|
+
data: new Blob([blob], {
|
|
413
|
+
type: mimeType
|
|
414
|
+
}),
|
|
415
|
+
type: mimeType
|
|
416
|
+
};
|
|
417
|
+
return Promise.resolve(file);
|
|
418
|
+
}
|
|
419
|
+
}, {
|
|
420
|
+
key: "render",
|
|
421
|
+
value: function render() {
|
|
422
|
+
// get screen recorder state
|
|
423
|
+
var streamActive = this.getPluginCommonState().streamActive;
|
|
424
|
+
if (!streamActive && !this.captureActive && !this.userDenied) {
|
|
425
|
+
this.start();
|
|
426
|
+
}
|
|
427
|
+
return /*#__PURE__*/createElement(CaptureScreen, {
|
|
428
|
+
onStartRecording: this.startRecording,
|
|
429
|
+
onStopRecording: this.stopRecording,
|
|
430
|
+
onStop: this.stop,
|
|
431
|
+
onSubmit: this.submit,
|
|
432
|
+
i18n: this.i18n,
|
|
433
|
+
stream: this.videoStream
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}]);
|
|
437
|
+
}(Plugin);
|
|
438
|
+
export { ScreenCapture as default };
|
package/lib/style.scss
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// packages/@scaleflex/widget-screen-capture/src/CaptureScreen.jsx
|
|
2
|
+
@import '@scaleflex/widget-core/lib/_utils.scss';
|
|
3
|
+
@import '@scaleflex/widget-core/lib/_variables.scss';
|
|
4
|
+
|
|
5
|
+
.filerobot-ScreenCapture-container {
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100%;
|
|
8
|
+
display: flex;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
align-items: center;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.filerobot-ScreenCapture-videoContainer {
|
|
15
|
+
width: 100%;
|
|
16
|
+
flex: 1;
|
|
17
|
+
flex-grow: 1;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
background-color: $darkgrey;
|
|
20
|
+
text-align: center;
|
|
21
|
+
position: relative;
|
|
22
|
+
|
|
23
|
+
.filerobot-size--md & {
|
|
24
|
+
max-width: 100%;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.filerobot-ScreenCapture-video {
|
|
29
|
+
max-width: 100%;
|
|
30
|
+
max-height: 100%;
|
|
31
|
+
position: absolute;
|
|
32
|
+
top: 0;
|
|
33
|
+
right: 0;
|
|
34
|
+
bottom: 0;
|
|
35
|
+
left: 0;
|
|
36
|
+
margin: auto;
|
|
37
|
+
outline: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.filerobot-ScreenCapture-buttonContainer {
|
|
41
|
+
width: 100%;
|
|
42
|
+
height: 75px;
|
|
43
|
+
border-top: 1px solid $gray-200;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
padding: 0 20px;
|
|
48
|
+
background-color: $white;
|
|
49
|
+
|
|
50
|
+
[data-filerobot-theme="dark"] & {
|
|
51
|
+
background-color: $gray-900;
|
|
52
|
+
border-top: 1px solid $gray-800;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.filerobot-ScreenCapture-button {
|
|
57
|
+
@include blue-border-focus;
|
|
58
|
+
width: 45px;
|
|
59
|
+
height: 45px;
|
|
60
|
+
border-radius: 50%;
|
|
61
|
+
color: $white;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
transition: all 0.3s;
|
|
64
|
+
|
|
65
|
+
[data-filerobot-theme="dark"] & {
|
|
66
|
+
@include blue-border-focus--dark;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.filerobot-size--md & {
|
|
70
|
+
width: 60px;
|
|
71
|
+
height: 60px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&:hover {
|
|
75
|
+
background-color: darken($red, 5%);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.filerobot-ScreenCapture-button svg {
|
|
80
|
+
width: 30px;
|
|
81
|
+
height: 30px;
|
|
82
|
+
max-width: 100%;
|
|
83
|
+
max-height: 100%;
|
|
84
|
+
display: inline-block;
|
|
85
|
+
vertical-align: text-top;
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
fill: currentColor;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.filerobot-ScreenCapture-button--submit {
|
|
91
|
+
background-color: $blue;
|
|
92
|
+
margin-left: 12px;
|
|
93
|
+
|
|
94
|
+
&:hover {
|
|
95
|
+
background-color: darken($blue, 5%);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&:disabled {
|
|
99
|
+
background-color: $gray-500;
|
|
100
|
+
cursor: default;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&:disabled:hover {
|
|
104
|
+
background-color: $gray-200;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.filerobot-ScreenCapture-title {
|
|
109
|
+
font-size: 22px;
|
|
110
|
+
line-height: 1.35;
|
|
111
|
+
font-weight: 400;
|
|
112
|
+
margin: 0;
|
|
113
|
+
margin-bottom: 5px;
|
|
114
|
+
padding: 0 15px;
|
|
115
|
+
max-width: 500px;
|
|
116
|
+
text-align: center;
|
|
117
|
+
color: $gray-800;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.filerobot-ScreenCapture-icon--stream {
|
|
121
|
+
position: absolute;
|
|
122
|
+
right: 0;
|
|
123
|
+
top: 0;
|
|
124
|
+
margin: 1rem;
|
|
125
|
+
z-index:1;
|
|
126
|
+
|
|
127
|
+
svg {
|
|
128
|
+
fill: $gray-500;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.filerobot-ScreenCapture-icon--streamActive svg {
|
|
133
|
+
animation: filerobot-ScreenCapture-icon--blink 1s cubic-bezier(0.47, 0, 0.75, 0.72) infinite;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@keyframes filerobot-ScreenCapture-icon--blink {
|
|
137
|
+
0% { fill: $blue;}
|
|
138
|
+
50% { fill: $gray-500; }
|
|
139
|
+
100% { fill: $blue; }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.filerobot-ScreenCapture-button--video {
|
|
143
|
+
color: $white;
|
|
144
|
+
background: $red;
|
|
145
|
+
|
|
146
|
+
&:hover {
|
|
147
|
+
background-color: darken($red, 10%);
|
|
148
|
+
}
|
|
149
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scaleflex/widget-screen-capture",
|
|
3
3
|
"description": "Scaleflex plugin that captures video from display or application.",
|
|
4
|
-
"version": "4.8.
|
|
4
|
+
"version": "4.8.12",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"style": "dist/style.min.css",
|
|
8
8
|
"types": "types/index.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@scaleflex/widget-utils": "^4.8.
|
|
10
|
+
"@scaleflex/widget-utils": "^4.8.12"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"react": "^19.0.0",
|
|
@@ -27,5 +27,5 @@
|
|
|
27
27
|
"/lib",
|
|
28
28
|
"/types"
|
|
29
29
|
],
|
|
30
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "c8eaaf5f9228b824d45de4027640e7eb5517fbb8"
|
|
31
31
|
}
|