@playkit-js/transcript 3.5.36 → 3.5.37
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 -0
- package/dist/playkit-transcript.js +1 -1
- package/dist/playkit-transcript.js.map +1 -1
- package/package.json +2 -2
- package/src/components/caption/caption.tsx +6 -7
- package/src/components/caption-list/captionList.tsx +11 -15
- package/src/components/transcript/transcript.tsx +7 -6
- package/src/utils/index.ts +0 -1
- package/src/utils/debounce.ts +0 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playkit-js/transcript",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.37",
|
|
4
4
|
"main": "dist/playkit-transcript.js",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"private": false,
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"clean": "rimraf ./dist",
|
|
43
43
|
"prebuild": "npm run clean",
|
|
44
44
|
"build": "webpack --mode production",
|
|
45
|
-
"dev": "webpack
|
|
45
|
+
"dev": "webpack serve --open --mode development",
|
|
46
46
|
"watch": "webpack --progress --color --watch --mode development",
|
|
47
47
|
"cy:open": "cypress open",
|
|
48
48
|
"cy:run": "yarn run cy:run:chrome && yarn run cy:run:firefox && yarn run cy:run:edge && yarn run cy:run:safari",
|
|
@@ -30,7 +30,7 @@ export interface CaptionProps {
|
|
|
30
30
|
interface ExtendedCaptionProps extends CaptionProps {
|
|
31
31
|
caption: CuePointData;
|
|
32
32
|
onClick: () => void;
|
|
33
|
-
|
|
33
|
+
isHighlighted: boolean;
|
|
34
34
|
shouldScroll: boolean;
|
|
35
35
|
shouldScrollToSearchMatch: boolean;
|
|
36
36
|
indexMap: Record<string, number> | undefined;
|
|
@@ -83,14 +83,14 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
shouldComponentUpdate(nextProps: ExtendedCaptionProps) {
|
|
86
|
-
const {indexMap,
|
|
86
|
+
const {indexMap, isHighlighted, isAutoScrollEnabled, activeSearchIndex, longerThanHour} = this.props;
|
|
87
87
|
if (longerThanHour !== nextProps.longerThanHour) {
|
|
88
88
|
return true;
|
|
89
89
|
}
|
|
90
|
-
if (
|
|
90
|
+
if (isHighlighted !== nextProps.isHighlighted) {
|
|
91
91
|
return true;
|
|
92
92
|
}
|
|
93
|
-
if (
|
|
93
|
+
if (isHighlighted && isAutoScrollEnabled !== nextProps.isAutoScrollEnabled) {
|
|
94
94
|
return true;
|
|
95
95
|
}
|
|
96
96
|
if (indexMap !== nextProps.indexMap) {
|
|
@@ -150,9 +150,8 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
render() {
|
|
153
|
-
const {caption,
|
|
154
|
-
const {startTime
|
|
155
|
-
const isHighlighted = Object.keys(highlighted).some(c => c === id);
|
|
153
|
+
const {caption, isHighlighted, showTime, longerThanHour, indexMap, captionLabel, moveToSearch, navigationInstruction, timeLabel, player} = this.props;
|
|
154
|
+
const {startTime} = caption;
|
|
156
155
|
const time = showTime ? secondsToTime(startTime, longerThanHour) : '';
|
|
157
156
|
|
|
158
157
|
const captionA11yProps: Record<string, any> = {
|
|
@@ -20,7 +20,6 @@ export interface Props {
|
|
|
20
20
|
onSeek: (n: CuePointData) => void;
|
|
21
21
|
autoScroll?: boolean;
|
|
22
22
|
onScroll: (n: number) => void;
|
|
23
|
-
widgetWidth: number;
|
|
24
23
|
highlightedMap: HighlightedMap;
|
|
25
24
|
showItemsIcons: boolean;
|
|
26
25
|
listDataContainCaptions?: boolean;
|
|
@@ -85,12 +84,12 @@ export class CaptionList extends Component<Props> {
|
|
|
85
84
|
key: id,
|
|
86
85
|
onClick: this._handleClick(captionData),
|
|
87
86
|
caption: captionData,
|
|
88
|
-
|
|
87
|
+
isHighlighted: Boolean(highlightedMap[id]),
|
|
89
88
|
longerThanHour: captionProps.videoDuration >= HOUR,
|
|
90
89
|
shouldScroll: this._getShouldScroll(id),
|
|
91
90
|
shouldScrollToSearchMatch: this._getShouldScrollToSearchMatch(id),
|
|
92
91
|
isAutoScrollEnabled,
|
|
93
|
-
searchCaption: this.props.searchMap[
|
|
92
|
+
searchCaption: this.props.searchMap[id],
|
|
94
93
|
...this._getSearchProps(id)
|
|
95
94
|
};
|
|
96
95
|
return newCaptionProps;
|
|
@@ -105,14 +104,19 @@ export class CaptionList extends Component<Props> {
|
|
|
105
104
|
};
|
|
106
105
|
|
|
107
106
|
render() {
|
|
108
|
-
const {data} = this.props;
|
|
109
|
-
let
|
|
107
|
+
const {data, highlightedMap} = this.props;
|
|
108
|
+
let isSearchCaptionInList = false;
|
|
110
109
|
return (
|
|
111
110
|
<div className={styles.transcriptWrapper} onKeyUp={this._handleKeyUp}>
|
|
112
111
|
{data.map((captionData, index) => {
|
|
113
112
|
const captionProps = this._getCaptionProps(captionData);
|
|
113
|
+
let isSearchCaption = false;
|
|
114
|
+
if (captionProps.searchCaption && Object.keys(captionProps.searchCaption).some(key => parseInt(key) === this.props.activeSearchIndex)) {
|
|
115
|
+
isSearchCaptionInList = true;
|
|
116
|
+
isSearchCaption = true;
|
|
117
|
+
}
|
|
114
118
|
return (
|
|
115
|
-
<ScreenReaderContext.Consumer>
|
|
119
|
+
<ScreenReaderContext.Consumer key={captionData.id}>
|
|
116
120
|
{(setTextToRead: (textToRead: string, delay?: number | undefined) => void) => {
|
|
117
121
|
return (
|
|
118
122
|
<Caption
|
|
@@ -123,15 +127,7 @@ export class CaptionList extends Component<Props> {
|
|
|
123
127
|
} else if (index === data.length - 1) {
|
|
124
128
|
this._lastCaptionRef = node;
|
|
125
129
|
}
|
|
126
|
-
if (captionProps.
|
|
127
|
-
Object.keys(captionProps.searchCaption).forEach(key => {
|
|
128
|
-
if (parseInt(key) === this.props.activeSearchIndex) {
|
|
129
|
-
this._currentCaptionRef = node;
|
|
130
|
-
isSearchCaption = true;
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
if (!isSearchCaption && captionProps.highlighted[captionData.id]) {
|
|
130
|
+
if (isSearchCaption || (!isSearchCaptionInList && captionProps.isHighlighted)) {
|
|
135
131
|
this._currentCaptionRef = node;
|
|
136
132
|
}
|
|
137
133
|
}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {h, Component} from 'preact';
|
|
2
2
|
import {ui, core} from '@playkit-js/kaltura-player-js';
|
|
3
|
-
import {debounce} from '
|
|
3
|
+
import {debounce} from '@playkit-js/common/dist/utils-common';
|
|
4
4
|
import * as styles from './transcript.scss';
|
|
5
5
|
import {Spinner} from '../spinner';
|
|
6
6
|
import {Search} from '../search';
|
|
@@ -23,6 +23,7 @@ const {PLAYER_BREAK_POINTS} = ui.Components;
|
|
|
23
23
|
const {connect} = ui.redux;
|
|
24
24
|
|
|
25
25
|
const SEARCH_EVENT_DISPATCH_TIMEOUT = 2000;
|
|
26
|
+
const WIDGET_RESIZE_DEBOUNCE_TIMEOUT = 250;
|
|
26
27
|
|
|
27
28
|
const translates = {
|
|
28
29
|
skipTranscript: <Text id="transcript.skip_transcript">Skip transcript</Text>,
|
|
@@ -131,12 +132,12 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
|
|
|
131
132
|
if (window.ResizeObserver) {
|
|
132
133
|
// observe transcript root element size changes
|
|
133
134
|
this._resizeObserver = new ResizeObserver(() => {
|
|
134
|
-
this.
|
|
135
|
+
this._debounced.setWidgetSize();
|
|
135
136
|
});
|
|
136
137
|
this._resizeObserver.observe(this._widgetRootRef!);
|
|
137
138
|
} else {
|
|
138
139
|
// use player size to define transcript root element size
|
|
139
|
-
this.
|
|
140
|
+
this._debounced.setWidgetSize();
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
|
|
@@ -155,7 +156,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
|
|
|
155
156
|
|
|
156
157
|
if (!this._resizeObserver && previousProps.playerWidth !== playerWidth) {
|
|
157
158
|
// re-calculate wiget size if player size changed
|
|
158
|
-
this.
|
|
159
|
+
this._debounced.setWidgetSize();
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
|
|
@@ -438,7 +439,6 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
|
|
|
438
439
|
activeSearchIndex={activeSearchIndex}
|
|
439
440
|
captionProps={captionProps}
|
|
440
441
|
onScroll={this._onScroll}
|
|
441
|
-
widgetWidth={this.state.widgetWidth}
|
|
442
442
|
showItemsIcons={true}
|
|
443
443
|
searchActive={false}
|
|
444
444
|
/>
|
|
@@ -505,7 +505,8 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
|
|
|
505
505
|
private _debounced = {
|
|
506
506
|
findSearchMatches: debounce(this._findSearchMatches, this.props.searchDebounceTimeout),
|
|
507
507
|
onActiveSearchIndexChange: debounce(this._setActiveSearchIndex, this.props.searchNextPrevDebounceTimeout),
|
|
508
|
-
searchEventDispatcher: debounce(this._dispatchSearchEvent, SEARCH_EVENT_DISPATCH_TIMEOUT)
|
|
508
|
+
searchEventDispatcher: debounce(this._dispatchSearchEvent, SEARCH_EVENT_DISPATCH_TIMEOUT),
|
|
509
|
+
setWidgetSize: debounce(this._setWidgetSize, WIDGET_RESIZE_DEBOUNCE_TIMEOUT)
|
|
509
510
|
};
|
|
510
511
|
|
|
511
512
|
render(props: TranscriptProps) {
|
package/src/utils/index.ts
CHANGED
package/src/utils/debounce.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
type Procedure = (...args: any[]) => void;
|
|
2
|
-
|
|
3
|
-
type Options = {
|
|
4
|
-
isImmediate: boolean;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export function debounce<F extends Procedure>(
|
|
8
|
-
func: F,
|
|
9
|
-
waitMilliseconds = 50,
|
|
10
|
-
options: Options = {
|
|
11
|
-
isImmediate: false
|
|
12
|
-
}
|
|
13
|
-
): F {
|
|
14
|
-
let timeoutId: any;
|
|
15
|
-
|
|
16
|
-
return function (this: any, ...args: any[]) {
|
|
17
|
-
const doLater = () => {
|
|
18
|
-
timeoutId = undefined;
|
|
19
|
-
if (!options.isImmediate) {
|
|
20
|
-
func.apply(this, args);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const shouldCallNow = options.isImmediate && timeoutId === undefined;
|
|
25
|
-
|
|
26
|
-
if (timeoutId !== undefined) {
|
|
27
|
-
clearTimeout(timeoutId);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
timeoutId = setTimeout(doLater, waitMilliseconds);
|
|
31
|
-
|
|
32
|
-
if (shouldCallNow) {
|
|
33
|
-
func.apply(this, args);
|
|
34
|
-
}
|
|
35
|
-
} as any;
|
|
36
|
-
}
|