diff --git a/dashboard-ui/bower_components/emby-apiclient/.bower.json b/dashboard-ui/bower_components/emby-apiclient/.bower.json index 3dad57dd05..6882b33b03 100644 --- a/dashboard-ui/bower_components/emby-apiclient/.bower.json +++ b/dashboard-ui/bower_components/emby-apiclient/.bower.json @@ -16,12 +16,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.0.17", - "_release": "1.0.17", + "version": "1.0.19", + "_release": "1.0.19", "_resolution": { "type": "version", - "tag": "1.0.17", - "commit": "3ce9bb842c3188d3440aef5319b01a24e57603cb" + "tag": "1.0.19", + "commit": "09f50cd4f4b126b0ea9a0a26c1b425b4a1e25f5b" }, "_source": "git://github.com/MediaBrowser/Emby.ApiClient.Javascript.git", "_target": "~1.0.3", diff --git a/dashboard-ui/bower_components/emby-apiclient/apiclient.js b/dashboard-ui/bower_components/emby-apiclient/apiclient.js index 93f9461206..7ff829da1c 100644 --- a/dashboard-ui/bower_components/emby-apiclient/apiclient.js +++ b/dashboard-ui/bower_components/emby-apiclient/apiclient.js @@ -187,7 +187,8 @@ var fetchRequest = { headers: headers, - method: request.type + method: request.type, + credentials: 'same-origin' }; var contentType = request.contentType; @@ -221,6 +222,9 @@ var timeout = setTimeout(reject, timeoutMs); + options = options || {}; + options.credentials = 'same-origin'; + fetch(url, options).then(function (response) { clearTimeout(timeout); resolve(response); diff --git a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js index b8e686a6be..358a9f0b9d 100644 --- a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js +++ b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js @@ -88,7 +88,8 @@ var fetchRequest = { headers: headers, - method: request.type + method: request.type, + credentials: 'same-origin' }; var contentType = request.contentType; @@ -124,6 +125,9 @@ var timeout = setTimeout(reject, timeoutMs); + options = options || {}; + options.credentials = 'same-origin'; + fetch(url, options).then(function (response) { clearTimeout(timeout); diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json index edfd95b985..d62e0f8ed6 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json @@ -10,19 +10,19 @@ "license": "https://github.com/MediaBrowser/emby-webcomponents/blob/master/LICENSE", "homepage": "https://github.com/MediaBrowser/emby-webcomponents", "dependencies": { - "requirejs": "requirejs#^2.1.22" + "requirejs": "requirejs#^2.1.22", + "isMobile": "isMobile#^0.3.9" }, "devDependencies": {}, "ignore": [], - "version": "1.0.0", - "_release": "1.0.0", + "version": "1.0.2", + "_release": "1.0.2", "_resolution": { "type": "version", - "tag": "1.0.0", - "commit": "e5ea8f8503ae36e45609e77aae4ecae170cb5dea" + "tag": "1.0.2", + "commit": "a4909b1637879d7e52ce9eaba8247ad98b690de9" }, "_source": "git://github.com/MediaBrowser/emby-webcomponents.git", "_target": "~1.0.0", - "_originalSource": "emby-webcomponents", - "_direct": true + "_originalSource": "emby-webcomponents" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/bower.json b/dashboard-ui/bower_components/emby-webcomponents/bower.json index b31e2944df..0a6c6d4d1d 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/bower.json @@ -10,7 +10,8 @@ "license": "https://github.com/MediaBrowser/emby-webcomponents/blob/master/LICENSE", "homepage": "https://github.com/MediaBrowser/emby-webcomponents", "dependencies": { - "requirejs": "requirejs#^2.1.22" + "requirejs": "requirejs#^2.1.22", + "isMobile": "isMobile#^0.3.9" }, "devDependencies": { diff --git a/dashboard-ui/bower_components/emby-webcomponents/browser.js b/dashboard-ui/bower_components/emby-webcomponents/browser.js new file mode 100644 index 0000000000..cc4cef38d2 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/browser.js @@ -0,0 +1,66 @@ +define(['isMobile'], function (isMobile) { + + var uaMatch = function (ua) { + ua = ua.toLowerCase(); + + var match = /(edge)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(opr)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(safari)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + var platform_match = /(ipad)/.exec(ua) || + /(iphone)/.exec(ua) || + /(android)/.exec(ua) || + []; + + var browser = match[1] || ""; + + if (ua.indexOf("windows phone") != -1 || ua.indexOf("iemobile") != -1) { + + // http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update + browser = "msie"; + } + else if (ua.indexOf("like gecko") != -1 && ua.indexOf('webkit') == -1 && ua.indexOf('opera') == -1 && ua.indexOf('chrome') == -1 && ua.indexOf('safari') == -1) { + browser = "msie"; + } + + if (browser == 'opr') { + browser = 'opera'; + } + + return { + browser: browser, + version: match[2] || "0", + platform: platform_match[0] || "" + }; + }; + + var userAgent = window.navigator.userAgent; + var matched = uaMatch(userAgent); + var browser = {}; + + if (matched.browser) { + browser[matched.browser] = true; + browser.version = matched.version; + } + + if (matched.platform) { + browser[matched.platform] = true; + } + + if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") != -1) { + browser.safari = true; + } + + if (isMobile.any) { + browser.mobile = true; + } + + browser.animate = document.documentElement.animate != null; + + return browser; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js new file mode 100644 index 0000000000..17ab704e3d --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js @@ -0,0 +1,333 @@ +define(['browser'], function (browser) { + + var supportedFormats; + function getSupportedFormats() { + + if (supportedFormats) { + return supportedFormats; + } + + var list = []; + var elem = document.createElement('video'); + + if (elem.canPlayType('video/webm').replace(/no/, '')) { + list.push('webm'); + } + if (elem.canPlayType('audio/mp4; codecs="ac-3"').replace(/no/, '')) { + list.push('ac3'); + } + if (browser.chrome) { + list.push('mkv'); + } + + var canPlayH264 = true; + var userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.indexOf('firefox') != -1 && userAgent.indexOf('windows') == -1) { + canPlayH264 = false; + } + + if (canPlayH264) { + list.push('h264'); + } + + if (document.createElement('audio').canPlayType('audio/aac').replace(/no/, '')) { + list.push('aac'); + } + + if (document.createElement('audio').canPlayType('audio/mp3').replace(/no/, '')) { + list.push('mp3'); + } + if (document.createElement('audio').canPlayType('audio/ogg; codecs="opus"').replace(/no/, '')) { + list.push('opus'); + } + + if (document.createElement('audio').canPlayType('audio/webm').replace(/no/, '')) { + list.push('webma'); + } + + if (document.createElement('audio').canPlayType('audio/flac').replace(/no/, '')) { + list.push('flac'); + } + + supportedFormats = list; + return list; + } + + var _supportsTextTracks; + function supportsTextTracks() { + + if (_supportsTextTracks == null) { + _supportsTextTracks = document.createElement('video').textTracks != null; + } + + // For now, until ready + return _supportsTextTracks; + } + + var _canPlayHls; + function canPlayHls(src) { + + if (_canPlayHls == null) { + _canPlayHls = window.MediaSource != null || canPlayNativeHls(); + } + return _canPlayHls; + } + + function canPlayNativeHls() { + var media = document.createElement('video'); + + if (media.canPlayType('application/x-mpegURL').replace(/no/, '') || + media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')) { + return true; + } + + return false; + } + + return function () { + + var bitrateSetting = 100000000; + + var supportedFormats = getSupportedFormats(); + + var canPlayWebm = supportedFormats.indexOf('webm') != -1; + var canPlayAc3 = supportedFormats.indexOf('ac3') != -1; + var canPlayMp3 = supportedFormats.indexOf('mp3') != -1; + var canPlayAac = supportedFormats.indexOf('aac') != -1; + var canPlayMkv = supportedFormats.indexOf('mkv') != -1; + + var profile = {}; + + profile.MaxStreamingBitrate = bitrateSetting; + profile.MaxStaticBitrate = 100000000; + profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 192000); + + profile.DirectPlayProfiles = []; + + if (supportedFormats.indexOf('h264') != -1) { + profile.DirectPlayProfiles.push({ + Container: 'mp4,m4v', + Type: 'Video', + VideoCodec: 'h264', + AudioCodec: 'aac' + (canPlayMp3 ? ',mp3' : '') + (canPlayAc3 ? ',ac3' : '') + }); + } + + if (browser.chrome) { + profile.DirectPlayProfiles.push({ + Container: 'mkv,mov', + Type: 'Video', + VideoCodec: 'h264', + AudioCodec: 'aac' + (canPlayMp3 ? ',mp3' : '') + (canPlayAc3 ? ',ac3' : '') + }); + } + + ['opus', 'mp3', 'aac', 'flac', 'webma'].forEach(function (audioFormat) { + + if (supportedFormats.indexOf(audioFormat) != -1) { + profile.DirectPlayProfiles.push({ + Container: audioFormat == 'webma' ? 'webma,webm' : audioFormat, + Type: 'Audio' + }); + } + }); + + if (canPlayWebm) { + profile.DirectPlayProfiles.push({ + Container: 'webm', + Type: 'Video' + }); + } + + profile.TranscodingProfiles = []; + + ['opus', 'mp3', 'aac'].forEach(function (audioFormat) { + + if (supportedFormats.indexOf(audioFormat) != -1) { + profile.TranscodingProfiles.push({ + Container: audioFormat, + Type: 'Audio', + AudioCodec: audioFormat, + Context: 'Streaming', + Protocol: 'http' + }); + profile.TranscodingProfiles.push({ + Container: audioFormat, + Type: 'Audio', + AudioCodec: audioFormat, + Context: 'Static', + Protocol: 'http' + }); + } + }); + + // Can't use mkv on mobile because we have to use the native player controls and they won't be able to seek it + if (canPlayMkv && !browser.mobile) { + profile.TranscodingProfiles.push({ + Container: 'mkv', + Type: 'Video', + AudioCodec: 'aac' + (canPlayAc3 ? ',ac3' : ''), + VideoCodec: 'h264', + Context: 'Streaming' + }); + } + + if (canPlayHls()) { + profile.TranscodingProfiles.push({ + Container: 'ts', + Type: 'Video', + AudioCodec: 'aac' + (canPlayAc3 ? ',ac3' : ''), + VideoCodec: 'h264', + Context: 'Streaming', + Protocol: 'hls' + }); + } + + if (canPlayWebm) { + + profile.TranscodingProfiles.push({ + Container: 'webm', + Type: 'Video', + AudioCodec: 'vorbis', + VideoCodec: 'vpx', + Context: 'Streaming', + Protocol: 'http' + }); + } + + profile.TranscodingProfiles.push({ + Container: 'mp4', + Type: 'Video', + AudioCodec: 'aac', + VideoCodec: 'h264', + Context: 'Streaming', + Protocol: 'http' + }); + + profile.TranscodingProfiles.push({ + Container: 'mp4', + Type: 'Video', + AudioCodec: 'aac', + VideoCodec: 'h264', + Context: 'Static', + Protocol: 'http' + }); + + profile.ContainerProfiles = []; + + profile.CodecProfiles = []; + profile.CodecProfiles.push({ + Type: 'Audio', + Conditions: [{ + Condition: 'LessThanEqual', + Property: 'AudioChannels', + Value: '2' + }] + }); + + profile.CodecProfiles.push({ + Type: 'VideoAudio', + Codec: 'aac', + Container: 'mkv,mov', + Conditions: [ + { + Condition: 'NotEquals', + Property: 'AudioProfile', + Value: 'HE-AAC' + } + // Disabling this is going to require us to learn why it was disabled in the first place + //, + //{ + // Condition: 'NotEquals', + // Property: 'AudioProfile', + // Value: 'LC' + //} + ] + }); + + profile.CodecProfiles.push({ + Type: 'VideoAudio', + Codec: 'aac,mp3', + Conditions: [ + { + Condition: 'LessThanEqual', + Property: 'AudioChannels', + Value: '6' + } + ] + }); + + profile.CodecProfiles.push({ + Type: 'VideoAudio', + Conditions: [ + { + Condition: 'Equals', + Property: 'IsSecondaryAudio', + Value: 'false', + IsRequired: 'false' + } + ] + }); + + profile.CodecProfiles.push({ + Type: 'Video', + Codec: 'h264', + Conditions: [ + { + Condition: 'NotEquals', + Property: 'IsAnamorphic', + Value: 'true', + IsRequired: false + }, + { + Condition: 'EqualsAny', + Property: 'VideoProfile', + Value: 'high|main|baseline|constrained baseline' + }, + { + Condition: 'LessThanEqual', + Property: 'VideoLevel', + Value: '41' + }] + }); + + profile.CodecProfiles.push({ + Type: 'Video', + Codec: 'vpx', + Conditions: [ + { + Condition: 'NotEquals', + Property: 'IsAnamorphic', + Value: 'true', + IsRequired: false + }] + }); + + // Subtitle profiles + // External vtt or burn in + profile.SubtitleProfiles = []; + if (supportsTextTracks()) { + + profile.SubtitleProfiles.push({ + Format: 'vtt', + Method: 'External' + }); + } + + profile.ResponseProfiles = []; + + profile.ResponseProfiles.push({ + Type: 'Video', + Container: 'm4v', + MimeType: 'video/mp4' + }); + + profile.ResponseProfiles.push({ + Type: 'Video', + Container: 'mov', + MimeType: 'video/webm' + }); + + return profile; + }(); +}); \ No newline at end of file diff --git a/dashboard-ui/components/requirecss.js b/dashboard-ui/bower_components/emby-webcomponents/requirecss.js similarity index 89% rename from dashboard-ui/components/requirecss.js rename to dashboard-ui/bower_components/emby-webcomponents/requirecss.js index 603326d340..96752bd015 100644 --- a/dashboard-ui/components/requirecss.js +++ b/dashboard-ui/bower_components/emby-webcomponents/requirecss.js @@ -26,17 +26,17 @@ define(function () { requireCss.load = function (cssId, req, load, config) { // Somehow if the url starts with /css, require will get all screwed up since this extension is also called css - cssId = cssId.replace('components/requirecss', 'css'); + var srch = '/emby-webcomponents/requirecss'; + var index = cssId.indexOf(srch); + + if (index != -1) { + cssId = 'css' + cssId.substring(index + srch.length); + } + var url = cssId + '.css'; var packageName = ''; - // TODO: handle any value before the # - if (url.indexOf('theme#') != -1) { - url = url.replace('theme#', ''); - packageName = 'theme'; - } - if (url.indexOf('http') != 0 && url.indexOf('file:') != 0) { url = config.baseUrl + url; } diff --git a/dashboard-ui/bower_components/emby-webcomponents/requirehtml.js b/dashboard-ui/bower_components/emby-webcomponents/requirehtml.js index 5c483087da..1764812234 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/requirehtml.js +++ b/dashboard-ui/bower_components/emby-webcomponents/requirehtml.js @@ -1,46 +1,46 @@ define(function () { - var cssAPI = {}; - - cssAPI.normalize = function (name, normalize) { - if (name.substr(name.length - 5, 5) == '.html') - name = name.substr(0, name.length - 5); - - return normalize(name); - } var importedFiles = []; - cssAPI.load = function (cssId, req, load, config) { + return { - // Somehow if the url starts with /css, require will get all screwed up since this extension is also called css - cssId = cssId.replace('js/requirehtml', 'html'); + load: function (cssId, req, load, config) { - var url = cssId + '.html'; + // Somehow if the url starts with /html, require will get all screwed up since this extension is also called html + cssId = cssId.replace('js/requirehtml', 'html'); - if (url.indexOf('http') != 0 && url.indexOf('file:') != 0) { - url = config.baseUrl + url; - } + var url = cssId + '.html'; - if (importedFiles.indexOf(url) == -1) { - importedFiles.push(url); - - var link = document.createElement('link'); - link.rel = 'import'; - - if (url.toLowerCase().indexOf('bower_') == -1) { - url = url + "?" + config.urlArgs; + if (url.indexOf('http') != 0 && url.indexOf('file:') != 0) { + url = config.baseUrl + url; } - link.onload = load; - link.href = url; + if (importedFiles.indexOf(url) == -1) { + importedFiles.push(url); - document.head.appendChild(link); + var link = document.createElement('link'); + link.rel = 'import'; - return; + if (url.toLowerCase().indexOf('bower_') == -1) { + url = url + "?" + config.urlArgs; + } + + link.onload = load; + link.href = url; + + document.head.appendChild(link); + + return; + } + + load(); + }, + + normalize: function (name, normalize) { + if (name.substr(name.length - 5, 5) == '.html') + name = name.substr(0, name.length - 5); + + return normalize(name); } - - load(); - } - - return cssAPI; + }; }); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index d549eec598..4101e4d1ae 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1835,7 +1835,7 @@ var AppInfo = {}; requirejs.config({ map: { '*': { - 'css': 'components/requirecss', + 'css': bowerPath + '/emby-webcomponents/requirecss', 'html': bowerPath + '/emby-webcomponents/requirehtml' } },