Merge pull request #1040 from friday/switches-get-stitches

Switches code optimizations
This commit is contained in:
Sam Potts
2018-06-17 00:39:35 +10:00
committed by GitHub
6 changed files with 125 additions and 246 deletions

57
src/js/controls.js vendored
View File

@ -119,28 +119,17 @@ const controls = {
}, },
// Create hidden text label // Create hidden text label
createLabel(type, attr) { createLabel(type, attr = {}) {
let text = i18n.get(type, this.config); // Skip i18n for abbreviations and brand names
const attributes = Object.assign({}, attr); const universals = {
pip: 'PIP',
airplay: 'AirPlay',
};
switch (type) { const text = universals[type] || i18n.get(type, this.config);
case 'pip': const attributes = Object.assign({}, attr, {
text = 'PIP'; class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),
break; });
case 'airplay':
text = 'AirPlay';
break;
default:
break;
}
if ('class' in attributes) {
attributes.class += ` ${this.config.classNames.hidden}`;
} else {
attributes.class = this.config.classNames.hidden;
}
return createElement('span', attributes, text); return createElement('span', attributes, text);
}, },
@ -342,19 +331,12 @@ const controls = {
if (type !== 'volume') { if (type !== 'volume') {
progress.appendChild(createElement('span', null, '0')); progress.appendChild(createElement('span', null, '0'));
let suffix = ''; const suffixKey = ({
switch (type) { played: 'played',
case 'played': buffer: 'buffered',
suffix = i18n.get('played', this.config); })[type];
break;
case 'buffer': const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';
suffix = i18n.get('buffered', this.config);
break;
default:
break;
}
progress.innerText = `% ${suffix.toLowerCase()}`; progress.innerText = `% ${suffix.toLowerCase()}`;
} }
@ -724,12 +706,9 @@ const controls = {
let value = null; let value = null;
let list = container; let list = container;
switch (setting) { if (setting === 'captions') {
case 'captions':
value = this.currentTrack; value = this.currentTrack;
break; } else {
default:
value = !is.empty(input) ? input : this[setting]; value = !is.empty(input) ? input : this[setting];
// Get default // Get default
@ -748,8 +727,6 @@ const controls = {
this.debug.warn(`Disabled value of '${value}' for ${setting}`); this.debug.warn(`Disabled value of '${value}' for ${setting}`);
return; return;
} }
break;
} }
// Get the list if we need to // Get the list if we need to

View File

@ -46,21 +46,12 @@ const media = {
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
if (this.isEmbed) { if (this.isHTML5) {
switch (this.provider) {
case 'youtube':
youtube.setup.call(this);
break;
case 'vimeo':
vimeo.setup.call(this);
break;
default:
break;
}
} else if (this.isHTML5) {
html5.extend.call(this); html5.extend.call(this);
} else if (this.isYouTube) {
youtube.setup.call(this);
} else if (this.isVimeo) {
vimeo.setup.call(this);
} }
}, },
}; };

View File

@ -200,46 +200,22 @@ const youtube = {
}, },
events: { events: {
onError(event) { onError(event) {
// If we've already fired an error, don't do it again // YouTube may fire onError twice, so only handle it once
// YouTube fires onError twice if (!player.media.error) {
if (is.object(player.media.error)) { const code = event.data;
return;
}
const detail = {
code: event.data,
};
// Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError
switch (event.data) { const message = ({
case 2: 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',
detail.message = 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',
'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.'; 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',
break; 101: 'The owner of the requested video does not allow it to be played in embedded players.',
150: 'The owner of the requested video does not allow it to be played in embedded players.',
}[code]) || 'An unknown error occured';
case 5: player.media.error = { code, message };
detail.message =
'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';
break;
case 100:
detail.message =
'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';
break;
case 101:
case 150:
detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';
break;
default:
detail.message = 'An unknown error occured';
break;
}
player.media.error = detail;
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}
}, },
onPlaybackQualityChange() { onPlaybackQualityChange() {
triggerEvent.call(player, player.media, 'qualitychange', false, { triggerEvent.call(player, player.media, 'qualitychange', false, {

View File

@ -1028,10 +1028,8 @@ class Plyr {
// Stop playback // Stop playback
this.stop(); this.stop();
// Type specific stuff // Provider specific stuff
switch (`${this.provider}:${this.type}`) { if (this.isHTML5) {
case 'html5:video':
case 'html5:audio':
// Clear timeout // Clear timeout
clearTimeout(this.timers.loading); clearTimeout(this.timers.loading);
@ -1040,10 +1038,7 @@ class Plyr {
// Clean up // Clean up
done(); done();
} else if (this.isYouTube) {
break;
case 'youtube:video':
// Clear timers // Clear timers
clearInterval(this.timers.buffering); clearInterval(this.timers.buffering);
clearInterval(this.timers.playing); clearInterval(this.timers.playing);
@ -1055,10 +1050,7 @@ class Plyr {
// Clean up // Clean up
done(); done();
} else if (this.isVimeo) {
break;
case 'vimeo:video':
// Destroy Vimeo API // Destroy Vimeo API
// then clean up (wait, to prevent postmessage errors) // then clean up (wait, to prevent postmessage errors)
if (this.embed !== null) { if (this.embed !== null) {
@ -1067,11 +1059,6 @@ class Plyr {
// Vimeo does not always return // Vimeo does not always return
setTimeout(done, 200); setTimeout(done, 200);
break;
default:
break;
} }
} }

View File

@ -8,6 +8,7 @@ import media from './media';
import support from './support'; import support from './support';
import ui from './ui'; import ui from './ui';
import { createElement, insertElement, removeElement } from './utils/elements'; import { createElement, insertElement, removeElement } from './utils/elements';
import { getDeep } from './utils/objects';
import is from './utils/is'; import is from './utils/is';
const source = { const source = {
@ -27,7 +28,7 @@ const source = {
// Update source // Update source
// Sources are not checked for support so be careful // Sources are not checked for support so be careful
change(input) { change(input) {
if (!is.object(input) || !('sources' in input) || !input.sources.length) { if (!getDeep(input, 'sources.length')) {
this.debug.warn('Invalid source format'); this.debug.warn('Invalid source format');
return; return;
} }
@ -52,32 +53,19 @@ const source = {
} }
// Set the type and provider // Set the type and provider
this.type = input.type; const { sources, type } = input;
this.provider = !is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5; const [{ provider = providers.html5, src }] = sources;
const tagName = provider === 'html5' ? type : 'div';
const attributes = provider === 'html5' ? {} : { src };
Object.assign(this, {
provider,
type,
// Check for support // Check for support
this.supported = support.check(this.type, this.provider, this.config.playsinline); supported: support.check(type, provider, this.config.playsinline),
// Create new element
// Create new markup media: createElement(tagName, attributes),
switch (`${this.provider}:${this.type}`) {
case 'html5:video':
this.media = createElement('video');
break;
case 'html5:audio':
this.media = createElement('audio');
break;
case 'youtube:video':
case 'vimeo:video':
this.media = createElement('div', {
src: input.sources[0].src,
}); });
break;
default:
break;
}
// Inject the new element // Inject the new element
this.elements.container.appendChild(this.media); this.elements.container.appendChild(this.media);
@ -114,7 +102,7 @@ const source = {
// Set new sources for html5 // Set new sources for html5
if (this.isHTML5) { if (this.isHTML5) {
source.insertElements.call(this, 'source', input.sources); source.insertElements.call(this, 'source', sources);
} }
// Set video title // Set video title

View File

@ -7,6 +7,15 @@ import browser from './utils/browser';
import { createElement } from './utils/elements'; import { createElement } from './utils/elements';
import is from './utils/is'; import is from './utils/is';
// Default codecs for checking mimetype support
const defaultCodecs = {
'audio/ogg': 'vorbis',
'audio/wav': '1',
'video/webm': 'vp8, vorbis',
'video/mp4': 'avc1.42E01E, mp4a.40.2',
'video/ogg': 'theora',
};
// Check for feature support // Check for feature support
const support = { const support = {
// Basic support // Basic support
@ -16,31 +25,9 @@ const support = {
// Check for support // Check for support
// Basic functionality vs full UI // Basic functionality vs full UI
check(type, provider, playsinline) { check(type, provider, playsinline) {
let api = false;
let ui = false;
const canPlayInline = browser.isIPhone && playsinline && support.playsinline; const canPlayInline = browser.isIPhone && playsinline && support.playsinline;
const api = support[type] || provider !== 'html5';
switch (`${provider}:${type}`) { const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);
case 'html5:video':
api = support.video;
ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);
break;
case 'html5:audio':
api = support.audio;
ui = api && support.rangeInput;
break;
case 'youtube:video':
case 'vimeo:video':
api = true;
ui = support.rangeInput && (!browser.isIPhone || canPlayInline);
break;
default:
api = support.audio && support.video;
ui = api && support.rangeInput;
}
return { return {
api, api,
@ -63,56 +50,29 @@ const support = {
// Check for mime type support against a player instance // Check for mime type support against a player instance
// Credits: http://diveintohtml5.info/everything.html // Credits: http://diveintohtml5.info/everything.html
// Related: http://www.leanbackplayer.com/test/h5mt.html // Related: http://www.leanbackplayer.com/test/h5mt.html
mime(type) { mime(inputType) {
const { media } = this; const [mediaType] = inputType.split('/');
if (!this.isHTML5 || mediaType !== this.type) {
return false;
}
let type;
if (inputType && inputType.includes('codecs=')) {
// Use input directly
type = inputType;
} else if (inputType === 'audio/mpeg') {
// Skip codec
type = 'audio/mpeg;';
} else if (inputType in defaultCodecs) {
// Use codec
type = `${inputType}; codecs="${defaultCodecs[inputType]}"`;
}
try { try {
// Bail if no checking function return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));
if (!this.isHTML5 || !is.function(media.canPlayType)) { } catch (err) {
return false; return false;
} }
// Check directly if codecs specified
if (type.includes('codecs=')) {
return media.canPlayType(type).replace(/no/, '');
}
// Type specific checks
if (this.isVideo) {
switch (type) {
case 'video/webm':
return media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, '');
case 'video/mp4':
return media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '');
case 'video/ogg':
return media.canPlayType('video/ogg; codecs="theora"').replace(/no/, '');
default:
return false;
}
} else if (this.isAudio) {
switch (type) {
case 'audio/mpeg':
return media.canPlayType('audio/mpeg;').replace(/no/, '');
case 'audio/ogg':
return media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '');
case 'audio/wav':
return media.canPlayType('audio/wav; codecs="1"').replace(/no/, '');
default:
return false;
}
}
} catch (e) {
return false;
}
// If we got this far, we're stuffed
return false;
}, },
// Check for textTracks support // Check for textTracks support