@playkit-js/transcript 3.1.0-canary.2-d22690c → 3.1.0-canary.4-372ac3f
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 +7 -1
- package/dist/playkit-transcript.js +1 -1
- package/dist/playkit-transcript.js.map +1 -1
- package/package.json +1 -1
- package/src/components/caption/caption.tsx +2 -2
- package/src/components/close-button/index.tsx +1 -1
- package/src/components/search/search.tsx +4 -4
- package/src/components/transcript/transcript.tsx +20 -18
- package/src/transcript-plugin.tsx +38 -15
package/package.json
CHANGED
|
@@ -116,8 +116,8 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
116
116
|
<A11yWrapper onClick={this._handleKeyDown}>
|
|
117
117
|
<div
|
|
118
118
|
className={styles.caption}
|
|
119
|
-
tabIndex={
|
|
120
|
-
|
|
119
|
+
tabIndex={0}
|
|
120
|
+
aria-label={caption.text}
|
|
121
121
|
ref={node => {
|
|
122
122
|
this._hotspotRef = node;
|
|
123
123
|
}}
|
|
@@ -16,7 +16,7 @@ interface CloseButtonProps {
|
|
|
16
16
|
|
|
17
17
|
export const CloseButton = withText(translates)((props: CloseButtonProps) => (
|
|
18
18
|
<A11yWrapper onClick={props.onClick}>
|
|
19
|
-
<button className={styles.closeBtn} tabIndex={
|
|
19
|
+
<button className={styles.closeBtn} tabIndex={0} aria-label={props.closeLabel}>
|
|
20
20
|
<Icon
|
|
21
21
|
id="transcript-plugin-close-button"
|
|
22
22
|
height={icons.BigSize}
|
|
@@ -167,14 +167,14 @@ class SearchComponent extends Component<SearchProps, SearchState> {
|
|
|
167
167
|
onFocus={this._onFocus}
|
|
168
168
|
onBlur={this._onBlur}
|
|
169
169
|
onMouseDown={this._handleMouseDown}
|
|
170
|
-
tabIndex={
|
|
170
|
+
tabIndex={0}
|
|
171
171
|
ref={node => {
|
|
172
172
|
this._inputRef = node;
|
|
173
173
|
}}
|
|
174
174
|
/>
|
|
175
175
|
{searchQuery && (
|
|
176
176
|
<A11yWrapper onClick={this._onClear}>
|
|
177
|
-
<button className={styles.clearIcon} tabIndex={
|
|
177
|
+
<button className={styles.clearIcon} tabIndex={0} aria-label={this.props.clearSearchLabel}>
|
|
178
178
|
<svg
|
|
179
179
|
width="32px"
|
|
180
180
|
height="32px"
|
|
@@ -201,7 +201,7 @@ class SearchComponent extends Component<SearchProps, SearchState> {
|
|
|
201
201
|
{searchQuery && (
|
|
202
202
|
<A11yWrapper onClick={this._goToPrevSearchResult}>
|
|
203
203
|
<button
|
|
204
|
-
tabIndex={
|
|
204
|
+
tabIndex={0}
|
|
205
205
|
className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
|
|
206
206
|
aria-label={this.props.prevMatchLabel}>
|
|
207
207
|
<svg
|
|
@@ -225,7 +225,7 @@ class SearchComponent extends Component<SearchProps, SearchState> {
|
|
|
225
225
|
{searchQuery && (
|
|
226
226
|
<A11yWrapper onClick={this._goToNextSearchResult}>
|
|
227
227
|
<button
|
|
228
|
-
tabIndex={
|
|
228
|
+
tabIndex={0}
|
|
229
229
|
className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
|
|
230
230
|
aria-label={this.props.nextMatchLabel}>
|
|
231
231
|
<svg
|
|
@@ -13,7 +13,10 @@ const {ENTER, SPACE, TAB, ESC} = KalturaPlayer.ui.utils.KeyMap;
|
|
|
13
13
|
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
14
14
|
|
|
15
15
|
const translates = {
|
|
16
|
-
autoScrollLabel: <Text id="transcript.auto_scroll">Enable auto scroll</Text
|
|
16
|
+
autoScrollLabel: <Text id="transcript.auto_scroll">Enable auto scroll</Text>,
|
|
17
|
+
errorTitle: <Text id="transcript.whoops">Whoops!</Text>,
|
|
18
|
+
errorDescripton: <Text id="transcript.load_failed">Failed to load transcript</Text>,
|
|
19
|
+
skipTranscript: <Text id="transcript.skip_transcript">Skip transcript</Text>
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
export interface TranscriptProps {
|
|
@@ -34,6 +37,9 @@ export interface TranscriptProps {
|
|
|
34
37
|
highlightedMap: HighlightedMap;
|
|
35
38
|
onItemClicked: (n: number) => void;
|
|
36
39
|
autoScrollLabel?: string;
|
|
40
|
+
errorTitle?: string;
|
|
41
|
+
errorDescripton?: string;
|
|
42
|
+
skipTranscript?: string;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
interface TranscriptState {
|
|
@@ -111,7 +117,7 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
111
117
|
<div
|
|
112
118
|
role="button"
|
|
113
119
|
className={`${styles.autoscrollButton} ${isAutoScrollEnabled ? '' : styles.autoscrollButtonVisible}`}
|
|
114
|
-
tabIndex={isAutoScrollEnabled ? -1 :
|
|
120
|
+
tabIndex={isAutoScrollEnabled ? -1 : 0}
|
|
115
121
|
aria-label={this.props.autoScrollLabel}
|
|
116
122
|
ref={node => {
|
|
117
123
|
this._autoscrollButtonRef = node;
|
|
@@ -238,8 +244,8 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
238
244
|
className={styles.skipTranscriptButton}
|
|
239
245
|
onKeyDown={this._handleKeyDown}
|
|
240
246
|
onClick={this._handleClick}
|
|
241
|
-
tabIndex={
|
|
242
|
-
|
|
247
|
+
tabIndex={0}>
|
|
248
|
+
{this.props.skipTranscript}
|
|
243
249
|
</div>
|
|
244
250
|
);
|
|
245
251
|
};
|
|
@@ -247,9 +253,6 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
247
253
|
private _renderTranscript = () => {
|
|
248
254
|
const {captions, hasError, onRetryLoad, showTime, videoDuration, highlightedMap} = this.props;
|
|
249
255
|
const {isAutoScrollEnabled, searchMap, activeSearchIndex, searchLength} = this.state;
|
|
250
|
-
if (!captions || !captions.length) {
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
256
|
|
|
254
257
|
if (hasError) {
|
|
255
258
|
return (
|
|
@@ -257,17 +260,16 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
257
260
|
<div className={styles.errorIcon}>
|
|
258
261
|
<ErrorIcon />
|
|
259
262
|
</div>
|
|
260
|
-
<p className={styles.errorMainText}>
|
|
261
|
-
<p className={styles.errorDescriptionText}>
|
|
262
|
-
Failed to get transcript, please try again
|
|
263
|
-
<button className={styles.retryButton} onClick={onRetryLoad}>
|
|
264
|
-
Retry
|
|
265
|
-
</button>
|
|
266
|
-
</p>
|
|
263
|
+
<p className={styles.errorMainText}>{this.props.errorTitle}</p>
|
|
264
|
+
<p className={styles.errorDescriptionText}>{this.props.errorDescripton}</p>
|
|
267
265
|
</div>
|
|
268
266
|
);
|
|
269
267
|
}
|
|
270
268
|
|
|
269
|
+
if (!captions || !captions.length) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
|
|
271
273
|
const captionProps = {
|
|
272
274
|
showTime,
|
|
273
275
|
searchLength,
|
|
@@ -369,8 +371,8 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
369
371
|
};
|
|
370
372
|
|
|
371
373
|
render(props: TranscriptProps) {
|
|
372
|
-
const {isLoading, kitchenSinkActive} = props;
|
|
373
|
-
|
|
374
|
+
const {isLoading, kitchenSinkActive, hasError} = props;
|
|
375
|
+
const renderTranscriptButtons = !(isLoading || hasError);
|
|
374
376
|
return (
|
|
375
377
|
<div
|
|
376
378
|
className={`${styles.root} ${kitchenSinkActive ? '' : styles.hidden}`}
|
|
@@ -383,7 +385,7 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
383
385
|
|
|
384
386
|
<CloseButton onClick={this.props.onClose} />
|
|
385
387
|
|
|
386
|
-
{
|
|
388
|
+
{renderTranscriptButtons && this._renderSkipTranscriptButton()}
|
|
387
389
|
<div
|
|
388
390
|
className={styles.body}
|
|
389
391
|
onScroll={this._onScroll}
|
|
@@ -392,7 +394,7 @@ export class TranscriptComponent extends Component<TranscriptProps, TranscriptSt
|
|
|
392
394
|
}}>
|
|
393
395
|
{isLoading ? this._renderLoading() : this._renderTranscript()}
|
|
394
396
|
</div>
|
|
395
|
-
{this._renderScrollToButton()}
|
|
397
|
+
{renderTranscriptButtons && this._renderScrollToButton()}
|
|
396
398
|
</div>
|
|
397
399
|
</div>
|
|
398
400
|
);
|
|
@@ -13,6 +13,8 @@ const {SidePanelModes, SidePanelPositions, ReservedPresetNames, ReservedPresetAr
|
|
|
13
13
|
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
14
14
|
const {get} = ObjectUtils;
|
|
15
15
|
|
|
16
|
+
const LOADING_TIMEOUT = 10000;
|
|
17
|
+
|
|
16
18
|
interface TimedMetadataEvent {
|
|
17
19
|
payload: {
|
|
18
20
|
cues: Array<CuePoint>;
|
|
@@ -35,6 +37,7 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
35
37
|
private _activeCuePointsMap: HighlightedMap = {};
|
|
36
38
|
private _captionMap: Map<string, Array<CuePointData>> = new Map();
|
|
37
39
|
private _isLoading = false;
|
|
40
|
+
private _loadingTimeoutId?: ReturnType<typeof setTimeout>;
|
|
38
41
|
private _hasError = false;
|
|
39
42
|
private _triggeredByKeyboard = false;
|
|
40
43
|
|
|
@@ -78,27 +81,39 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
private _initListeners(): void {
|
|
81
|
-
this.eventManager.
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this._isLoading = true;
|
|
87
|
-
}
|
|
84
|
+
this.eventManager.listenOnce(this.player, this.player.Event.TRACKS_CHANGED, () => {
|
|
85
|
+
if (this._getTextTracks().length) {
|
|
86
|
+
this.eventManager.listen(this.player, this.player.Event.TIMED_METADATA_CHANGE, this._onTimedMetadataChange);
|
|
87
|
+
this.eventManager.listen(this.player, this.player.Event.TIMED_METADATA_ADDED, this._onTimedMetadataAdded);
|
|
88
|
+
this.eventManager.listen(this.player, this.player.Event.TEXT_TRACK_CHANGED, this._handleLanguageChange);
|
|
88
89
|
this._addDownloadIcon();
|
|
89
90
|
this._addPrintIcon();
|
|
90
91
|
this._addTranscriptItem();
|
|
92
|
+
this._initLoading();
|
|
91
93
|
}
|
|
92
94
|
});
|
|
93
|
-
this.eventManager.listen(this.player, this.player.Event.TIMED_METADATA_CHANGE, this._onTimedMetadataChange);
|
|
94
|
-
this.eventManager.listen(this.player, this.player.Event.TIMED_METADATA_ADDED, this._onTimedMetadataAdded);
|
|
95
|
-
this.eventManager.listen(this.player, this.player.Event.TEXT_TRACK_CHANGED, this._handleLanguageChange);
|
|
96
95
|
}
|
|
97
96
|
|
|
97
|
+
private _initLoading = () => {
|
|
98
|
+
clearTimeout(this._loadingTimeoutId);
|
|
99
|
+
this._isLoading = false;
|
|
100
|
+
this._hasError = false;
|
|
101
|
+
if (!this._captionMap.has(this._activeCaptionMapId)) {
|
|
102
|
+
// turn on loading animation till captions added to TextTrack
|
|
103
|
+
this._isLoading = true;
|
|
104
|
+
this._loadingTimeoutId = setTimeout(() => {
|
|
105
|
+
// display error slate
|
|
106
|
+
this._isLoading = false;
|
|
107
|
+
this._hasError = true;
|
|
108
|
+
this._updateTranscriptPanel();
|
|
109
|
+
}, LOADING_TIMEOUT);
|
|
110
|
+
}
|
|
111
|
+
this._updateTranscriptPanel();
|
|
112
|
+
};
|
|
113
|
+
|
|
98
114
|
private _handleLanguageChange = () => {
|
|
99
115
|
this._activeCaptionMapId = this._getCaptionMapId();
|
|
100
|
-
this.
|
|
101
|
-
this._updateTranscriptPanel();
|
|
116
|
+
this._initLoading();
|
|
102
117
|
};
|
|
103
118
|
|
|
104
119
|
private _updateTranscriptPanel() {
|
|
@@ -140,11 +155,16 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
140
155
|
this._activeCaptionMapId = this._getCaptionMapId();
|
|
141
156
|
this._captionMap.set(this._activeCaptionMapId, newData);
|
|
142
157
|
this._isLoading = false;
|
|
158
|
+
clearTimeout(this._loadingTimeoutId);
|
|
143
159
|
this._updateTranscriptPanel();
|
|
144
160
|
};
|
|
145
161
|
|
|
162
|
+
private _getTextTracks = () => {
|
|
163
|
+
return this.player.getTracks(this.player.Track.TEXT) || [];
|
|
164
|
+
};
|
|
165
|
+
|
|
146
166
|
private _getCaptionMapId = (): string => {
|
|
147
|
-
const allTextTracks = this.
|
|
167
|
+
const allTextTracks = this._getTextTracks();
|
|
148
168
|
const activeTextTrack = allTextTracks.find(track => track.active);
|
|
149
169
|
if (activeTextTrack?.language === 'off') {
|
|
150
170
|
// use 1st captions from text-track list
|
|
@@ -219,9 +239,11 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
219
239
|
}
|
|
220
240
|
|
|
221
241
|
private _addTranscriptItem(): void {
|
|
222
|
-
|
|
223
|
-
|
|
242
|
+
if (this._transcriptPanel > 0) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
224
245
|
|
|
246
|
+
const {expandMode, position, expandOnFirstPlay, showTime, scrollOffset, searchDebounceTimeout, searchNextPrevDebounceTimeout} = this.config;
|
|
225
247
|
this._transcriptPanel = this.sidePanelsManager!.add({
|
|
226
248
|
label: 'Transcript',
|
|
227
249
|
panelComponent: () => {
|
|
@@ -320,6 +342,7 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
320
342
|
this._captionMap = new Map();
|
|
321
343
|
this._activeCaptionMapId = '';
|
|
322
344
|
this._isLoading = false;
|
|
345
|
+
clearTimeout(this._loadingTimeoutId);
|
|
323
346
|
this._hasError = false;
|
|
324
347
|
this._triggeredByKeyboard = false;
|
|
325
348
|
}
|