Skip to content

Commit 424d021

Browse files
alex-barstowgkatsev
authored andcommitted
fix: tracks are disabled and cuepoints are cleared in iOS native player (#4569)
In the HTML5 tech, when we go fullscreen to the native player, listen for change events and restore previous mode state for the metadata text tracks. This is 5.x version of #4496.
1 parent 935ec1e commit 424d021

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

src/js/tech/html5.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ class Html5 extends Tech {
131131
this.proxyNativeTextTracks_();
132132
}
133133

134+
// prevent iOS Safari from disabling metadata text tracks during native playback
135+
this.restoreMetadataTracksInIOSNativePlayer_();
136+
134137
// Determine if native controls should be used
135138
// Our goal should be to get the custom controls on mobile solid everywhere
136139
// so we can remove this all together. Right now this will block custom
@@ -173,6 +176,72 @@ class Html5 extends Tech {
173176
super.dispose();
174177
}
175178

179+
/**
180+
* When a captions track is enabled in the iOS Safari native player, all other
181+
* tracks are disabled (including metadata tracks), which nulls all of their
182+
* associated cue points. This will restore metadata tracks to their pre-fullscreen
183+
* state in those cases so that cue points are not needlessly lost.
184+
*
185+
* @private
186+
*/
187+
restoreMetadataTracksInIOSNativePlayer_() {
188+
const textTracks = this.textTracks();
189+
let metadataTracksPreFullscreenState;
190+
191+
// captures a snapshot of every metadata track's current state
192+
const takeMetadataTrackSnapshot = () => {
193+
metadataTracksPreFullscreenState = [];
194+
195+
for (let i = 0; i < textTracks.length; i++) {
196+
const track = textTracks[i];
197+
198+
if (track.kind === 'metadata') {
199+
metadataTracksPreFullscreenState.push({
200+
track,
201+
storedMode: track.mode
202+
});
203+
}
204+
}
205+
};
206+
207+
// snapshot each metadata track's initial state, and update the snapshot
208+
// each time there is a track 'change' event
209+
takeMetadataTrackSnapshot();
210+
textTracks.addEventListener('change', takeMetadataTrackSnapshot);
211+
212+
const restoreTrackMode = () => {
213+
for (let i = 0; i < metadataTracksPreFullscreenState.length; i++) {
214+
const storedTrack = metadataTracksPreFullscreenState[i];
215+
216+
if (storedTrack.track.mode === 'disabled' && storedTrack.track.mode !== storedTrack.storedMode) {
217+
storedTrack.track.mode = storedTrack.storedMode;
218+
}
219+
}
220+
// we only want this handler to be executed on the first 'change' event
221+
textTracks.removeEventListener('change', restoreTrackMode);
222+
};
223+
224+
// when we enter fullscreen playback, stop updating the snapshot and
225+
// restore all track modes to their pre-fullscreen state
226+
this.on('webkitbeginfullscreen', () => {
227+
textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
228+
229+
// remove the listener before adding it just in case it wasn't previously removed
230+
textTracks.removeEventListener('change', restoreTrackMode);
231+
textTracks.addEventListener('change', restoreTrackMode);
232+
});
233+
234+
// start updating the snapshot again after leaving fullscreen
235+
this.on('webkitendfullscreen', () => {
236+
// remove the listener before adding it just in case it wasn't previously removed
237+
textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
238+
textTracks.addEventListener('change', takeMetadataTrackSnapshot);
239+
240+
// remove the restoreTrackMode handler in case it wasn't triggered during fullscreen playback
241+
textTracks.removeEventListener('change', restoreTrackMode);
242+
});
243+
}
244+
176245
/**
177246
* Create the `Html5` Tech's DOM element.
178247
*

0 commit comments

Comments
 (0)